Analytics Integration (GA4 & Segment)
CADENCE automatically forwards experiment assignment data to Google Analytics 4 and Segment. No configuration required — if the analytics tool is present on the page, experiment data is forwarded.
How it works
When getVariant() assigns a user to an experiment, the SDK:
- Detects GA4 (
window.dataLayer) and Segment (window.analytics) at call time, not at SDK init time — so your analytics scripts can load in any order - Forwards the experiment assignment to each detected provider independently (an error in one never affects the other)
- Deduplicates events per session — each experiment fires at most one event per analytics provider per session
The forwarding is fire-and-forget. It never delays or blocks variant assignment.
Google Analytics 4 (GA4)
What CADENCE sends to GA4
CADENCE pushes a single event to window.dataLayer:
window.dataLayer.push({
event: 'experiment_viewed',
experiment_id: '<uuid>', // CADENCE experiment UUID
experiment_variant: 'Control' // "Control", "A", "B", "C", or "D"
})
Why experiment_variant uses group labels instead of variant names: GA4 custom dimensions work best with low-cardinality values. Group labels (Control, A, B, C, D) are stable — they do not change if you rename variants in CADENCE. This prevents GA4 from creating new dimension values every time you edit a variant name, which would pollute your custom dimension reports.
Why experiment_name is not included: Experiment names are high-cardinality (every experiment is unique). Including names as a GA4 custom dimension would exhaust your custom dimension quota over time. Use experiment_id to cross-reference with the CADENCE dashboard.
This event works with both direct gtag.js installations and Google Tag Manager. CADENCE defensively initializes window.dataLayer = window.dataLayer || [] so events buffer even if GTM hasn't loaded yet — GTM drains the array when its container initializes.
Setting up GA4 Custom Dimensions
Before the experiment_id and experiment_variant parameters appear in GA4 reports and Explorations, you need to register them as custom dimensions.
- Go to GA4 Admin → Custom definitions → Custom dimensions
- Click Create custom dimension
- Create the first dimension:
- Dimension name: Experiment ID
- Scope: Event
- Event parameter:
experiment_id
- Click Save, then click Create custom dimension again
- Create the second dimension:
- Dimension name: Experiment Variant
- Scope: Event
- Event parameter:
experiment_variant
- Click Save
Custom dimensions take time to populate
After creating custom dimensions, it can take up to 24 hours before they appear in GA4 reports and Explorations. The events are collected immediately — the delay is only in the UI becoming queryable.
Viewing experiment data in GA4 Explorations
Once custom dimensions are registered and events have been collecting, use GA4 Explorations to analyze variant performance:
- In GA4, go to Explore → Create new exploration
- Under Dimensions, click the + icon and add Experiment ID and Experiment Variant
- Under Metrics, add Total users and Event count (or whatever conversion metrics you care about)
- Drag Experiment ID and Experiment Variant into the Rows drop zone
- To isolate a single experiment, add a filter: Experiment ID → exactly matches → paste the experiment UUID from your CADENCE dashboard
Variant labels (Control, A, B, C, D) are stable identifiers. They will not change if you rename variants in CADENCE, so your Explorations and segments remain consistent over the life of a test.
Verifying the GA4 integration
Using GA4 DebugView:
- Install the GA4 DebugView Chrome extension or use GA4 Admin → DebugView
- Navigate to a page where a CADENCE experiment is running
- Look for the
experiment_viewedevent in the event stream - Click the event to verify
experiment_idandexperiment_variantappear in the parameters
Using the browser console:
// Inspect the dataLayer queue directly
console.log(window.dataLayer)
// Look for an object with event: "experiment_viewed"
Segment
What CADENCE sends to Segment
CADENCE sends data to Segment in two ways:
1. A track event on variant assignment:
analytics.track('Experiment Viewed', {
experiment_id: '<uuid>',
experiment_name: '<experiment name>',
variation_name: 'Control', // "Control", "A", "B", "C", or "D"
nonInteraction: 1
})
The nonInteraction: 1 property prevents bounce rate inflation in GA4 destinations that receive this event. This follows the same convention used by Google Analytics' non-interaction hits.
2. Experiment context on every page view:
CADENCE patches analytics.page() to include a cadence_experiments property on all subsequent page calls:
// What your page() calls look like after CADENCE attaches context:
analytics.page({
cadence_experiments: 'abc123:Control,def456:A'
// ...your other page properties
})
The format is a comma-separated string of experimentId:variantLabel pairs — one entry per active experiment in the session.
Why Experiment Viewed instead of a custom event name
Experiment Viewed is the industry-standard event name used by Optimizely, GrowthBook, LaunchDarkly, and other experimentation tools. Amplitude, Mixpanel, and other Segment destinations have built-in support for this event schema and can recognize it without custom configuration.
Using variation_name (with values Control, A, B, C, D) to build cohorts in downstream tools is consistent with this convention.
Verifying in the Segment Source Debugger
- Open your Segment workspace → select your Source → click Debugger
- Navigate to a page where a CADENCE experiment is running
- Look for an event named
Experiment Viewedin the event stream - Click the event to verify properties include
experiment_id,experiment_name,variation_name - Trigger a page navigation and look for a
pageevent — verifyproperties.cadence_experimentscontains your experiment ID and variant label
Downstream destinations
The Experiment Viewed event with variation_name works out-of-the-box with:
- Amplitude — map
variation_nameto a user property for cohort analysis - Mixpanel — use
variation_nameas a filter in funnels and flows - Heap —
Experiment Viewedappears as a named event, filter by properties - Any GA4 destination —
nonInteraction: 1prevents bounce inflation
Technical details
For those who want to understand the implementation:
- Detection is at call time, not SDK init time. This means your analytics tools can load asynchronously after CADENCE without missing any events. The Segment analytics.js stub queues
track()calls before the full library loads, andwindow.dataLayerbuffers events before GTM initializes. - Deduplication uses a per-session
Set. Each experiment ID is tracked per provider — once an event has been forwarded for an experiment, subsequentgetVariant()calls for that experiment do not fire duplicate events. - Error isolation — GA4 and Segment forwarding run in separate try/catch blocks. A failure in one provider (for example, Segment not present on the page) does not suppress the other.
- Segment page patching uses
addSourceMiddlewareif available (analytics-next / the modern Segment library) or falls back to monkey-patchinganalytics.pagefor classic analytics.js. The patch is applied only once per session regardless of how manygetVariant()calls are made.
Troubleshooting
"I don't see experiment_viewed in GA4 DebugView"
Check that GTM or gtag.js is installed and configured with your GA4 property. CADENCE initializes window.dataLayer and pushes events to it, but cannot send events to GA4 without a measurement ID configured somewhere on the page. If you are using GTM, make sure your GA4 Configuration tag is present and firing.
"Events appear in Segment but not in my downstream destination"
Check your destination settings in Segment. Many destinations have event allowlists or require you to explicitly enable specific events. Go to your destination settings and ensure Experiment Viewed is not being filtered out.
"I see experiment_viewed multiple times for the same experiment"
This should not happen — the SDK deduplicates by experiment ID per session. If you are seeing duplicates, check whether you have multiple CADENCE SDK instances initialized on the page (for example, two <script> tags or two Cadence.init() calls).
"experiment_variant shows undefined in the GA4 event"
Make sure you are using CADENCE SDK v1.1 or later. The analytics forwarding feature was added in v1.1. Earlier SDK versions do not include the analytics-forwarder module.
"The Segment Experiment Viewed event is there but cadence_experiments is missing from page() calls"
The cadence_experiments page context is attached after the first getVariant() call in a session. Make sure CADENCE's getVariant() has been called before the analytics.page() call you are inspecting. If you are using a single-page app and triggering page() on route changes, ensure getVariant() is called during initial load.