Skip to content

Highly customizable, dependency-free, universal, service abstraction around Google Optimize.

License

Notifications You must be signed in to change notification settings

haensl/google-optimize-service

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

google-optimize-service

NPM

npm version

CircleCI

Highly customizable, lightweight, universal, service abstraction around Google Optimize.

google-optimize-service provides a lightweight abstraction layer around Google Optimize. It enables easy access to and management of experiment information.

Table of Contents

Quick Start

1. Install google-optimize-service

via npm:

npm i -S google-optimize-service

via yarn:

yarn add google-optimize-service

2. Import and use the service

ESM

import optimize from 'google-optimize-service';
optimize.preventFlicker();

const experiment = optmize.get();
/**
 * Assuming the query parameters set by Google Optimize:
 * ?utm_expid=69&utm_referrer=&variant=doggy
 *
 * experiment := {
 *   experimentId: '69', // google optimize experiment id, i.e. utm_expid
 *   referrer: '', // google optimize referrer, i.e. utm_referrer
 *   variant: 'doggy' // custom set experiment variable
 * }
 */

CommonJS

const optimize = require('google-optimize-service');

const experiment = optimize.get();
/**
 * Assuming the query parameters set by Google Optimize:
 * ?utm_expid=69&utm_referrer=&variant=doggy
 *
 * experiment := {
 *   experimentId: '69', // google optimize experiment id, i.e. utm_expid
 *   referrer: '', // google optimize referrer, i.e. utm_referrer
 *   variant: 'doggy' // custom set experiment variable
 * }
 */

Features

google-optimize-service is a highly customizable abstraction layer for Google Optimize. As such it features:

Autodiscovery of the environment.

If run in a browser, google-optimize-service will automatically find the query parameters and check for available storage APIs to persist experiment data. If you're working in a non-browser environment, however, you can tell google-optimize-service where to find URL query parameters and how to persist experiment data.

Custom fields carrying your experiment variables.

By default google-optimize-service is setup to extract a variant from the URL. If your experiment, however, requires a more complex setup, e.g. with multiple or differently named experiment variables, you can tell google-optimize-service which query parameters belong to your experiment.

Auto-persistance of experiment data.

To ensure your users will always see the same variant of your application, google-optimize-service by default automatically persists experiment data. Of course you can prevent persistance or employ your own storage strategies as you see fit.

Flicker prevention: anti-flicker snippet.

No need to manually add the anti-flicker snippet to your page, google-optimize-service's got you covered.

Supports multiple experiments.

By employing persistance and discovery strategies, google-optimize-service facilitates work in an agile environment where change is frequent and/or multiple Optimize experiments run in parallel. This can help reduce the amount of work necessary to refactor experiment implementations.

Universal.

Whether you work on a ESM powered SPA or in a CommonJS powered Node.js project google-optimize-service has your back. It works with any modern JavaScript source base.

Lightweight.

google-optimize-service is implemented in a resource preserving manner and introduces minimal additional production dependencies.

Customization

google-optimize-service can be adjusted to your needs via a multitude of settings documented in the API section.

This is what it's default configuration looks like:

{
  autopersist: true, // customize via autopersist().
  fields: [ // customize via fields().
    'variant'
  ],
  key: 'optimize', // customize via key().
  location: { // customize via location(). location is subject to autodiscovery.
    search: ''
  },
  storage: null, // customize via storage(). storage is subject to autodiscovery.
  storagePreference: storagePreferences.localStorage // customize via storagePreference().
}

All configuration is customizable:

API

autopersist([shouldPersist])

default: true

Configure whether or not to automatically persist experiment data to storage. If set to true, optimize will persist experiments found in the query with every call to get().

If called without parameter, autopersist() returns the current autopersist setting.

Arguments

shouldPersist optional - a boolean indicating whether or not to persist experiment data to storage.

Example

const optimize = require('google-optimize-service');

optimize.autopersist(true);
const experiment = optimize.get();

// experiment will be persisted to storage

configure(options)

Wraps all configuration options into a convenient abstraction.

Arguments

options - a map containing configuration options. Valid, available configuration options are:

Example

const optimize = require('google-optimize-service');

optimize.configure({
  autopersist: true,
  fields: [
    'variant',
    'subvariant'
  ],
  key: 'my-app',
  storagePreference: optimize.storagePreferences.sessionStorage
});
const experiment = optimize.get();

currentExperimentId()

Returns the utm_expid of the current, i.e. as set in the URL query parameters, experiment.

Example

const optimize = require('google-optimize-service');

const currentExperimentId = optimize.currentExperimentId();

discover()

Autodiscovers configuration for the current environment. When calling discover(), google-optimize-service performs checks to see if a window object with location (and search) is available to retrieve experiment information from. Furthermore, session- and localStorage are checked and set as storage engines if available. Discover is automatically invoked upon first importing the google-optimize-service. Use storagePreference to indicate whether you prefer session- or localStorage for your application.

Example

const optimize = require('google-optimize-service');

optimize.discover();
const experiment = optimize.get();

fields([newFields])

default: [ 'variant' ]

Set custom fields to retrieve from the URL query when parsing experiment data.

If called without parameter, fields() returns the current fields setting.

Arguments

fields optional - an Array of strings representing the name of query parameters that should be added to the experiment data.

Example

const optimize = require('google-optimize-service');

optimize.fields([
  'variant',
  'subvariant'
]);
const experiment = optimize.get();

/**
 * experiment now contains properties variant and subvariant, if they are set in the query string.
 */
switch (experiment.variant) {
  case 'A':
    switch (experiment.subvariant) {
      case 1:
        // add code for variant A.1
        break;
    }
}

fromQuery()

Returns experiment data from the URL query. Disregards persisted experiment information.

Example

const optimize = require('google-optimize-service');

const experiment = optimize.fromQuery();

get([experimentId])

get() is your main entrypoint to experiment data. It consolidates stored experiment data with experiment data in the URL query, whereby stored data superseeds URL data. If not not provided experimentId defaults to the currentExperimentId. If there is experiment data in the URL query that is not persisted, yet, it is merged into the dataset. If autopersist is set to true, consolidated experiment data is persisted to storage. If no experimentId is provided and there is no currentExperimentId (or the parameter is deliberately set to null or undefined), a map of all experiments is returned. The map is keyed by experimentId.

Arguments

experimentId optional - the id of the experiment to retrieve. Defaults to the return value of currentExperimentId(). If not available or set to null or undefined, a map of all available experiments is returned.

Example

const optimize = require('google-optimize-service');

const experiment = optimize.get();
// experiment is the current experiment

const someOtherExperiment = optimize.get(someOtherExperimentId);
// someOtherExperiment contains information about experiment with id someOtherExperimentId

key([newKey])

default: 'optimize'

Sets the key used when persisting experiment information to storage.

If called without parameter, returns the current key.

Arguments

newKey optional - if provided newKey is set as the key to use when persisting experiment information.

Example

const optimize = require('google-optimize-service');

optimize.key('my-optimize-experiments')
const experiment = optimize.get();

// experiment data is fetched from and persisted to the key 'my-optimize-experiments'.

location([newLocation])

Sets the location object to use to retrieve search/query data from.

If called without parameter, returns the current location.

By default, google-optimize-service tries to discover if it is run in a browser and defaults to window.location if available. If you are working on the server-side, however, you may wish provide a different location object to parse experiment data from.

Arguments

newLocation optional - must be an object with a property search, e.g. { search: '?utm_expid=69&variant=naughty' }, from which to parse experiment information.

Example

Use with Koa

const optimize = require('google-optimize-service');
const Router = require('koa-router');

const router = Router();

router.get('/', async (ctx) => {
  optimize.location({
    search: ctx.request.search
  });

  const experiment = optimize.get();
  // experiment data is parsed from ctx.request.search.
});

Use with Express

const optimize = require('google-optimize-service');
const express = require('express');

const app = express();

app.get('/', (req, res) => {
  optimize.location({
    search: req.originalUrl.slice(req.originalUrl.indexOf('?'))
  });

  const experiment = optimize.get();
  // experiment data is parsed from the original URL's query string.
});

persist([experiments])

Persists experiment data to storage at key. If not provided as parameter, persist() tries to persist experiments returned by get(). If no storage is configured, this is a noop.

Arguments

experiments optional - The experiments to persist to storage. If not provided, persist() tries to retrieve experiment data from get().

Example

const optimize = require('google-optimize-service');

const experiments = optimize.get(null);
optimize.persist(experiments);

preventFlicker([timeout],[intervalMs])

Installs the anti-flicker snippet.

Arguments

timeout optional - Timeout to wait for Google Analytics in milliseconds. Default: 2000.

intervalMs optional - Interval in which to check for Google Analytics in milliseconds. Default: 10.

Example

const optimize = require('google-optimize-service');

optimize.preventFlicker();

storage([newStorage])

Sets and returns the storage implementation to use.

If called without parameter, it returns the currently set storage engine.

By default google-optimize-service tries to discover available storage mechanisms and configures itself accoringly. E.g. if run in a browser, google-optimize-service can discover that both localStorage and sessionStorage are available on the window object. Depending on the set storagePreference, it configures itself to use one of those when discover()ing.

Supplying your own storage engine to use for persist()ing experiments, can come handy when working in non-browser environments. See the examples section for illustration.

Arguments

newStorage optional - A storage engine to use when persist()ing experiment data. newStorage can be any custom storage solution implementing at least a minimum set of setItem() and getItem() from the web storage API.

Example

Explicitly using sessionStorage

const optimize = require('google-optimize-service');

optimize.storage(window.sessionStorage);
optimize.persist(optimize.get(null));

Using a custom storage engine

const optimize = require('google-optimize-service');

const store = {};

optimize.storage({
  setItem: (key, value) => {
    store[key] = value;
  },
  getItem: (key) => store[key]
});

optimize.persist(optimize.get(null));

storagePreference([newPreference])

Sets the storage preference to use when deciding between local- and sessionStorage during discover().

If called without parameter, returns the current storage preference.

Arguments

newPreference optional - The storage preference to use. This should be one of the constants provided via storagePreferences.

Example

const optimize = require('google-optimize-service');

optimize.storagePreference(optimize.storagePreferences.sessionStorage);
optimize.discover();
optimize.persist(optimize.get(null));

storagePreferences

Map of available storage preferences to be used with storagePreference().

Currently available storage preferences:

storagePreferences.localStorage prefers localStorage over sessionStorage.

storagePreferences.sessionStorage prefers sessionStorage over localStorage.

storagePreferences constitute only a hint. I.e. if the storage preference is set to sessionStorage but only localStorage is available, google-optimize-service will pick localStorage.

The MIT License (MIT)

Copyright (c) Hans-Peter Dietz @h_p_d | [email protected]

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

About

Highly customizable, dependency-free, universal, service abstraction around Google Optimize.

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published