You can send Javascript impressions and events to Google Analytics and send Google analytics hit data to Split as events. With this integration you can use the event data you already collect via Google Analytics to power analytics and experimentation within Split.
Language Support
This integration works with the Universal Analytics (analytics.js) library, whether it's set up with the classic Google Analytics tag, a tag manager like Google Tag Manager, or Global Site Tags (gtag.js). It doesn't support the new Google Analytics 4 properties.
This integration is currently supported in Split's JavaScript client side SDK version 10.11.1
and above. Learn more about how to configure the integration in the Split's SDK documentation.
Requirements
This integration requires the Google analytics.js library to be running on the web. Learn more about analytics.js here.
Google Analytics to Split
Automatically capture Google Analytics hits as Split events. This removes the need to instrument Split's client.track()
and leverage the event data already captured in Google Analytics.
To connect Split's SDK with the Google Analytics library, use Split's plugin available under the name 'splitTracker'
. Note that Split's SDK does not detect any hits that were queued before the 'require' command, but by requiring plugins early in the process, the asynchronicity is automatically handled. Read more about using plugins.
<script>
// The analytics initialization snippet;
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date(); a = s.createElement(o),
m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m)
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
ga('create', 'UA-XXXXX-Y', 'auto');
// BAD: This GA pageview hit would not be picked up by the integration.
ga('send', 'pageview', '/index');
// Require the 'splitTracker' plugin before sending any hits you want us to track. You can require it in as many trackers as you'd like.
ga('require', 'splitTracker'); // Require for use with the default tracker
ga('myTracker.require', 'splitTracker'); // Require for use with a tracker named "myTracker"
// GOOD: This GA pageview hit will be picked up by the integration.
ga('send', 'pageview', '/index');
</script>
Requiring not available plugins with Analytics
Because of how Google Analytics handles the asynchronicity of providing plugins, it's extremely important to test the plugins to ensure they load and run correctly. If a plugin fails to load or has an error, it prevents all subsequent analytics.js commands from executing. Read more here.
In this case, to use the 'splitTracker'
plugin, make sure that the GOOGLE_ANALYTICS_TO_SPLIT
integration is set up in your SDK configuration so it's always available. If you're using the Google Analytics Debugger and get the log message No plugin url set for "splitTracker".
, it's because you haven't instantiated the SDK with the integration.
If Split's SDK code is shared on multiple pages and the integration shouldn't be used everywhere, turn off the data flow by setting the hits
flag as false as explained on the configs table.
If you need further assistance, contact Split's support team at support@split.io.
The constant type for this integration is GOOGLE_ANALYTICS_TO_SPLIT
. By default all impressions and events are tracked for the key
and trafficType
provided in the configuration settings.
The default prefix ga. is used for the event types. Event types are based on the hit data with some constraints to comply with the event type rules. For example, if tracking a pageview hit using ga('send', 'pageview', '/myPagePath')
, the eventType is 'ga.pageview'
in Split.
var factory = SplitFactory({
core: {
authorizationKey: 'YOUR_BROWSER_API_KEY',
// key and traffic type for the resulting Split events will be taken from the factory config.
key: 'CUSTOMER_ID',
trafficType: 'user'
},
integrations: [{
type: 'GOOGLE_ANALYTICS_TO_SPLIT'
}]
});
const factory = SplitFactory({
core: {
authorizationKey: 'YOUR_BROWSER_API_KEY',
// key and traffic type for the resulting Split events will be taken from the factory config.
key: 'CUSTOMER_ID',
trafficType: 'user'
},
integrations: [{
type: 'GOOGLE_ANALYTICS_TO_SPLIT'
} as SplitIO.IGoogleAnalyticsToSplitConfig]
});
Configurations
The integration has a number of knobs for configuring how the integration should work.
Name | Type | Description | Default value |
---|---|---|---|
prefix | String | Optional string prefix for events which are followed by a dot (.) and be prepended to all the events generated by the integration. | 'ga' |
hits | Boolean | Optional boolean flag to control the flow of the Google Analytics hits. If turned off, no hits are picked up by the integration. | true |
filter | Function | Optional filtering criteria to be applied to the hits picked up by the integration before mapping and sending to Split as events. This function receives the model of the hit as a parameter. If false is returned, the given hit is filtered out. See below for more details. | No custom filter criteria |
mapper | Function | Optional mapping function to change how hits are translated into Split events. This function receives the model of the hit as the first parameter and the Split event as generated by the default mapping. The returned object from this function is validated as a Split event and queued to be sent, if valid. See below for more details. | The default mapping is applied. |
identities | Identities | A valid Split event requires a key and a traffic type . In the event these are not provided via the configuration of the factory or its best to track the events for multiple key and trafficType pairs, utilize this configuration to define the list and to track hits as events for an identity. An identity is just an object with two string properties, key and trafficType . See below for more details. |
The core.key and core.trafficType properties from the config are used. |
autoRequire | Boolean | Optional flag to log an error if the auto-require script is not detected. The auto-require script automatically requires the splitTracker plugin for created trackers, and should be placed right after your Google Analytics, GTM, or gtag.js script tag. Refer to the Google Tag Manager guide for more information. |
false |
Filter
The filter is an optional predicate to define which hits are tracked. The signature of the function is below.
function filter(model: UniversalAnalytics.Model): boolean;
For example, to track hits of hitType event
that are not of a certain category, write the following filter function shown below.
function customFilter(model: UniversalAnalytics.Model): boolean {
return model.get('hitType') === 'event' && model.get(eventCategory) !== UNWANTED_CATEGORY;
}
If a hit is filtered, it won't reach the mapping step.
Mapper
Learn more about Split events and their structure here. The events basic structure is shown below.
type EventData = {
eventTypeId: string;
value?: number;
properties?: Properties;
trafficTypeName?: string;
key?: string;
timestamp?: number;
};
The default mapping gets the key
and trafficType
from the configuration of the factory or the identities as explained below. These will NOT be part of the object you'll receive.
The timestamp
is generated as usual.
The eventType
field in Split is mapped as shown below:
- If the hitType equals
'event'
, the fieldeventAction
will be used. - If the hitType equals
'social'
instead, the fieldsocialAction
will be used. - If the hitType does not match the previous ones (like
pageview
), the actualhitType
will be used.
The value
field in Split is mapped as shown below:
- If the hitType equals
'event'
, the fieldeventValue
will be used. - If the hitType equals
'timing'
, the fieldtimingValue
will be used. - If the hitType does not match the previous ones (like
pageview
),null
is used as the default value (same as calling track without one).
The properties
field in Split is mapped as shown below:
- If the hitType equals
'pageview'
, the fieldpage
will be tracked as a property. - If the hitType equals
'screenview'
, the fieldscreenName
will be tracked as a property. - If the hitType equals
'event'
, the fieldseventCategory
andeventLabel
will be tracked as properties. - If the hitType equals
'social'
, the fieldssocialNetwork
andsocialTarget
will be tracked as properties. - If the hitType equals
'timing'
, the fieldstimingCategory
,timingVar
andtimingLabel
will be tracked as properties. - If the hitType equals
'exception'
, the fieldsexDescription
andexFatal
will be tracked as properties.
Any other fields are not tracked as event properties by default. Define a custom mapper to track additional fields and update how fields should be mapped. The signature of the mapper function is shown below.
function mapper(model: UnrsalAnalytics.Model, defaultMapping: SplitIO.EventData): SplitIO.EventData;
For example, to track the user location as an event property or conditionally add a value to the event, modify the received default mapped event and return it as shown below.
function mapper(model: UnrsalAnalytics.Model, defaultMapping: SplitIO.EventData): SplitIO.EventData {
// Of course you can apply any rules you'd like as long as you return a valid Split event from the function.
// The received object is a copy, so it's safe to modify and return afterwards avoiding the need for always defining a new object.
defaultMapping.properties.location = userLocation;
if (defaultMapping.eventTypeId.includes('playVideo')) defaultMapping.value = videoInstance.playedTime;
return defaultMapping;
};
Identities
Use this option if the trafficType is not defined in the factory or to track the same hits for multiple traffic types.
Each identity only defines two properties as shown below.
type Identity = {
key: string;
trafficType: string;
};
For example, track the same hits as events at the user level and at the account level as shown below.
const userId = 'CUSTOMER_ID';
const accountId = 'ACCOUNT_ID';
const factory = SplitFactory({
core: {
authorizationKey: 'YOUR_BROWSER_API_KEY',
// No need to define a traffic type at least for the integration, as it's provided via the identities array.
key: userId
},
integrations: [{
type: 'GOOGLE_ANALYTICS_TO_SPLIT',
identities: [{
key: userId, trafficType: 'user'
}, {
key: accountId, trafficType: 'account'
}]
} as SplitIO.IGoogleAnalyticsToSplitConfig]
});
It is important to note that the identity assignment is done AFTER the mapping. By defining the key
and trafficType
on the mapper, the identities provided is ignored and events won't be generated for multiple identities.
Full interface definition
See the full interface of the GOOGLE_ANALYTICS_TO_SPLIT
integration object defined below.
interface IGoogleAnalyticsToSplitConfig {
/**
* Type constant.
*/
type: 'GOOGLE_ANALYTICS_TO_SPLIT',
/**
* Optional flag to filter GA hits from being tracked as Split events.
* @default true
*/
hits?: boolean,
/**
* Optional predicate used to define a custom filter for tracking GA hits as Split events.
*/
filter?: (model: UniversalAnalytics.Model) => boolean,
/**
* Optional function useful when you need to modify the Split event before tracking it.
* This function is invoked with two arguments:
* 1. the GA model object representing the hit.
* 2. the default format of the mapped Split event instance.
* The return value must be a Split event, that can be the second argument or a new object.
*/
mapper?: (model: UniversalAnalytics.Model, defaultMapping: SplitIO.EventData) => SplitIO.EventData,
/**
* Optional prefix for EventTypeId, to prevent any kind of data collision between events.
* @default 'ga'
*/
prefix?: string,
/**
* List of Split identities (key & traffic type pairs) used to track events.
* If not provided, events are sent using the key and traffic type provided at SDK config
*/
identities?: Identity[]
}
Set up with Google Tag Manager and gtag.js
When you use Google Tag Manager (GTM) or Global Site Tag (gtag.js) to set up your Universal Analytics configuration, trackers are created with dynamic names.
To learn more about how to configure this integration in this scenario, refer to the Google Tag Manager guide.
Split to Google Analytics
Automatically capture Split impressions and events as hits into Google Analytics' dashboard. This removes the need to manually connect Split to Google Analytics.
The constant type for this integration is SPLIT_TO_GOOGLE_ANALYTICS
and by default, all impressions and events are tracked using the hitType event
but with two different eventCategory values, 'split-impression'
and 'split-event'
.
var factory = SplitFactory({
core: {
authorizationKey: 'YOUR_BROWSER_API_KEY',
key: 'CUSTOMER_ID'
},
integrations: [{
type: 'SPLIT_TO_GOOGLE_ANALYTICS'
}]
});
const factory = SplitFactory({
core: {
authorizationKey: 'YOUR_BROWSER_API_KEY',
key: 'CUSTOMER_ID'
},
integrations: [{
type: 'SPLIT_TO_GOOGLE_ANALYTICS'
} as SplitIO.ISplitToGoogleAnalyticsConfig]
});
Configurations
The integration has a number of knobs for configuring how the integration should work.
Name | Type | Description | Default value |
---|---|---|---|
impressions | Boolean | Optional boolean flag to control the flow of Split impressions. If turned off (false), no impressions are picked up by the integration. | true |
events | Boolean | Optional boolean flag to control the flow of Split events. If turned off (false), no events are picked up by the integration. | true |
filter | Function | Optional filter criteria to be applied to the events and impressions picked up by the integration before mapping and sending to Google Analytics as hits. This function receives an object with two properties, type property which is either 'IMPRESSION' or 'EVENT' , and the payload property with the actual data. If false is returned, the given impression or event is filtered out. See below for more details. |
No custom filter criteria |
mapper | Function | Optional mapping function to change how events and impressions are translated into Google Analytics hits. This function receives the data object with type property which is either 'IMPRESSION' or 'EVENT' , and the payload property with the actual event or impression data as the first parameter and the Analytics hit as generated by Split's default mapping. The returned object from this function is validated as an Analytics hit and queued to be sent, if valid. See below for more details. |
The default mapping is applied. |
trackers | string | If using multiple Google Analytics trackers on the page or just not the default one, provide the tracker names to connect with the desired trackers. See below for more details. | The integration will work with the default tracker. |
Filter
The filter is an optional predicate used to define which impressions or events are tracked. The signature of the function is shown below.
function filter(data: SplitIO.IntegrationData): boolean;
IntegrationData and the payload options are shown below.
type IntegrationData = { type: 'IMPRESSION', payload: SplitIO.ImpressionData } | { type: 'EVENT', payload: SplitIO.EventData };
type ImpressionData = {
impression: {
feature: string,
keyName: string,
treatment: string,
time: number,
bucketingKey?: string,
label: string,
changeNumber: number
},
// these are the attributes you provided on the getTreatment call, in case you want to send any to Google Analytics tied to the impression.
attributes?: SplitIO.Attributes,
ip: string,
hostname: string,
sdkLanguageVersion: string
};
type EventData = {
eventTypeId: string;
value?: number;
properties?: Properties;
trafficTypeName?: string;
key?: string;
timestamp?: number;
};
For example, to only track impressions for a particular feature flag along with all the events, write the following filter function:
function customFilter(data: SplitIO.IntegrationData): boolean {
if (data.type !== 'IMPRESSION') return true;
const evaluatedFeature = data.payload.impression.feature;
return evaluatedFeature === 'SPLIT_TO_TRACK_EVALUATIONS_AS_HITS';
}
If a hit is filtered, it won't reach the mapping step.
Mapper
Learn more about Google Analytics and which rules are neccessary to comply with in the guide sending data to Google Analytics. For quick reference, all hits MUST have a hitType. Split's SDK validates this automatically.
The default mapping for impressions would generate hits as shown below.
// Based on the data object you'll receive on the mapper:
{
hitType: 'event',
eventCategory: 'split-impression',
eventAction: 'Evaluate ' + data.payload.impression.feature,
eventLabel: 'Treatment: ' + data.payload.impression.treatment + '. Targeting rule ' + data.payload.impression.label,
nonInteraction: true
}
// For example, the generated object for a feature flag called my_feature could be:
{
hitType: 'event',
eventCategory: 'split-impression',
eventAction: 'Evaluate my_feature',
eventLabel: 'Treatment: on. Targeting rule: default rule.',
nonInteraction: true
}
The default mapping for events would generate hits as shown below.
// Based on the data object you'll receive on the mapper:
{
hitType: 'event',
eventCategory: 'split-event',
eventAction: payload.eventTypeId,
eventValue: payload.value,
nonInteraction: true
}
// For example, the generated object for an event generated with client.track('user', 'cart_checkout', 2000)
{
hitType: 'event',
eventCategory: 'split-event',
eventAction: 'cart_checkout',
eventValue: 2000,
nonInteraction: true
}
Split doesn't automatically add any extra fields or dimensions to the data. Easily define a custom mapper and change or add values. The signature of the mapper function is shown below.
function mapper(data: SplitIO.IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject): UniversalAnalytics.FieldsObject;
For example, add a dimension to a Split event derived hits based on the trafficType and keep impressions derived hits as they are.
function mapper(data: SplitIO.IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject): UniversalAnalytics.FieldsObject {
// Of course you can apply any rules you'd like as long as you return a valid FieldsObject from the function.
// The received object is a copy, so it's safe to modify and return afterwards avoiding the need for always defining a new object.
if (data.type === 'EVENT') {
defaultMapping.dimension1 = data.payload.trafficType;
}
return defaultMapping;
}
Trackers
If using named trackers, provide the names for the ones you want to connect with the integration. By default, Split hooks to the default tracker (''
).
For example, to only send event data through the marketing tracker, write the below.
const factory = SplitFactory({
core: {
authorizationKey: 'YOUR_BROWSER_API_KEY',
key: 'CUSTOMER_ID'
},
integrations: [{
type: 'SPLIT_TO_GOOGLE_ANALYTICS',
trackers: ['marketing'],
impressions: false
}]
});
See the full interface of the SPLIT_TO_GOOGLE_ANALYTICS
integration object defined below.
interface ISplitToGoogleAnalyticsConfig {
/**
* Type constant.
*/
type: 'SPLIT_TO_GOOGLE_ANALYTICS',
/**
* Optional flag to filter Split impressions from being tracked as GA hits.
* @default true
*/
impressions?: boolean,
/**
* Optional flag to filter Split events from being tracked as GA hits.
* @default true
*/
events?: boolean,
/**
* Optional predicate used to define a custom filter for tracking Split data (events and impressions) as GA hits.
*/
filter?: (data: SplitIO.IntegrationData) => boolean,
/**
* Optional function useful when you need to modify the GA hit before sending it.
* This function is invoked with two arguments:
* 1. the input data (Split event or impression).
* 2. the default format of the mapped FieldsObject instance (GA hit).
* The return value must be a FieldsObject, that can be the second argument or a new object.
*/
mapper?: (data: SplitIO.IntegrationData, defaultMapping: UniversalAnalytics.FieldsObject) => UniversalAnalytics.FieldsObject,
/**
* List of tracker names to send the hit. An empty string represents the default tracker.
* If not provided, hits are only sent to default tracker.
*/
trackerNames?: string[],
}
Comments
2 comments
Hi, I got "No plugin url set for "splitTracker" when I tried to require the plugin. Could you help me? please
Hi Cristian Vargas. I am sorry it has been a while since you posted your comment, but I wanted to provide a response anyway for future references.
If you're getting the log message `No plugin url set for "splitTracker".`, I assume you are using Google Analytics Debugger. The reason for that log might be that you have forgotten to instantiated the SDK with the "GOOGLE_ANALYTICS_TO_SPLIT" integration, as follows:
var factory = SplitFactory({
core: {
authorizationKey: <YOUR CLIENT-SIDE API KEY>,
key: <USER KEY>,
trafficType: <TRAFFIC TYPE>
},
integrations: [{
type:'GOOGLE_ANALYTICS_TO_SPLIT'
}]
});
Without the integration, the `splitTracker` plugin will not be provided, and so it will not be found when you place the command `ga('require', 'splitTracker')`
Please sign in to leave a comment.