google-optimize-service
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();
CommonJS
const optimize = require('google-optimize-service');
const experiment = optimize.get();
Features
google-optimize-service
is a highly customizable abstraction layer for Google Optimize. As such it features:
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.
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.
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,
fields: [
'variant'
],
key: 'optimize',
location: {
search: ''
},
storage: null,
storagePreference: storagePreferences.localStorage
}
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();
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();
switch (experiment.variant) {
case 'A':
switch (experiment.subvariant) {
case 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();
const someOtherExperiment = optimize.get(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();
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();
});
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();
});
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 | h.p.dietz@gmail.com
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.