How-toChat widgetInstallation

How to Install a Chat Widget With Google Tag Manager (and When Not To)

Install a chat widget through a Google Tag Manager Custom HTML tag: the snippet to paste, triggers, consent settings, page exceptions, and when to skip GTM.

PepoChat TeamPublished Last verified 13 min read
Six stacked shipping containers in green, maroon, blue and orange, their doors stencilled with weights and capacities

Short answer

To install a chat widget with Google Tag Manager, create a Custom HTML tag, paste the vendor's JavaScript snippet inside script tags, fire it on the All Pages or a Window Loaded trigger with exceptions for pages like checkout, test it in Preview, then submit and publish a version. As of October 2026, GTM rebuilds script tags without their data attributes, so attribute-based snippets fail. Skip GTM when blockers, a strict CSP or container ownership get in the way.

Google Tag Manager is often the quickest way onto a website you do not edit every day. When its container already runs on every page and your team or agency has access, a new tag needs no theme change and no developer ticket. A chat widget fits that model with two catches: some install snippets break inside Tag Manager, and some sites are better served by a plain script tag.

This guide is for agencies, marketers and support leads who manage sites through Tag Manager. It covers the steps in Google's current menu names, the right snippet, triggers, consent settings, page exceptions, single-page apps, how Intercom and Tidio do it, when to skip Tag Manager, and troubleshooting.

PepoChat is our product; its loader's behaviour below was checked in its code and documentation on 22 October 2026. Every Tag Manager step comes from Google's help pages read the same day, and we read the Tag Manager code Google served that day to see what happens to a script tag inside a Custom HTML tag.

Why install a chat widget through Google Tag Manager?

Installing a chat widget through Google Tag Manager lets you add, change or remove it on every page from one web interface, without editing the site's theme, and every publish is saved as a version you can roll back. Google Tag Manager (GTM) is Google's tag management system: a container snippet on each page loads the tags you configure, and each tag runs when its trigger, in Google's words "a rule that determines when a specific tag should fire", says so.

Four things make it attractive for chat:

  • One place per site. The chat tag sits next to analytics in each client's container, so an agency running many sites, as in our guide to AI chatbots for agencies, needs no CMS logins to move it.
  • No theme edits. Code pasted into a theme footer can vanish in a theme update; a tag does not.
  • Rules without code. Triggers, exceptions and consent settings decide where and when the widget loads.
  • Versions. "Every time a container is published, a version of that container is recorded," Google says, so a bad change is undone by publishing the previous version.

How do you install a chat widget with Google Tag Manager?

You install a chat widget with Google Tag Manager in four steps: create a Custom HTML tag with the vendor's JavaScript snippet, attach a trigger, test it in Preview, and publish a new container version. A Custom HTML tag is the tag type that, in Google's words, "allows you to deploy a tag that isn't yet supported via Tag Manager".

  1. Copy the JavaScript snippet. In PepoChat, open Widget Setup, click JavaScript and copy the code, which already holds your Organization ID; the install docs show every format. For other vendors, use their JavaScript or Tag Manager snippet, for the reason explained below.
  2. Create the tag. In Tag Manager, click Tags, then New, and name it, for example "Chat widget". Click Tag Configuration and select Custom HTML.
  3. Paste the code. Paste the snippet into the HTML field, wrapped as Google's note asks: "Always place JavaScript inside <script></script> HTML tags." Leave Support document.write unticked; PepoChat's loader does not use it.
  4. Choose the trigger. Click Triggering and pick the All Pages trigger. For a Window Loaded trigger, first click Triggers, then New, click Trigger Configuration and choose Window Loaded. Save the tag.

The finished tag for PepoChat:

<script>
  (function () {
    var script = document.createElement("script");
    script.src = "https://widget.pepochat.com/widget.js";
    script.async = true;
    script.setAttribute("data-organization-id", "YOUR_ORGANIZATION_ID");
    document.body.appendChild(script);
  })();
</script>

Two optional lines go before appendChild: script.setAttribute("data-preload", "false"); loads the chat frame only when a visitor clicks the launcher, and script.setAttribute("data-position", "bottom-left"); moves the launcher to the left corner.

Which trigger should the chat tag use?

Use the All Pages trigger for most sites, or a Window Loaded trigger when page speed matters most, because a chat launcher never needs to load before your content. Google describes five page view trigger types:

Trigger typeWhen it fires, per Google's helpUse it for a chat widget?
Consent InitializationBefore every other trigger, for tags that set or update consentNo: reserve it for your consent platform's tag
InitializationBefore all other triggers except Consent InitializationNo: chat is not that urgent
Page View (the All Pages trigger)Fires "immediately when the web browser begins to load a page"Yes, the usual choice
DOM ReadyAfter the browser has finished constructing the page's HTMLYes; PepoChat's loader waits for this point anyway
Window LoadedAfter the page has fully loaded, including images and scriptsYes, when chat should wait for everything else

Trigger descriptions from Google's Tag Manager help on page view triggers, read 22 October 2026.

PepoChat's loader draws the launcher once the page's HTML is ready and fetches the chat frame in idle time after the page loads, so the trigger mainly decides when its 3.4 KB compressed loader downloads. Intercom recommends Window Loaded for its Messenger "so your website loads as fast as possible".

Why does the HTML snippet fail inside a Custom HTML tag?

An HTML snippet that keeps its settings in data attributes fails in Google Tag Manager because GTM rebuilds every script tag in a Custom HTML tag, and in the code Google served on 22 October 2026 it copies only the address, id and character set. We read that injection code in four live containers that day, and it was identical in all four.

When a Custom HTML tag fires, Tag Manager does not insert your script tags as written. For each script with a src, it creates a fresh script element with the address, the id, the character set and, if the page has one, the page's CSP nonce. A data-organization-id or any other data attribute stays behind. Google's Custom tags help page does not mention this; it notes only that Tag Manager minifies the code.

PepoChat's loader reads its settings from document.currentScript, the script element that is running, or else from the first script on the page whose address contains "widget" and carries a data-organization-id. With the HTML snippet in a Custom HTML tag, neither has the attribute, so the loader logs "data-organization-id attribute is required" in the console and draws nothing. The JavaScript snippet works because its own code creates the script element and sets the attribute, so the loader finds it on document.currentScript, as the behaviour and API docs describe.

How do you test a chat widget tag before publishing it?

Test the chat tag in Preview mode, which connects your site to Tag Assistant "so that you can inspect which tags fired and in which order", while visitors keep the published container until you publish. Six checks cover it:

  1. Start Preview. In the Workspace tab, click Preview at the top right, enter your website URL in Tag Assistant and click Connect. Untick Include debug signal in the URL only if the debug parameter breaks your pages.
  2. Confirm the tag fired. Your site opens in a new window marked Connected. Back in Tag Assistant, click Continue, select the event your trigger uses, such as Container Loaded for All Pages, and check the chat tag is among the tags that fired.
  3. Confirm the loader ran. In the site window's developer tools, the Network panel should show widget.js loading, and typing window.EchoWidget in the Console should return an object with init, show, hide and destroy.
  4. Hold a test chat. Ask a question your knowledge base answers and check the conversation arrives in your team inbox. If you preview on a staging domain, add it to the allowed domains list first.
  5. Visit an excluded page. If you added exceptions, open a checkout page and confirm the tag did not fire.
  6. Publish. Click Submit, keep Publish and Create Version selected, enter a Version Name and Version Description such as "Chat widget, all pages except checkout", and click Publish.

To undo a bad publish, click Versions, click the last version that worked, then Action and Publish.

Whether a chat widget must wait for consent depends on what it stores on or reads from the visitor's device, and Google Tag Manager only enforces the answer you choose: Consent Mode on its own does not hold back a chat tag. Consent Mode, Google says, "allows web and app developers to adjust tag and app SDK behavior based on user consent choices", but "Non-Google tags will not change their behavior based on consent mode."

For a non-Google tag such as a chat widget, the switch sits on the tag. Google's consent mode support page places it under Advanced Settings > Consent Settings, with three Additional Consent Checks: Not set, the default, with no additional checks; No additional consent required; and Require additional consent for tag to fire, where the tag "will only fire if the status of all specified consent types are 'granted' when the tag is triggered."

If your assessment says the chat must wait, set it up in three steps:

  1. Choose Require additional consent for tag to fire and add the consent type you filed chat under, such as functionality_storage, storage that "supports the functionality of the website or app" in Google's description. Google also lets you add custom consent types your consent platform supports.
  2. Add a second firing trigger for the moment a visitor accepts, such as a Custom Event trigger on the event your consent platform sends when choices are saved, because the check happens only when a trigger fires.
  3. Set Tag firing options to Once per page, so the widget loads once even when both triggers fire.
A yellow traffic light against a clear blue sky with only its green signal lit
A chat tag set to require consent works like this signal: Tag Manager checks the consent state when the trigger fires, and the tag runs only on green.

For that assessment, PepoChat sets no cookies on your site; its chat frame on widget.pepochat.com keeps a session ID in its own storage, and a visitor session is created only when someone opens the chat. In our cookie consent test on 19 October 2026 it stored nothing before a click, though with preloading on, a returning visitor's stored session ID is read on later pages; data-preload="false" makes that click-only. Whether that counts as strictly necessary is for you or your legal adviser to judge; this guide is not legal advice. To review all tags at once, select Enable consent overview under Admin > Container Settings.

How do you hide a chat widget on some pages with Google Tag Manager?

To hide a chat widget on some pages with Google Tag Manager, add a trigger exception that matches those pages, for example a Page Path containing /checkout, so the chat tag never fires there. Google's help on firing triggers and trigger exceptions defines a trigger exception, or blocking trigger, as "a kind of trigger that can be used to block another trigger's ability to fire under certain conditions."

First click Triggers, then New, click Trigger Configuration and choose a page view trigger type. Under This trigger fires on, select Some Events and add a condition such as Page Path contains /checkout. Then open the chat tag, click Triggering, and click Add in the Exceptions section. Use the same trigger type as the firing trigger, Window Loaded for a Window Loaded tag, and confirm in Preview that the tag did not fire there.

Page typeShow the launcher?WhyGTM exception (example)PepoChat API instead
Checkout and paymentUsually hideA floating button can cover the pay button on a small screenPage Path contains /checkoutEchoWidget.destroy() on entry, EchoWidget.init({}) on exit
Cart and order confirmationUsually showShipping, returns and "did my order go through?" questions start hereNoneNone needed
Privacy, terms and cookie pagesUsually showVisitors ask how to delete data or cancel; keep the policies in the knowledge base so answers matchNoneNone needed
Paid ad landing pagesTest bothOne call to action can convert better, but an unanswered pre-sale question loses the leadPage Path contains /lp/None needed
Logged-in app or customer portalHide, unless app users should chatThe agent answers from your knowledge base, not from the account on screenPage URL contains app.example.comEchoWidget.destroy() on app routes
Embeds, kiosks and full-screen toolsHideThe corner is already in usePage Path contains /embedEchoWidget.destroy()

These are starting points, not Google or PepoChat rules; test changes against your own sales and support numbers.

A white No Entry road sign with a red circle and white bar, seen from below against a deep blue sky and clouds
A trigger exception is Tag Manager's no-entry sign: the chat tag fires on every page except the ones the exception matches, such as checkout.

One trap with the widget's own API: EchoWidget.hide() only closes the chat window, and the launcher stays. To take the launcher off a page after the loader has run, call EchoWidget.destroy(), and bring it back with EchoWidget.init({}). For where chat helps visitors most, see our website chatbot best practices.

How do you run a chat widget in a single-page app through Google Tag Manager?

In a single-page app the page never reloads, so a chat tag on the All Pages trigger fires once and the launcher stays on every route; to change it per route, also fire the tag on Google Tag Manager's History Change trigger. Google says that trigger "will fire a tag when the URL fragment changes or when a site uses the HTML5 pushstate API".

Create it under Triggers, New, Trigger Configuration, History Change. Give one Custom HTML tag two firing triggers, All Pages and History Change, and set Tag firing options to Once per event, since Once per page would stop it after the first load. The tag loads the widget once, then removes or restores the launcher as routes change:

<script>
  (function () {
    // Routes where the launcher should not appear: edit the paths.
    function excluded() {
      return /^\/(checkout|account)(\/|$)/.test(location.pathname);
    }
    function apply() {
      var chat = window.EchoWidget;
      if (!chat) return;
      if (excluded() && !window.pepoChatRemoved) {
        chat.destroy();
        window.pepoChatRemoved = true;
      } else if (!excluded() && window.pepoChatRemoved) {
        chat.init({});
        window.pepoChatRemoved = false;
      }
    }
    if (window.pepoChatRequested) {
      apply();
      return;
    }
    window.pepoChatRequested = true;
    var script = document.createElement("script");
    script.src = "https://widget.pepochat.com/widget.js";
    script.async = true;
    script.setAttribute("data-organization-id", "YOUR_ORGANIZATION_ID");
    script.onload = apply;
    document.body.appendChild(script);
  })();
</script>

A visitor who is chatting keeps the open conversation while moving between allowed routes, because nothing is re-created. If your app routes with the URL fragment, test location.hash instead of location.pathname.

How do Intercom and Tidio install through Google Tag Manager?

Intercom installs through a Google Tag Manager template, Tidio documents no Tag Manager install and instead sends chat events into the data layer, and PepoChat uses a Custom HTML tag with its JavaScript snippet, as of October 2026.

VendorInstall route in its docsTrigger adviceChat events in the data layer
IntercomCommunity Template Gallery: "Intercom (by Intercom)", Install method, workspace IDWindow LoadedNot covered in its GTM article
TidioNo GTM install guide; paste its JavaScript code above the closing body tagNone givenYes, after you connect its Google Tag Manager integration
PepoChatCustom HTML tag with the JavaScript snippet from Widget SetupAll Pages or Window LoadedNone

From Intercom's and Tidio's help centers and PepoChat's code and docs, read 22 October 2026.

Intercom's Tag Manager article adds an Update method for single-page apps and later logins. Tidio's only Tag Manager article among the 234 in its English help center shows how events such as tidio_widget_open reach the data layer, caught with a Custom Event trigger matching ^tidio_\w+. PepoChat has no template and pushes no events to the data layer, so Tag Manager cannot see chat opens, a limit if you track chat as a conversion step.

When should you not use Google Tag Manager for a chat widget?

Skip Google Tag Manager for a chat widget in five cases: content blockers stop Tag Manager for some visitors, the site enforces a nonce-based CSP, consent gating holds back the whole container, support cannot publish the container, or the site already loads the widget.

Content blockers remove Tag Manager. EasyPrivacy, which the EasyList project calls "an optional supplementary filter list" and tests with Adblock Plus, AdBlock, uBlock Origin and AdGuard, blocks googletagmanager.com; the copy we downloaded on 22 October 2026 lets Tag Manager's script run on only 465 named sites. Elsewhere, its users never see a chat that lives inside the container. We found no rule naming widget.pepochat.com in EasyList or EasyPrivacy that day; both lists are on easylist.to.

A nonce-based Content Security Policy. Google's guide to Tag Manager with a Content Security Policy recommends a nonce on the container snippet, after which "Tag Manager will then propagate the nonce to any scripts that it adds to the page", and it discourages 'unsafe-inline'. With Tag Manager in the middle, test the chat tag in Preview with the policy switched on before relying on it; a direct tag needs only https://widget.pepochat.com in script-src and frame-src. Developers can also block every Custom HTML tag with a gtm.blocklist entry for the customScripts class.

Consent gating holds back the whole container. In Google's basic consent mode, "you prevent Google tags from loading until a user interacts with a consent banner", and some setups hold back every tag the same way. The chat then waits too, even when your assessment would let it load earlier.

Support cannot publish. In Google's permission levels, Edit users "make edits but not create versions or publish", and Approve users create versions "but not publish". If marketing or a former agency owns publishing, support cannot fix a broken chat quickly.

The widget is already on the site. A theme footer, the WordPress plugin or app code may load it. PepoChat ignores a second copy and logs "already initialized", but the copy that runs first wins, so settings such as data-preload in the other copy silently do nothing. On WordPress, the plugin's Hide on these pages setting handles page rules without Tag Manager.

If a site has no container yet, adding one just for chat costs more than the chat. The containers on Tidio's, Crisp's, Intercom's and LiveChat's own home pages weighed 176 to 211 KB compressed on 22 October 2026, against 3.4 KB for PepoChat's loader; containers grow with their tags. Our page speed measurements show what the widgets themselves add.

Why does the tag fire but the chat widget not show?

When the chat tag fires but no widget appears, the cause is usually one of five things: a lost data attribute, a CSP blocking the script or frame, a domain that is not allowed, a wrong Organization ID, or another copy that loaded first.

SymptomWhere you see itLikely causeFix
No launcher; "data-organization-id attribute is required"ConsoleHTML snippet in a Custom HTML tagReplace it with the JavaScript snippet
No launcher; a CSP error naming widget.pepochat.comConsolescript-src does not allow the widgetAdd https://widget.pepochat.com to script-src
"The chat couldn't load" 15 seconds after openingChat windowframe-src blocks the frame, or the network or a blocker doesAdd the origin to frame-src; test in a clean browser profile
"This website is not allowed to use this chat widget."Chat windowThe domain is missing from allowed domainsAdd it in Widget Customization
"Organization not valid"Chat windowWrong or cut-off Organization IDCopy the snippet again from Widget Setup
"already initialized"; your settings are ignoredConsoleThe theme, a plugin or another tag loads it tooKeep one install
Tag listed as not firedTag AssistantTrigger conditions, an exception, or consent not grantedCheck the trigger, exceptions and Consent Settings
Works in Preview, not for visitorsLive siteContainer not published, a cached page, or Tag Manager blockedSubmit and publish, purge the cache, test without blockers

Messages as of 22 October 2026, from PepoChat's loader code and docs.

What to do next

  • Copy the JavaScript snippet from Widget Setup, build the tag with an exception for checkout, and run the six Preview checks before you publish.
  • If Tag Manager is the wrong fit, follow our guide to adding a chat widget with one script tag, which covers each site builder and the CSP lines.
  • To try it on your own container, create a free PepoChat workspace: every feature is on the free plan, which includes 200 AI replies a month.

Frequently asked questions

Can you install a chat widget with Google Tag Manager?
Yes. Create a Custom HTML tag, paste the vendor's JavaScript snippet inside script tags, attach the All Pages or a Window Loaded trigger, test it in Preview and publish a version. As of October 2026, Tag Manager rebuilds script tags without their data attributes, so a snippet that keeps its settings in data attributes needs its JavaScript version or a vendor template.
Does loading a chat widget through GTM slow the site?
Not if Tag Manager is already on the site. The chat tag adds a few lines to the container, and the widget's own loader downloads exactly as it would from a direct tag. Adding Tag Manager only for chat costs more: four chat vendors' own home page containers weighed 176 to 211 KB compressed in October 2026. A Window Loaded trigger keeps chat out of the way.
Should a chat widget fire before cookie consent?
Only if everything it stores on or reads from the visitor's device fits an exemption such as strictly necessary, which is a judgement for you or your legal adviser. Tag Manager enforces your answer: Consent Mode alone does not hold back a non-Google tag, so set Require additional consent for tag to fire on the chat tag and add a trigger for the consent update.
How do I hide the chat widget on some pages with GTM?
Add a trigger exception to the chat tag. Create a trigger of the same type as the firing trigger, set it to fire on Some Events where Page Path contains a path such as /checkout, then add it under Exceptions in the tag's Triggering section. In a single-page app, use the widget's API instead: PepoChat's EchoWidget.destroy() removes the launcher and init() restores it.
Why does my tag fire but the chat widget doesn't show?
Usually the snippet lost its configuration or something blocks it. Tag Manager drops data attributes from script tags, so attribute-based snippets fail; a Content Security Policy may block the script or frame; the site may be missing from the vendor's allowed domains; or another copy of the widget loaded first. The browser console or the message in the chat window usually names the cause.
Is a direct script tag better than GTM?
A direct script tag is better when you control the site's code, enforce a nonce-based Content Security Policy, or need chat to reach visitors whose content blockers stop Tag Manager. Tag Manager is better when its container is already on every page, the site's code is hard to change, and you want versions, permissions and page rules without waiting for a developer.

Try this on your own site in ten minutes

PepoChat includes every feature on the free plan — 200 AI replies and 5 knowledge sources a month, no credit card.