Experiment Analytics
How to analyze Coframe experiment results using treatment data and holdout/baseline groups
Copy this guide and your current settings as a prompt for your AI agent.
Preview agent promptSee the guide, code and settings included when you copy.
This page explains how to use the treatment data Coframe emits to analyze experiment results in your own analytics tooling. It covers what data is available per impression, which fields identify control versus treatment groups, and how to join Coframe data to your own event stream.
For a full description of every field in the treatment payload and how the three-step assignment gate works, see Experiment Assignment & IDs.
01The data you analyze with
Every time a visitor is assigned to an experiment, Coframe emits a CoframeTreatmentDataV2 record — one per active experiment with a terminal assignment. These records are the primary input for experiment analysis.
Two ways to access the data:
1. bulkCallbackV2 (real-time, preferred)
Subscribe before the SDK loads so the callback fires as soon as assignments are determined:
window.CFQ = window.CFQ || [];
window.CFQ.push({
subscribe: 'treatmentApplied',
bulkCallbackV2: function(treatments, rawIds) {
treatments.forEach(function(t) {
// forward t to your analytics platform
});
}
});The callback receives an array of CoframeTreatmentDataV2 objects. Each object in the array corresponds to one terminal experiment assignment for this page view. See CFQ Commands for the full subscribe API.
2. Coframe.treatmentsDataV2 (on demand)
After the SDK has initialised, window.Coframe.treatmentsDataV2 holds the same array. It starts as null and is populated once treatment analytics have run. Useful for reading assignments imperatively after init. See The Coframe Global for the full property reference.
The fields in each record
Each CoframeTreatmentDataV2 object carries eight fields. The complete field reference — types, meanings, and example payloads for each visitor group — is in Experiment Assignment & IDs. The fields relevant to analysis are:
| Field | Role in analysis |
|---|---|
coframe_experiment_id |
Groups all visitors (baseline + treatment) in the same experiment |
coframe_variant_id / coframe_variant_slug |
Identifies which specific variant this visitor received |
coframe_in_exp_baseline |
true when the visitor is in the experiment control group |
coframe_in_global_holdout |
true when the visitor is excluded from all experiments project-wide |
coframe_user_token |
Visitor identity — join with your own user-level events |
coframe_impression_id |
Page-view identity — join or deduplicate at the impression level |
02Comparing variants
Scoping to an experiment
coframe_experiment_id is shared by every visitor who entered a given experiment — including baseline and all treatment variants. Use it as the primary grouping key to scope your analysis to a single experiment population.
Identifying the control group
coframe_in_exp_baseline: true marks visitors who are in the experiment-level baseline. These visitors see the original, unmodified content and are tracked for comparison against treatment visitors. Within a single coframe_experiment_id, compare the behavior of visitors where coframe_in_exp_baseline is true against those where it is false.
coframe_variant_slug will be 'baseline' for these visitors, or the variant name for treatment visitors.
The global holdout as a project-level control
coframe_in_global_holdout: true identifies visitors who were excluded from all Coframe experiments before reaching any per-experiment assignment. This group receives no Coframe treatments at all, across every experiment on the project.
The global holdout has its own coframe_experiment_id (different from any per-experiment ID) and its coframe_variant_slug will be 'global_holdout'. Because these visitors are entirely unaffected by Coframe, they can serve as a clean control for measuring Coframe’s aggregate effect on site behavior — separate from any individual experiment comparison.
Distinguishing the three visitor groups
| Visitor group | coframe_in_global_holdout |
coframe_in_exp_baseline |
|---|---|---|
| Global holdout | true |
false |
| Experiment baseline (control) | false |
true |
| Treatment variant | false |
false |
Use coframe_variant_id and coframe_variant_slug to further distinguish which specific treatment variant a visitor received when coframe_in_exp_baseline and coframe_in_global_holdout are both false.
03Joining to your analytics
Coframe data is most useful when joined to your own event stream so you can measure downstream behavior (conversions, retention, revenue) per variant group.
Joining at the visitor level — coframe_user_token
coframe_user_token is a persistent visitor identifier. Coframe sets it at SDK init time from either a generated UUID (cookie-backed) or a value you supply via CFQ.setUserToken. When you forward this field to your analytics platform, you can join it to any event your system records for the same user. Filter your event stream to users whose coframe_user_token appears in the treatment data for a given coframe_experiment_id, then compare behavior across variant groups.
Joining at the impression level — coframe_impression_id
coframe_impression_id is Coframe.sessionId — a UUID generated at script-load time, unique to the page session. It resets on each new page load. Use it to join or deduplicate at the impression level: if the same visitor views an experiment page multiple times, each page view produces a distinct coframe_impression_id.
Forwarding to analytics platforms
The Analytics Integrations section provides ready-to-use bulkCallbackV2 snippets for common platforms (Segment, Amplitude, PostHog, and others). Each snippet forwards the coframe_* fields as event properties, making them available for filtering and grouping in your analytics tool.
# Experiment Analytics
How to analyze Coframe experiment results using treatment data and holdout/baseline groups
This page explains how to use the treatment data Coframe emits to analyze experiment results in your own analytics tooling. It covers what data is available per impression, which fields identify control versus treatment groups, and how to join Coframe data to your own event stream.
For a full description of every field in the treatment payload and how the three-step assignment gate works, see [Experiment Assignment & IDs](../docs/experiment-assignment.html).
## The data you analyze with
Every time a visitor is assigned to an experiment, Coframe emits a `CoframeTreatmentDataV2` record — one per active experiment with a terminal assignment. These records are the primary input for experiment analysis.
Two ways to access the data:
1. `bulkCallbackV2` (real-time, preferred)
Subscribe before the SDK loads so the callback fires as soon as assignments are determined:
JS
```
window.CFQ = window.CFQ || [];
window.CFQ.push({
subscribe: 'treatmentApplied',
bulkCallbackV2: function(treatments, rawIds) {
treatments.forEach(function(t) {
// forward t to your analytics platform
});
}
});
```
The callback receives an array of `CoframeTreatmentDataV2` objects. Each object in the array corresponds to one terminal experiment assignment for this page view. See [CFQ Commands](../docs/cfq-commands.html) for the full subscribe API.
2. `Coframe.treatmentsDataV2` (on demand)
After the SDK has initialised, `window.Coframe.treatmentsDataV2` holds the same array. It starts as `null` and is populated once treatment analytics have run. Useful for reading assignments imperatively after init. See [The Coframe Global](../docs/coframe-global.html) for the full property reference.
The fields in each record
Each `CoframeTreatmentDataV2` object carries eight fields. The complete field reference — types, meanings, and example payloads for each visitor group — is in [Experiment Assignment & IDs](../docs/experiment-assignment.html). The fields relevant to analysis are:
Field |
Role in analysis |
`coframe_experiment_id` |
Groups all visitors (baseline + treatment) in the same experiment |
`coframe_variant_id` / `coframe_variant_slug` |
Identifies which specific variant this visitor received |
`coframe_in_exp_baseline` |
`true` when the visitor is in the experiment control group |
`coframe_in_global_holdout` |
`true` when the visitor is excluded from all experiments project-wide |
`coframe_user_token` |
Visitor identity — join with your own user-level events |
`coframe_impression_id` |
Page-view identity — join or deduplicate at the impression level |
## Comparing variants
Scoping to an experiment
`coframe_experiment_id` is shared by every visitor who entered a given experiment — including baseline and all treatment variants. Use it as the primary grouping key to scope your analysis to a single experiment population.
Identifying the control group
`coframe_in_exp_baseline: true` marks visitors who are in the experiment-level baseline. These visitors see the original, unmodified content and are tracked for comparison against treatment visitors. Within a single `coframe_experiment_id`, compare the behavior of visitors where `coframe_in_exp_baseline` is `true` against those where it is `false`.
`coframe_variant_slug` will be `'baseline'` for these visitors, or the variant name for treatment visitors.
The global holdout as a project-level control
`coframe_in_global_holdout: true` identifies visitors who were excluded from all Coframe experiments before reaching any per-experiment assignment. This group receives no Coframe treatments at all, across every experiment on the project.
The global holdout has its own `coframe_experiment_id` (different from any per-experiment ID) and its `coframe_variant_slug` will be `'global_holdout'`. Because these visitors are entirely unaffected by Coframe, they can serve as a clean control for measuring Coframe’s aggregate effect on site behavior — separate from any individual experiment comparison.
Distinguishing the three visitor groups
Visitor group |
`coframe_in_global_holdout` |
`coframe_in_exp_baseline` |
Global holdout |
`true` |
`false` |
Experiment baseline (control) |
`false` |
`true` |
Treatment variant |
`false` |
`false` |
Use `coframe_variant_id` and `coframe_variant_slug` to further distinguish which specific treatment variant a visitor received when `coframe_in_exp_baseline` and `coframe_in_global_holdout` are both `false`.
## Joining to your analytics
Coframe data is most useful when joined to your own event stream so you can measure downstream behavior (conversions, retention, revenue) per variant group.
Joining at the visitor level — `coframe_user_token`
`coframe_user_token` is a persistent visitor identifier. Coframe sets it at SDK init time from either a generated UUID (cookie-backed) or a value you supply via `CFQ.setUserToken`. When you forward this field to your analytics platform, you can join it to any event your system records for the same user. Filter your event stream to users whose `coframe_user_token` appears in the treatment data for a given `coframe_experiment_id`, then compare behavior across variant groups.
Joining at the impression level — `coframe_impression_id`
`coframe_impression_id` is `Coframe.sessionId` — a UUID generated at script-load time, unique to the page session. It resets on each new page load. Use it to join or deduplicate at the impression level: if the same visitor views an experiment page multiple times, each page view produces a distinct `coframe_impression_id`.
Forwarding to analytics platforms
The [Analytics Integrations](../docs/segment.html) section provides ready-to-use `bulkCallbackV2` snippets for common platforms (Segment, Amplitude, PostHog, and others). Each snippet forwards the `coframe_*` fields as event properties, making them available for filtering and grouping in your analytics tool.
## Related
- [Experiment Assignment & IDs](../docs/experiment-assignment.html) — canonical field reference, the three-step assignment gate, and example payloads for each visitor group
- [Events and Tracking](../docs/events-and-tracking.html) — what Coframe records and how tracking data is structured
- [Analytics Integrations](../docs/segment.html) — platform-specific snippets for forwarding treatment data
- [The Coframe Global](../docs/coframe-global.html) — `Coframe.treatmentsDataV2` and the full runtime object reference