Skip to content

Install Dialog via Google Tag Manager

This guide deploys the Dialog widget through Google Tag Manager — a no-code path you set up entirely from GTM. It is for stores that are not on Shopify or Prestashop and have no frontend developer available. If that’s not exactly your situation, another path serves you better — check the limits below before you commit.

Most disappointments with GTM installs are one of these known limits, not bugs. Read this before picking the path.

GTM can:

  • Deploy the Dialog widget on your product pages with zero storefront code.
  • Pass the product ID (and the selected variant) to Dialog via GTM variables.
  • Forward add_to_cart and purchase events to Dialog via the GTM tracking bridge.

GTM cannot:

  • Refresh your cart UI after a product is added through Dialog. No GTM tag has visibility into your application state. Your frontend developer must add a small JS snippet listening to the dialog:cart:updated event on document to re-render your cart icon / mini-cart — see Add to cart issues for the exact pattern. Without it, visitors must reload the page to see the cart update. This is a hard limit of GTM, not something support can configure away.
  • Load the widget instantly or blend it into your design system. The widget loads via GTM after the rest of the page: visitors get a delay and a layout shift before it appears.
  • Track conversions by itself. Add-to-cart and checkout attribution need the extra tags described in the GTM tracking bridge — skip them and your dashboard numbers will be wrong.

GTM is the right fit when all of the following are true:

  • Your store is not on Shopify (use the Shopify app instead — it covers data ingestion AND frontend in one go).
  • Your store is not on Prestashop (use the Prestashop module instead).
  • You don’t have frontend developers available to wire the SDK or the React / Vue components.
  • You do have GTM already installed on your site (or someone who can install it).

If you have a React or Vue storefront, prefer the components. If you have any other frontend (Svelte, server-side templating, vanilla JS), prefer the SDK. GTM should be the last-resort when none of those are feasible.

  • A Google Tag Manager account with a container deployed on your site.
  • Your Dialog API key (provided by the Dialog team after you create an API Integration organization at app.askdialog.com/sign-up).
  • The product ID available in JavaScript on your product pages — typically via dataLayer.push, a global JS variable, or a DOM attribute.
  • A catalog already uploaded to Dialog so the assistant has content to answer with. See Catalog integration.

Step 1: Make sure GTM is live on your site

Section titled “Step 1: Make sure GTM is live on your site”

This guide assumes GTM is already deployed. If it isn’t, install the standard GTM snippet on every page (see Google’s own setup guide). For the Dialog tag to do anything useful, it needs to fire on at least your product pages.

Step 2: Create a variable for the product ID

Section titled “Step 2: Create a variable for the product ID”

Dialog needs to know which product the visitor is looking at. Create a GTM variable that returns the product ID.

In GTM, go to VariablesUser-Defined VariablesNew:

  • Name: Dialog Product ID
  • Type: depends on how the product ID is exposed on your site.

Data Layer Variable — if your site pushes the product ID to the dataLayer on product pages:

  • Type: Data Layer Variable
  • Variable name: productId (or whatever key your dataLayer uses).

Custom JavaScript — if the product ID lives on a global JS variable:

function() {
return window.myApp.currentProduct.id;
}

DOM Element — if the product ID is in a DOM attribute:

  • Type: DOM Element
  • Selection method: CSS Selector
  • Element selector: [data-product-id]
  • Attribute name: data-product-id

In GTM, go to TagsNew:

  • Name: Dialog - Instant Block
  • Type: Custom HTML
  • HTML:
<script src="https://cdn.askdialog.com/assets/dialog-instant.js?productId={{Dialog Product ID}}&apiKey=YOUR_API_KEY&target=YOUR_CSS_SELECTOR&position=afterend"></script>

Replace YOUR_API_KEY with your Dialog API key, and YOUR_CSS_SELECTOR with a CSS selector targeting where you want the Dialog block to appear on the product page.

ParameterRequiredDescription
productIdYesThe product ID displayed on the current page
apiKeyYesYour Dialog API key
targetYesA CSS selector targeting the element next to which Dialog is inserted
positionNoInsertion position relative to the target (default: afterend)
bridgesGaAddToCartNoSet to true if you also forward GA add_to_cart to Dialog via the tracking bridge — prevents a duplicate user_added_to_cart on assistant add-to-cart
ValueDescription
beforebeginBefore the target element
afterbeginInside the target, before its first child
beforeendInside the target, after its last child
afterendAfter the target element (default)

Add a trigger to the tag so it only fires on product pages:

  • Type: Page View
  • Fires on: Some Page Views
  • Condition: a page-path condition that matches your product URLs. Examples:
    • WooCommerce / WordPress: Page Path contains /product/
    • Magento: Page Path matches the regex ^/.+\.html$ (or scope it tighter)
    • Custom ecom: whatever pattern your product URLs use
  1. In GTM, click Preview (top right).
  2. Enter a product page URL from your site.
  3. Verify that:
    • The Dialog - Instant Block tag fires.
    • The product questions block appears on the page.
    • Suggestions load correctly.
    • The input field lets you ask a question and opens the Dialog assistant.

When testing passes, click Submit in GTM to publish the container.

If your product pages have variants (sizes, colors, etc.), push the currently selected variant ID to Dialog so add-to-cart actions use the exact SKU the visitor picked — not the parent product ID.

Add this inline, synchronous snippet as a GTM Custom HTML tag firing before dialog-instant.js on the same product page view. It buffers setVariant calls fired before the main script finishes loading, so no variant change is lost during the script download window:

<script>
window.dialog = window.dialog || {};
window.dialog._queue = window.dialog._queue || [];
window.dialog.setVariant =
window.dialog.setVariant ||
function (args) {
window.dialog._queue.push(['setVariant', args]);
};
</script>

This is the same pattern used by gtag, fbq, and Segment. When dialog-instant.js loads, it drains _queue and replaces the stub with the real implementation. The || guard keeps the snippet idempotent if your GTM tag fires more than once.

Step 2: Create a variable for the variant ID

Section titled “Step 2: Create a variable for the variant ID”

In GTM, VariablesNew, named e.g. Dialog Variant ID. The type depends on how your storefront exposes the currently selected variant — usually the same approach you used for Dialog Product ID (Data Layer Variable, Custom JavaScript, or DOM Element).

Create a second Custom HTML tag that fires whenever the visitor changes variant on the PDP:

<script>
window.dialog = window.dialog || {};
window.dialog._queue = window.dialog._queue || [];
window.dialog.setVariant =
window.dialog.setVariant ||
function (args) {
window.dialog._queue.push(['setVariant', args]);
};
window.dialog.setVariant({ variantId: '{{Dialog Variant ID}}' });
</script>

Trigger this tag on a Custom Event with event name variant_changed (or whatever event name your storefront pushes), where your storefront calls dataLayer.push({ event: 'variant_changed', variantId: 'X' }) whenever a variant is selected.

Alternative: dialog:variant-changed window event

Section titled “Alternative: dialog:variant-changed window event”

If you’d rather dispatch a DOM event than call a method, dispatch a dialog:variant-changed event on window:

window.dispatchEvent(
new CustomEvent('dialog:variant-changed', {
detail: { variantId: 'SELECTED_VARIANT_ID' },
}),
);

Dialog listens for this event and forwards to the same internal setter. Same validation, same behavior. Use whichever style fits your storefront.

When the visitor interacts with the widget, Dialog picks the variant in this order:

  1. Latest value pushed via window.dialog.setVariant or the dialog:variant-changed event.
  2. The textContent of an element matching .product-id on the page (legacy fallback).
  3. undefined — Dialog adds the parent product to cart.

For new installs, prefer setVariant. The .product-id DOM fallback is supported for backward compatibility with older installs.

  1. In GTM Preview mode, navigate to a product page on your site.
  2. Open the browser DevTools console.
  3. Paste:
    window.addEventListener('enableDialogAssistantEvent', (e) =>
    console.log('[dialog]', e.detail.payload.selectedVariantId),
    );
  4. Pick a variant on the page, then click a suggestion in the Dialog widget.
  5. The console should log the selected variant ID — that’s what Dialog will use for add-to-cart.

The Dialog block adapts to your site via CSS variables. Override them in your site’s stylesheet to tune the look:

:root {
--dialog-primary-color: #000000; /* Primary color (buttons, accents) */
--dialog-cta-text-color: #ffffff; /* Button text color */
--dialog-shop-font-family: inherit; /* Font family */
}

Tracking add-to-cart and checkout from GTM

Section titled “Tracking add-to-cart and checkout from GTM”

GTM deploys the widget but it doesn’t automatically know when a visitor adds to cart or completes checkout outside the assistant. To attribute conversion correctly, wire those events via the GTM tracking bridge — two more GTM tags that forward add_to_cart and purchase events to Dialog.

IssueLikely causeSolution
Block doesn’t appearThe target selector doesn’t match any elementCheck the CSS selector in the browser devtools
productId is undefinedThe GTM variable returns undefined at load timeEnsure the product ID is available on the page before the tag fires
403 error on the APIInvalid or expired API keyVerify your API key with the Dialog team
Block appears in the wrong placeThe target or position parameter is not suitableAdjust the CSS selector and/or the position value
TypeError: window.dialog.setVariant is not a functionThe pre-init stub is missing and a setVariant call ran before dialog-instant.js finished loadingAdd the inline stub snippet from “Push the selected variant” — Step 1
[Dialog] setVariant: expected { variantId: string } ...You passed something other than { variantId: 'X' }Ensure variantId is a non-empty string; check that GTM is resolving the variable and quotes are preserved
Cart adds the parent product, not the selected variantsetVariant not wired up, or variant-change trigger isn’t firingVerify the Dialog Variant ID GTM variable resolves to the selected variant on the page; check the Custom HTML tag fires on every variant change