CFQ Commands
Every window.CFQ command the Coframe SDK accepts — identity, consent, feature flags, conversions, and the treatment callback
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.
window.CFQ is a plain JavaScript array of command objects. You can push
commands at any time — before or after the SDK script loads.
When the SDK loads, it replays commands that were pushed beforehand using two
mechanisms. waitForCmd performs a reverse scan of the existing queue via
findLastCmd and resolves immediately if a matching command already exists;
it then registers a push listener for future items. listenForCmd iterates
the full existing queue and fires the callback for each matching entry, then
hooks push for future items. A third internal mechanism, subscribeToCmd, is
forward-only: it does not replay history and is used internally when the
initial state has already been consumed by another path.
Once the SDK is running, queue.push is patched so new commands are
dispatched immediately to registered listeners. The queue is protected from
re-assignment: window.CFQ = window.CFQ || [] is safe because the SDK
installs an Object.defineProperty getter/setter that silently ignores
reassignments.
On this page
01config
Purpose: Trigger SDK initialisation.
When to call: Place this command before or alongside your SDK <script>
tag. The SDK blocks at startup on a waitForCmd until this command arrives —
no variant selection or event sending happens without it. The config value
must be a CoframeConfig object with at minimum projectId.
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({
config: {
projectId: 'proj_abc123',
waitForHydration: true
}
});
</script>See also: Config Reference
02setUserToken
Purpose: Provide a custom visitor identity for cookieless tracking.
When to call: Push this command after you have resolved the visitor’s
identity on your side (for example, after an authentication check). This
command is only consumed when config.waitForUserToken: true; the SDK waits
for cmd.setUserToken to be a non-empty string, then stores it as
Coframe.userToken.
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({ setUserToken: 'visitor-123' });
</script>See also: Identity Settings
03cookiesEnabled
Purpose: Grant or revoke cookie consent.
When to call: Push this command after your consent management platform
(CMP) resolves the visitor’s cookie preference. The SDK replays the last
pre-queued value synchronously via findLastCmd, then subscribes for future
changes. This command is required when config.waitForCookiesEnabled: true.
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({ cookiesEnabled: true });
</script>See also: SDK Options — Cookies & Consent
04featureFlagSet
Purpose: Gate SDK activation behind a feature flag.
When to call: Push this command after evaluating the flag in your feature
flag platform. The SDK waits for typeof cmd.featureFlagSet === 'boolean'.
If the value is false, the SDK exits gracefully and reveals the page without
applying variants. If the wait times out (config.timeoutMs, capped at 5 s),
the SDK also exits gracefully.
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({ featureFlagSet: true });
</script>See also: SDK Options — Feature Flag Control
05pageHydrated
Purpose: Signal that the page has finished hydrating.
When to call: Push this command once your SSR or React hydration is
complete. It unblocks variant selection when config.waitForHydration: true.
The SDK predicate is cmd.pageHydrated === true || cmd.emit === 'pageHydrated'
— the emit form is deprecated.
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({ pageHydrated: true });
</script>See also: React Integration
06conversion
Purpose: Report a manual conversion event.
When to call: Push this command at the point in your code where the
conversion action occurs (for example, on a successful purchase or sign-up).
The SDK listens continuously for cmd.conversion !== undefined. At least one
of metricId or metricName must be present in the payload; if neither is
provided, the SDK logs an error and discards the event.
ConversionEventPayload fields:
| Field | Type | Required |
|---|---|---|
metricId |
string |
one of metricId / metricName required |
metricName |
string |
one of metricId / metricName required |
metadata |
Record<string, string> |
optional |
value |
number |
optional |
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({
conversion: {
metricId: 'metric_abc',
metadata: { plan: 'pro' },
value: 99
}
});
</script>See also: Tracking Settings
07subscribe: 'treatmentApplied'
Purpose: Subscribe to SDK-emitted treatment events.
When to call: Push this command before the SDK finishes initialising (or
at any time — replay ensures it is received). Include one callback field; if
more than one is present, at most one is active. The preferred field is
bulkCallbackV2; bulkCallbackV2WithoutConsent
fires even before cookie consent is granted. The older callback and
bulkCallback fields are deprecated.
| Callback field | Consent-gated | Notes |
|---|---|---|
callback |
yes | v1, per-treatment; deprecated |
bulkCallback |
yes | v1 bulk; deprecated |
bulkCallbackV2 |
yes | preferred |
bulkCallbackV2WithoutConsent |
no | fires before cookie consent |
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({
subscribe: 'treatmentApplied',
bulkCallbackV2: (treatments, rawIds) => {
treatments.forEach(t =>
analytics.track('Experiment Viewed', {
experiment_id: t.coframe_experiment_id,
variant_id: t.coframe_variant_id,
})
);
}
});
</script>See also: Segment Integration
08Deprecated aliases
The following command forms were deprecated as of January 2026. They continue to work; migrate to the modern forms shown below.
| Deprecated form | Preferred replacement |
|---|---|
{ emit: 'pageHydrated' } |
{ pageHydrated: true } |
{ emit: 'conversion', payload: { ... } } |
{ conversion: { ... } } |
{ emit: { featureFlagSet: bool } } |
{ featureFlagSet: bool } |
{ subscribe: 'treatmentApplied', callback: fn } |
{ subscribe: 'treatmentApplied', bulkCallbackV2: fn } |
{ subscribe: 'treatmentApplied', bulkCallback: fn } |
{ subscribe: 'treatmentApplied', bulkCallbackV2: fn } |
See Migration Notes for more on these deprecations.
# CFQ Commands
Every window.CFQ command the Coframe SDK accepts — identity, consent, feature flags, conversions, and the treatment callback
`window.CFQ` is a plain JavaScript array of command objects. You can push
commands at any time — before or after the SDK script loads.
When the SDK loads, it replays commands that were pushed beforehand using two
mechanisms. `waitForCmd` performs a reverse scan of the existing queue via
`findLastCmd` and resolves immediately if a matching command already exists;
it then registers a push listener for future items. `listenForCmd` iterates
the full existing queue and fires the callback for each matching entry, then
hooks push for future items. A third internal mechanism, `subscribeToCmd`, is
forward-only: it does not replay history and is used internally when the
initial state has already been consumed by another path.
Once the SDK is running, `queue.push` is patched so new commands are
dispatched immediately to registered listeners. The queue is protected from
re-assignment: `window.CFQ = window.CFQ || []` is safe because the SDK
installs an `Object.defineProperty` getter/setter that silently ignores
reassignments.
## config
Purpose: Trigger SDK initialisation.
When to call: Place this command before or alongside your SDK `<script>`
tag. The SDK blocks at startup on a `waitForCmd` until this command arrives —
no variant selection or event sending happens without it. The `config` value
must be a `CoframeConfig` object with at minimum `projectId`.
HTML
```
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({
config: {
projectId: 'proj_abc123',
waitForHydration: true
}
});
</script>
```
See also: [Config Reference](../docs/config-reference.html)
## setUserToken
Purpose: Provide a custom visitor identity for cookieless tracking.
When to call: Push this command after you have resolved the visitor’s
identity on your side (for example, after an authentication check). This
command is only consumed when `config.waitForUserToken: true`; the SDK waits
for `cmd.setUserToken` to be a non-empty string, then stores it as
`Coframe.userToken`.
HTML
```
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({ setUserToken: 'visitor-123' });
</script>
```
See also: [Identity Settings](../docs/identity-settings.html)
## cookiesEnabled
Purpose: Grant or revoke cookie consent.
When to call: Push this command after your consent management platform
(CMP) resolves the visitor’s cookie preference. The SDK replays the last
pre-queued value synchronously via `findLastCmd`, then subscribes for future
changes. This command is required when `config.waitForCookiesEnabled: true`.
HTML
```
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({ cookiesEnabled: true });
</script>
```
See also: [SDK Options — Cookies & Consent](../docs/sdk-options.html#cookies-consent)
## featureFlagSet
Purpose: Gate SDK activation behind a feature flag.
When to call: Push this command after evaluating the flag in your feature
flag platform. The SDK waits for `typeof cmd.featureFlagSet === 'boolean'`.
If the value is `false`, the SDK exits gracefully and reveals the page without
applying variants. If the wait times out (`config.timeoutMs`, capped at 5 s),
the SDK also exits gracefully.
HTML
```
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({ featureFlagSet: true });
</script>
```
See also: [SDK Options — Feature Flag Control](../docs/sdk-options.html#feature-flag-control)
## pageHydrated
Purpose: Signal that the page has finished hydrating.
When to call: Push this command once your SSR or React hydration is
complete. It unblocks variant selection when `config.waitForHydration: true`.
The SDK predicate is `cmd.pageHydrated === true || cmd.emit === 'pageHydrated'`
— the `emit` form is deprecated.
HTML
```
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({ pageHydrated: true });
</script>
```
See also: [React Integration](../docs/react.html)
## conversion
Purpose: Report a manual conversion event.
When to call: Push this command at the point in your code where the
conversion action occurs (for example, on a successful purchase or sign-up).
The SDK listens continuously for `cmd.conversion !== undefined`. At least one
of `metricId` or `metricName` must be present in the payload; if neither is
provided, the SDK logs an error and discards the event.
`ConversionEventPayload` fields:
Field |
Type |
Required |
`metricId` |
`string` |
one of `metricId` / `metricName` required |
`metricName` |
`string` |
one of `metricId` / `metricName` required |
`metadata` |
`Record<string, string>` |
optional |
`value` |
`number` |
optional |
HTML
```
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({
conversion: {
metricId: 'metric_abc',
metadata: { plan: 'pro' },
value: 99
}
});
</script>
```
See also: [Tracking Settings](../docs/tracking-settings.html)
## subscribe: 'treatmentApplied'
Purpose: Subscribe to SDK-emitted treatment events.
When to call: Push this command before the SDK finishes initialising (or
at any time — replay ensures it is received). Include one callback field; if
more than one is present, at most one is active. The preferred field is
`bulkCallbackV2`; `bulkCallbackV2WithoutConsent`
fires even before cookie consent is granted. The older `callback` and
`bulkCallback` fields are deprecated.
Callback field |
Consent-gated |
Notes |
`callback` |
yes |
v1, per-treatment; deprecated |
`bulkCallback` |
yes |
v1 bulk; deprecated |
`bulkCallbackV2` |
yes |
preferred |
`bulkCallbackV2WithoutConsent` |
no |
fires before cookie consent |
HTML
```
<script>
window.CFQ = window.CFQ || [];
window.CFQ.push({
subscribe: 'treatmentApplied',
bulkCallbackV2: (treatments, rawIds) => {
treatments.forEach(t =>
analytics.track('Experiment Viewed', {
experiment_id: t.coframe_experiment_id,
variant_id: t.coframe_variant_id,
})
);
}
});
</script>
```
See also: [Segment Integration](../docs/segment.html)
## Deprecated aliases
The following command forms were deprecated as of January 2026. They continue
to work; migrate to the modern forms
shown below.
Deprecated form |
Preferred replacement |
`{ emit: 'pageHydrated' }` |
`{ pageHydrated: true }` |
`{ emit: 'conversion', payload: { ... } }` |
`{ conversion: { ... } }` |
`{ emit: { featureFlagSet: bool } }` |
`{ featureFlagSet: bool }` |
`{ subscribe: 'treatmentApplied', callback: fn }` |
`{ subscribe: 'treatmentApplied', bulkCallbackV2: fn }` |
`{ subscribe: 'treatmentApplied', bulkCallback: fn }` |
`{ subscribe: 'treatmentApplied', bulkCallbackV2: fn }` |
See [Migration Notes](../docs/migration-notes.html) for more on these
deprecations.