# Use FlowConsent with Google Tag Manager

Using FlowConsent with Google Tag Manager: put the snippet in the <head> above the GTM container, never as a GTM tag, then set consent checks on your tags.

> Canonical: https://www.flowconsent.com/en/doc/install-google-tag-manager
> Last updated: 2026-10-01
With Google Tag Manager, the FlowConsent snippet goes in your site's `<head>`, **above the GTM snippet**, and never as a tag inside GTM: loaded from the container, the banner would arrive too late for prior blocking. Setup takes two steps: place the snippet before GTM, then make sure every tag in your container respects consent (automatic for Google tags, to be configured for the others).

## Before you start

- An account on [app.flowconsent.com](https://app.flowconsent.com) (the Free plan costs nothing, needs no credit card and covers up to 25,000 sessions per month).
- A banner created and deployed. On the Free plan, deployment goes through your own Cloudflare account ([Cloudflare guide](/en/doc/cloudflare-deployment)); on Pro and Enterprise, it is one click.
- Edit access to your site's `<head>` code and to your GTM container.

## Step 1: Paste the snippet above the GTM snippet

Copy your snippet from **Builder → Deployment → Integration** (**HTML / No-code** tab). Paste it **right after the opening `<head>` tag**, and keep the `<!-- Google Tag Manager -->` snippet below it:

```html title="Your site's <head>"
<head>
  <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>

  <!-- Google Tag Manager -->
  <script>(function(w,d,s,l,i){ /* code provided by GTM */ })(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
  <!-- End Google Tag Manager -->

  <!-- the rest of your <head> -->
</head>
```

The Consent Mode stub writes the `denied` defaults into the `dataLayer` before GTM starts: the container reads them when it loads, and every Google tag runs in denied mode until the visitor chooses. When the visitor decides, the banner sends `gtag('consent', 'update', …)` and GTM applies the new state. No template from the GTM gallery is needed.

The second GTM snippet (a `<noscript>` with an `<iframe>`, right after `<body>`) stays where it usually is.

## Why not load FlowConsent from GTM

> [!WARNING]
> Do not create a **Custom HTML** tag to load FlowConsent. The GTM container loads asynchronously: anything it injects arrives after the HTML has been parsed. GTM's **Consent Initialization - All Pages** trigger guarantees ordering inside the container, but not beyond it: scripts written directly in the page, or added by a plugin, run without waiting. Prior blocking requires FlowConsent to run before any tracker, which means in the HTML, above GTM.

The same logic applies when GTM is injected by a plugin or a native integration (a "GTM container ID" field in a CMS): if that code lands above your snippet, remove the ID from those settings and paste the GTM snippet yourself, below FlowConsent. If you renamed the `dataLayer` variable in the GTM snippet, switch it back to `dataLayer`: that is the name the stub uses.

## Step 2: Set consent on your GTM tags

In any tag, open **Advanced Settings → Consent Settings**. You will find two blocks there.

**Built-In Consent Checks.** Google tags (Google tag, GA4, Google Ads, Floodlight) read the Consent Mode v2 signals sent by FlowConsent themselves. Nothing to configure: on refusal, they switch to cookieless mode (`gcs=G100` pings, see the [Google Consent Mode guide](/en/doc/google-consent-mode)).

**Additional Consent Checks.** Non-Google tags (Meta Pixel, LinkedIn, Hotjar, Custom HTML…) have no built-in checks. Select **Require additional consent for tag to fire**, click **+ Add required consent** and enter the matching signal, for example `ad_storage` for an advertising pixel or `analytics_storage` for an analytics tool. The tag then fires only if those signals are granted at the moment its trigger occurs.

> [!TIP]
> GTM's **Consent Overview** page sorts your tags into two groups, consent configured or not: an easy way to make sure none is missed. A tag left on **Not set** fires without any additional check.

## Verify the installation

1. In GTM, click **Preview**: Tag Assistant opens on your site. Select a Google tag, then the **Consent** tab: the **On-page Default** column must show `Denied` for all four signals. After clicking **Accept**, the **On-page Update** column switches to `Granted`.
2. In a private window, the banner appears and the **Network** tab shows no third-party request before **Accept** (apart from Google `gcs=G100` pings, which comply with the refusal).
3. Run the [setup wizard](/en/doc/setup-wizard) (Builder → Integration): it checks that the loader is present with the right license code, that the stub is present, and that it precedes every Google tag, GTM included.
4. Finish with a refusal scan from the **Compliance** tab ([compliance verification](/en/doc/compliance-verification)).

## Do it from your AI agent (MCP)

FlowConsent has an official MCP server, `https://mcp.flowconsent.com`, usable from Claude, ChatGPT or any MCP client. You connect through OAuth 2.0 with your FlowConsent account, no API key required. Your agent fetches the snippet and placement instructions (`get_banner_snippet`, `get_setup_instructions`), verifies the installation with a real scan (`verify_consent_compliance`) and can set up recurring monitoring (`monitor_compliance`). It does not edit your site or your GTM container: it provides the snippet, the instructions and the verification.

Example request:

> Give me my banner snippet for my site that uses Google Tag Manager, remind me where it goes relative to the GTM snippet, then check that it is properly installed on https://mysite.com

Learn more: [MCP server](/en/doc/mcp-server) and [FlowConsent for AI agents](/en/mcp).

## Frequently asked questions

### Can I install FlowConsent only through a GTM tag?

No. A banner loaded by GTM arrives after the page HTML, so scripts that do not go through GTM would not be blocked in time. The snippet must sit in the `<head>`, above the GTM snippet.

### Do I need to configure anything for GA4 or Google Ads in GTM?

No. Their built-in consent checks read the Consent Mode v2 signals sent by FlowConsent. Only non-Google tags need additional consent.

### My Meta pixel in GTM still fires after a refusal: why?

Its tag is most likely on **Not set**. Switch it to **Require additional consent for tag to fire** with `ad_storage`, publish the container, then run a refusal scan again.

### Do I need a FlowConsent template from the GTM Community Template Gallery?

No. The stub in the snippet sets the defaults and the banner sends the consent update itself: GTM needs no extra template.
