# Google Tag Manager

Load ProductLense from a Custom HTML tag in Google Tag Manager that fires on all pages.

If your site's scripts are managed in Google Tag Manager, load ProductLense from a Custom HTML tag that fires on every page. Use the small loader below rather than pasting the plain script tag: it creates the ProductLense script element and sets `data-site` explicitly, so the attribute survives however Tag Manager injects the tag.

## Create the tag

1. Copy your site id from Settings → Sites in the ProductLense dashboard.
2. In Tag Manager, open Tags → New → Tag Configuration → Custom HTML.
3. Paste the snippet, replacing `SITE_ID`. Leave Support document.write turned off; it is not needed.
4. Under Triggering, choose All Pages (or Initialization - All Pages).
5. Save, then Submit and publish the container.

```html title="Custom HTML tag" {9}
<script>
  (function () {
    window.productlense = window.productlense || function () {
      (window.productlense.q = window.productlense.q || []).push(arguments);
    };
    var s = document.createElement('script');
    s.defer = true;
    s.src = 'https://api.productlense.app/a.js';
    s.setAttribute('data-site', 'SITE_ID');
    document.head.appendChild(s);
  })();
</script>
```

Set other attributes the same way, for example `s.setAttribute('data-exclude', '/admin/*');`. See [the script attributes](/docs/install/script-tag).

> [!NOTE]
> Do not add History Change triggers for ProductLense. The script records single-page app route changes itself, so an extra tag would only duplicate pageviews.

## Custom events and identify from Tag Manager

Fire events from another Custom HTML tag on the trigger you already use, such as a form submission or a dataLayer event:

```html title="Custom HTML tag: ProductLense signup event"
<script>
  window.productlense('event', 'Signup', { plan: {{DLV - plan}} });
</script>
```

```html title="Custom HTML tag: ProductLense identify"
<script>
  if ({{DLV - user_id}}) window.productlense('identify', String({{DLV - user_id}}));
</script>
```

`{{DLV - plan}}` and `{{DLV - user_id}}` stand for Data Layer Variables you define in the container. The queue stub in the loader keeps these calls until the ProductLense script has loaded. Use the same user id you store on the customer in your billing provider; see [how payments are attributed](/docs/revenue/attribution).

## Verify your installation

1. Publish the container (Preview mode works too), then open your site in a normal browser window.
2. Open the Live page in the ProductLense dashboard. Your visit appears within a few seconds.
3. In the browser's developer tools, the Network tab shows a request for `https://api.productlense.app/a.js` and a `POST` to `https://api.productlense.app/api/e` with status `204`.

Nothing is sent from `localhost` unless you add `s.setAttribute('data-dev', 'true');`. Ad blockers in your own browser may block the request. If the visit does not appear, follow [Verify your installation](/docs/install/verify).
