# Webflow integration: install FlowConsent the right way

Install FlowConsent on Webflow: paste the snippet in Site settings → Custom code, publish, and remove the GA Measurement ID from Apps & Integrations.

> Canonical: https://www.flowconsent.com/en/doc/webflow-integration
> Last updated: 2026-07-30
Installing FlowConsent on Webflow takes two steps: paste your snippet into **Site settings → Custom code → Head code** and publish — then **remove any Google Analytics Measurement ID from Site settings → Apps & Integrations**. That second step is not optional: Webflow injects its native GA integration above your custom code, where no consent tool can block it.

## Step 1 — Paste the snippet in Head code

Copy your snippet from **Builder → Deployment → Integration** — a **Webflow** tab generates it for you. It has two parts, and their order matters:

```html title="Site settings → Custom code → Head code"
<script>
// FlowConsent Loader - place BEFORE any other script in the <head>
window.dataLayer=window.dataLayer||[];
function gtag(){dataLayer.push(arguments);}
gtag('consent','default',{
  'ad_storage':'denied',
  'analytics_storage':'denied',
  'ad_user_data':'denied',
  'ad_personalization':'denied',
  'wait_for_update':500
});
gtag('set','url_passthrough',true);
gtag('set','ads_data_redaction',true);
</script>
<!-- FlowConsent CMP -->
<script src="https://YOUR-LICENSE-CODE.consent.flowconsent.com/cookie-manager.js?code=YOUR_LICENSE_CODE"></script>
```

The first block is the **Consent Mode stub**: it records `denied` defaults for all four Google consent signals at HTML parse time. The second loads the banner itself. The stub comes first because the banner script loads asynchronously — the stub, inline, always wins the race against any Google tag loaded later.

In Webflow: **Site settings → Custom code → Head code**, paste the snippet at the very top, save, then **publish** the site. Custom code only ships on publish — the Designer preview does not run it.

## Step 2 — Remove the GA Measurement ID from Apps & Integrations

> [!WARNING]
> If a Google Analytics Measurement ID is set in **Site settings → Apps & Integrations**, Webflow injects its own GA loader **above your custom code**. Its `gtag('config')` then enters the dataLayer before your consent defaults, Google processes it without any restriction, and analytics cookies are set no matter what the banner does. **No CMP can win this race** — the only fix is to remove the Measurement ID from that panel and declare Google Analytics in **Builder → Services** instead, so the banner injects it only after consent.

This is not theoretical: Consent Mode defaults only apply to tags that enter the dataLayer **after** them. A `gtag('config', 'G-XXXX')` queued earlier is processed as if consent had never been denied.

## How FlowConsent detects the lost race

You do not have to discover this by auditing cookies manually. When the banner boots, it inspects the dataLayer: if a `gtag('config')` entry precedes the consent defaults, it logs an explicit error in the browser console and reports a `ConsentDefaultRaceLost` event to FlowConsent telemetry, naming the affected tag IDs. If you see that error, a tag is being injected above the snippet — on Webflow, that is almost always the Apps & Integrations panel.

## Verify the installation

The **installation assistant** (Builder → Integration) checks the live page for you, in the order things actually break:

1. the FlowConsent loader is present, with **your** license code;
2. the Consent Mode stub is present;
3. the stub **precedes** every Google tag — and it specifically flags a tag injected by Webflow's site settings.

> [!TIP]
> Finish with a refusal scan from the **Compliance** tab: it loads your published site in a real browser, refuses consent, and confirms that nothing fires. That is the proof the installation is correct — not the fact that the banner is visible.
