Common Integration Issues
Frequent Coframe setup mistakes — and how to fix them
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.
The issues below are the most common integration mistakes teams encounter when setting up Coframe. Each section describes what the failure looks like, why it happens, and the specific change that resolves it.
For problems where data appears absent or incomplete after a correct integration, see Missing Data. For a structured first pass when something is generally wrong, start with the Debug Checklist.
On this page
- 01Anti-flicker snippet loaded asynchronously or through a tag manager
- 02Variants not applying in a React app — pageHydrated never pushed
- 03SDK stays dormant — waitForFeatureFlag set but signal never pushed
- 04Cookies and events not recorded — waitForCookiesEnabled set but consent never pushed
- 05SDK loads but no variants appear — trackingOnly: true is set
- 06Related links
01Anti-flicker snippet loaded asynchronously or through a tag manager
Symptom
Visitors briefly see the original page content before the variant appears — a “flash of original content” — even though the Coframe SDK loads and variants are eventually applied.
Cause
The anti-flicker snippet must run synchronously before the browser’s first
paint. If the install script is placed inside an async tag manager (such as
Google Tag Manager), or if the <script> tag carrying the IIFE carries an
async or defer attribute, the browser may paint the page before the snippet
runs. Once first paint has occurred, hiding <body> has no effect on the
frames already rendered — the flash has already happened.
The snippet works by injecting a CSS rule that sets body opacity to zero
immediately, then scheduling a show() call at timeoutMs (the install script ships 1000 ms)
as a fail-open fallback. That sequence is only effective if it executes before
any paint.
Fix
Place the Coframe install script directly in the <head> of your HTML, without
async or defer, and without routing it through a tag manager. The main SDK
request (cf.js) is loaded asynchronously within the IIFE and is unaffected.
Only the outer IIFE — which contains the anti-flicker snippet — must be
synchronous.
See Anti-Flicker for how the mechanism works
and how to tune timeoutMs. See SDK Options
for the full configuration reference.
02Variants not applying in a React app — pageHydrated never pushed
Symptom
In a React application, the SDK loads successfully and appears in the network tab, but no variants are applied to any element on any page load.
Cause
When waitForHydration: true is set in the config object, the SDK blocks
variant selection until { pageHydrated: true } is pushed to window.CFQ. If
the <Coframe /> component — or the equivalent useEffect that pushes this
signal — was never added to the component tree, the signal never arrives and
the SDK never proceeds to apply changes.
Fix
Add the <Coframe /> component to the root of your component tree so it mounts
on every page. Its useEffect pushes the hydration signal after React finishes
mounting:
import React, { useEffect } from 'react';
function Coframe() {
useEffect(() => {
window.CFQ = window.CFQ || [];
window.CFQ.push({ pageHydrated: true });
}, []);
return null;
}
export default Coframe;import Coframe from './components/Coframe';
function App() {
return (
<>
<Coframe />
{/* Your app content */}
</>
);
}See the React integration guide for the full setup, and CFQ Commands for the complete command reference.
03SDK stays dormant — waitForFeatureFlag set but signal never pushed
Symptom
Coframe is installed and the SDK request succeeds, but no variants are applied and no treatment events are recorded. The page behaves as if the SDK is not present at all.
Cause
When waitForFeatureFlag: true is set in the config, the SDK waits for an
explicit { featureFlagSet: boolean } signal before it initializes. If the
companion script that pushes this signal is missing or never runs, the SDK
stays dormant until timeoutMs (the install script ships 1000 ms) elapses, after which it
exits gracefully without applying variants. The result looks identical to an
SDK that never loaded.
Fix
Ensure the feature-flag script runs on every page load. Push the signal even
when the flag evaluates to false — the SDK needs an explicit value in both
cases:
<script id="coframe-feature-flag-control" async>
const coframeEnabled = true; // replace with your feature flag value
window.CFQ = window.CFQ || [];
window.CFQ.push({ featureFlagSet: coframeEnabled });
</script>When featureFlagSet is false, the SDK exits gracefully and reveals the page
without applying any variants. When the script is absent entirely, the SDK
keeps waiting until the timeout.
See SDK Options for the feature flag configuration details.
04Cookies and events not recorded — waitForCookiesEnabled set but consent never pushed
Symptom
Coframe loads, but no cookies are written and no tracking events appear in the analytics output — even after the visitor has accepted the site’s cookie consent prompt.
Cause
When waitForCookiesEnabled: true is set in the config, the SDK holds off on
writing cookies and sending events until { cookiesEnabled: true } is pushed to
window.CFQ. If the consent signal is never pushed from the CMP callback —
because the push was omitted from the callback, or because the callback itself
never fires — the SDK runs that session without recording any cookies or events,
even if the visitor accepted.
Fix
Push { cookiesEnabled: true } from the callback that fires when the visitor
accepts your cookie consent prompt:
// Inside your CMP "accept" callback:
window.CFQ = window.CFQ || [];
window.CFQ.push({ cookiesEnabled: true });This call can be made at any point after the install script runs — the SDK replays the last queued value and then subscribes for future changes. If a visitor declines consent and the signal is never pushed, the SDK runs without writing cookies for that session; this is the intended behavior.
See SDK Options for the cookie consent configuration. If event data is still missing after fixing the consent flow, see Missing Data.
05SDK loads but no variants appear — trackingOnly: true is set
Symptom
Coframe loads correctly and treatment events are visible in the analytics output, but no content or visual changes are applied to the page on any page load.
Cause
When trackingOnly: true is set in the config, the SDK runs in observation
mode. It records which treatment a visitor would receive and emits the
corresponding analytics events, but it does not apply any changes to the page.
Anti-flicker is also disabled in this mode, since there are no visual changes
to protect against.
This mode is commonly used during an initial integration phase to validate that event flow is correct before enabling live variant delivery. If it is left in the config after that phase, variants never appear regardless of experiment status.
Fix
If you want Coframe to apply variant changes to the page, remove
trackingOnly: true from your config object, or set it to false. If you are
intentionally in an observation or audit phase, keeping it enabled is correct.
See SDK Options for tracking-only mode details and when to use it.
# Common Integration Issues
Frequent Coframe setup mistakes — and how to fix them
The issues below are the most common integration mistakes teams encounter when
setting up Coframe. Each section describes what the failure looks like, why it
happens, and the specific change that resolves it.
For problems where data appears absent or incomplete after a correct integration,
see [Missing Data](../docs/missing-data.html). For a structured first
pass when something is generally wrong, start with the
[Debug Checklist](../docs/debug-checklist.html).
## Anti-flicker snippet loaded asynchronously or through a tag manager
Symptom
Visitors briefly see the original page content before the variant appears — a
“flash of original content” — even though the Coframe SDK loads and variants
are eventually applied.
Cause
The anti-flicker snippet must run synchronously before the browser’s first
paint. If the install script is placed inside an async tag manager (such as
Google Tag Manager), or if the `<script>` tag carrying the IIFE carries an
`async` or `defer` attribute, the browser may paint the page before the snippet
runs. Once first paint has occurred, hiding `<body>` has no effect on the
frames already rendered — the flash has already happened.
The snippet works by injecting a CSS rule that sets `body` opacity to zero
immediately, then scheduling a `show()` call at `timeoutMs` (the install script ships `1000` ms)
as a fail-open fallback. That sequence is only effective if it executes before
any paint.
Fix
Place the Coframe install script directly in the `<head>` of your HTML, without
`async` or `defer`, and without routing it through a tag manager. The main SDK
request (`cf.js`) is loaded asynchronously within the IIFE and is unaffected.
Only the outer IIFE — which contains the anti-flicker snippet — must be
synchronous.
See [Anti-Flicker](../docs/anti-flicker.html) for how the mechanism works
and how to tune `timeoutMs`. See [SDK Options](../docs/sdk-options.html)
for the full configuration reference.
## Variants not applying in a React app — pageHydrated never pushed
Symptom
In a React application, the SDK loads successfully and appears in the network
tab, but no variants are applied to any element on any page load.
Cause
When `waitForHydration: true` is set in the config object, the SDK blocks
variant selection until `{ pageHydrated: true }` is pushed to `window.CFQ`. If
the `<Coframe />` component — or the equivalent `useEffect` that pushes this
signal — was never added to the component tree, the signal never arrives and
the SDK never proceeds to apply changes.
Fix
Add the `<Coframe />` component to the root of your component tree so it mounts
on every page. Its `useEffect` pushes the hydration signal after React finishes
mounting:
JSX
```
import React, { useEffect } from 'react';
function Coframe() {
useEffect(() => {
window.CFQ = window.CFQ || [];
window.CFQ.push({ pageHydrated: true });
}, []);
return null;
}
export default Coframe;
```
JSX
```
import Coframe from './components/Coframe';
function App() {
return (
<>
<Coframe />
{/* Your app content */}
</>
);
}
```
See the [React integration guide](../docs/react.html) for the full
setup, and [CFQ Commands](../docs/cfq-commands.html) for the complete
command reference.
## SDK stays dormant — waitForFeatureFlag set but signal never pushed
Symptom
Coframe is installed and the SDK request succeeds, but no variants are applied
and no treatment events are recorded. The page behaves as if the SDK is not
present at all.
Cause
When `waitForFeatureFlag: true` is set in the config, the SDK waits for an
explicit `{ featureFlagSet: boolean }` signal before it initializes. If the
companion script that pushes this signal is missing or never runs, the SDK
stays dormant until `timeoutMs` (the install script ships `1000` ms) elapses, after which it
exits gracefully without applying variants. The result looks identical to an
SDK that never loaded.
Fix
Ensure the feature-flag script runs on every page load. Push the signal even
when the flag evaluates to `false` — the SDK needs an explicit value in both
cases:
HTML
```
<script id="coframe-feature-flag-control" async>
const coframeEnabled = true; // replace with your feature flag value
window.CFQ = window.CFQ || [];
window.CFQ.push({ featureFlagSet: coframeEnabled });
</script>
```
When `featureFlagSet` is `false`, the SDK exits gracefully and reveals the page
without applying any variants. When the script is absent entirely, the SDK
keeps waiting until the timeout.
See [SDK Options](../docs/sdk-options.html) for the feature flag
configuration details.
## Cookies and events not recorded — waitForCookiesEnabled set but consent never pushed
Symptom
Coframe loads, but no cookies are written and no tracking events appear in the
analytics output — even after the visitor has accepted the site’s cookie consent
prompt.
Cause
When `waitForCookiesEnabled: true` is set in the config, the SDK holds off on
writing cookies and sending events until `{ cookiesEnabled: true }` is pushed to
`window.CFQ`. If the consent signal is never pushed from the CMP callback —
because the push was omitted from the callback, or because the callback itself
never fires — the SDK runs that session without recording any cookies or events,
even if the visitor accepted.
Fix
Push `{ cookiesEnabled: true }` from the callback that fires when the visitor
accepts your cookie consent prompt:
JS
```
// Inside your CMP "accept" callback:
window.CFQ = window.CFQ || [];
window.CFQ.push({ cookiesEnabled: true });
```
This call can be made at any point after the install script runs — the SDK
replays the last queued value and then subscribes for future changes. If a
visitor declines consent and the signal is never pushed, the SDK runs without
writing cookies for that session; this is the intended behavior.
See [SDK Options](../docs/sdk-options.html) for the cookie consent
configuration. If event data is still missing after fixing the consent flow,
see [Missing Data](../docs/missing-data.html).
## SDK loads but no variants appear — trackingOnly: true is set
Symptom
Coframe loads correctly and treatment events are visible in the analytics output,
but no content or visual changes are applied to the page on any page load.
Cause
When `trackingOnly: true` is set in the config, the SDK runs in observation
mode. It records which treatment a visitor would receive and emits the
corresponding analytics events, but it does not apply any changes to the page.
Anti-flicker is also disabled in this mode, since there are no visual changes
to protect against.
This mode is commonly used during an initial integration phase to validate that
event flow is correct before enabling live variant delivery. If it is left in
the config after that phase, variants never appear regardless of experiment
status.
Fix
If you want Coframe to apply variant changes to the page, remove
`trackingOnly: true` from your config object, or set it to `false`. If you are
intentionally in an observation or audit phase, keeping it enabled is correct.
See [SDK Options](../docs/sdk-options.html) for tracking-only mode
details and when to use it.
## Related links
- [Anti-Flicker](../docs/anti-flicker.html)
- [SDK Options](../docs/sdk-options.html)
- [CFQ Commands](../docs/cfq-commands.html)
- [React integration guide](../docs/react.html)
- [Debug Checklist](../docs/debug-checklist.html)
- [Missing Data](../docs/missing-data.html)