How to gate a chat widget behind cookie consent on any website platform

Stop a chat widget setting cookies or storing data before a visitor has agreed to it. The code is the same everywhere; where you paste it is not. This covers 35 platforms, 19 of which gate custom code behind a paid plan.

Why this matters

Chat widgets almost always store something — a conversation ID at minimum — and under GDPR and similar regimes that usually requires consent before it happens, not after. The fix is not a banner on top of a widget that has already loaded; it is not loading the widget until consent exists. That means injecting the script from your consent callback rather than putting it in the page directly.

What you paste

<script>
  // Load the widget only once the visitor has accepted functional cookies.
  window.addEventListener("consent:accepted", function (event) {
    if (!event.detail || !event.detail.functional) return;
    var s = document.createElement("script");
    s.src = "https://example.com/widget.js";
    s.defer = true;
    s.dataset.site = "your_public_key";
    document.body.appendChild(s);
  });
</script>

The event name depends on your consent tool — Cookiebot, Osano, CookieYes and Google Consent Mode all expose something equivalent. The pattern is the same: nothing loads until consent fires.

Where it goes, by platform

The code is identical everywhere. The screen you paste it into is not, and neither is whether your plan allows it — 19 of 35 platforms require a paid plan for custom code.

PlatformWhere it goesPlan needed
ShopifyOnline Store → Themes → Edit code → layout/theme.liquidAll plans can edit theme code. Checkout pages are restricted to Shopify Plus.
WooCommerceThe parent theme's footer.php, or a code-snippets pluginNo plan gate — WooCommerce is self-hosted, so you control the code.
BigCommerceStorefront → Script ManagerScript Manager is available on all plans.
Adobe CommerceContent → Design → Configuration → HTML Head / FooterAvailable on Adobe Commerce and Magento Open Source alike.
PrestaShopThe theme's templates/_partials/footer.tplSelf-hosted, so no plan gate.
EcwidThe host page, not Ecwid itselfCustom code on Instant Site requires a paid plan.
Squarespace CommerceSettings → Developer Tools → Code Injection → FooterCode Injection requires a Business plan or higher.
OpenCartcatalog/view/theme/<theme>/template/common/footer.twigSelf-hosted, so no plan gate.
Shift4ShopSettings → Design → Themes & Styles → Edit TemplateTemplate editing is available on all paid plans.
WordPressThe active theme's footer.php, or a code-snippets pluginSelf-hosted WordPress has no gate. WordPress.com requires a Business plan for custom code.
WebflowProject settings → Custom code → Footer codeCustom code requires a paid Site plan; it is not available on the free staging domain alone.
SquarespaceSettings → Developer Tools → Code Injection → FooterCode Injection requires a Business plan or higher. Personal plans cannot add custom code.
WixSettings → Custom Code → Add Custom CodeCustom code requires a paid Premium plan and a connected domain.
FramerSite settings → General → Custom Code → End of <body>Custom code requires a paid site plan.
GhostSettings → Code injection → Site FooterAvailable on Ghost(Pro) and self-hosted alike.
WeeblySettings → SEO → Footer CodeCustom code requires a paid plan.
DudaSettings → Head HTML / Body End HTMLAvailable on all paid Duda plans.
CarrdAn Embed element set to Code, placed at the end of the pageEmbed elements require Carrd Pro.
BubbleSettings → SEO / metatags → Script in the bodyCustom code requires a paid Bubble plan.
SoftrSettings → Custom code → BodyCustom code requires a paid plan.
Next.jsapp/layout.tsx, using next/scriptNone — you control the code.
Reactpublic/index.html, before the closing </body> tagNone.
Vueindex.html, before the closing </body> tagNone.
Nuxtnuxt.config.ts, under app.head.scriptNone.
Astrosrc/layouts/Layout.astro, before </body>None.
SvelteKitsrc/app.html, before %sveltekit.body% closesNone.
Gatsbygatsby-ssr.js, via onRenderBodyNone.
Hugolayouts/partials/footer.htmlNone.
Jekyll_layouts/default.html or _includes/footer.htmlNone.
plain HTMLEvery page's closing </body> tagNone.
HubSpot CMSSettings → Website → Pages → Site footer HTMLAvailable on CMS Hub Starter and above.
DrupalThe theme's html.html.twig, or the Asset Injector moduleSelf-hosted, so no plan gate.
JoomlaThe template's index.phpSelf-hosted, so no plan gate.
Notion sitesA hosting layer such as Super or Potion, not Notion itselfDepends on the hosting layer; most require a paid plan for custom code.
Shopify Hydrogenapp/root.tsx, inside the document bodyNone beyond your Shopify plan.

How to check it worked

  • Open the site in a private window, decline consent, and confirm no widget script appears in the Network tab.

  • Check Application → Cookies and confirm no widget cookies exist before consent.

  • Accept consent and confirm the widget then loads without a page refresh.

What goes wrong

  • Loading the widget and hiding it with CSS. It has already set its cookies; hiding it changes nothing legally.

  • Forgetting that a returning visitor's stored consent should load the widget on the next page load without waiting for the event.

  • Blocking the widget so thoroughly that visitors who accept still cannot reach support.

Questions

Is a chat widget a functional or a marketing cookie?
Usually functional, since it exists to deliver a service the visitor asked for — but this depends on what the vendor stores and whether they use it for anything else. Read their cookie declaration rather than assuming, and take your own legal advice.
Does this apply outside the EU?
Increasingly yes. The UK, Brazil, and several US states have comparable rules. Consent-gating by default is the simpler position to maintain.

Related

While you are in that field.

RubyRep installs through the same screen, in the same visit. Enter your site and we will read it and hand you the line to paste.

https://

Takes about a minute. No credit card.

All how-to guides