> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuração do Google Tag Manager

> Adicione o OneSignal Web Push ao seu site usando o Google Tag Manager (GTM), incluindo configuração do service worker, inicialização e configuração segura de Tags.

Este guia mostra como carregar e inicializar o OneSignal Web SDK usando o Google Tag Manager (GTM) e, opcionalmente, definir um External ID e Tags do OneSignal após a inicialização.

## Pré-requisitos

* Um site que suporte HTTPS.
* Você pode publicar alterações no GTM para o container do site.
* Você completou o fluxo de [configuração do Web SDK](./web-sdk-setup) do OneSignal até **Adicionar código ao site**. Isso lhe dá:
  * Um aplicativo OneSignal Web Push e o App ID.
  * A configuração do [OneSignal Service Worker](./onesignal-service-worker).

## Configuração

### 1. Configure seu aplicativo web do OneSignal

Siga a [configuração do Web SDK](./web-sdk-setup) até chegar à etapa **Adicionar código ao site**. É aqui que você obterá o OneSignal App ID.

<Frame caption="Depois de chegar a esta etapa, você precisará fazer alguns ajustes no código para funcionar com o Google Tag Manager.">
  <img src="https://mintcdn.com/onesignal/Y9PryqrHCRmPv_BC/images/web-push/add-code-to-site.png?fit=max&auto=format&n=Y9PryqrHCRmPv_BC&q=85&s=445d73fafe6bd92c5a6dcfbac563c1ee" alt="Etapa Adicionar código ao site no painel de configuração do OneSignal Web SDK" width="2588" height="1638" data-path="images/web-push/add-code-to-site.png" />
</Frame>

<Warning>
  Você deve fazer upload do arquivo OneSignal Service Worker diretamente para o seu servidor. Consulte [OneSignal Service Worker](./onesignal-service-worker).
</Warning>

### 2. Crie variáveis do GTM

Crie variáveis do GTM para valores que você referencia em tags. Isso evita codificar valores fixos e torna sua configuração mais fácil de manter.

**Crie uma variável `ONESIGNAL_APP_ID`**

1. No GTM, vá para **Variables > New**.
2. Escolha **Constant**.
3. Nomeie como `ONESIGNAL_APP_ID`
4. Defina o valor como seu OneSignal App ID.
5. Salve

<Frame caption="Criando uma variável do OneSignal App ID">
  <img src="https://mintcdn.com/onesignal/wJS3gHTEqDzyW0IP/images/web-push/gtm-app-id-variable.png?fit=max&auto=format&n=wJS3gHTEqDzyW0IP&q=85&s=8a7752f1d4095d4c8e6b8119a9de2bfc" alt="Criando uma variável do OneSignal App ID no Google Tag Manager" width="2378" height="1656" data-path="images/web-push/gtm-app-id-variable.png" />
</Frame>

<Check>
  Agora você pode referenciar seu App ID em qualquer lugar no GTM usando `{{ ONESIGNAL_APP_ID }}`.
</Check>

**Crie uma variável `ONESIGNAL_EXTERNAL_ID` (Recomendado)**

Use esta variável se você associar usuários com um identificador externo (por exemplo, um ID de usuário do seu banco de dados ou sistema de autenticação).

Escolha o tipo de variável com base em onde o valor está disponível no seu site. Opções comuns:

* Data Layer Variable (recomendado)
* First-Party Cookie
* DOM Variable (avançado)

### 3. Crie a tag de inicialização do OneSignal

1. No GTM, vá para **Tags > New**
2. Nomeie a tag: `OneSignal - Init`
3. Tag Type: **Custom HTML**
4. Cole o código abaixo.
5. Em **Advanced Settings > Tag firing options**, defina **Once per page**.
6. Em **Triggering**, selecione **Initialization - All Pages**.

```html HTML theme={null}
<!--
  OneSignal – Web SDK initialization using Google Tag Manager

  This snippet:
  - Loads the OneSignal Web SDK
  - Initializes OneSignal with your App ID
  - Enables the Subscription Bell (notifyButton)

  Works for most sites out of the box.
-->

<!-- 1. Load the OneSignal Web SDK (v16) -->
<!-- This script must load on every page where you want OneSignal available -->
<script
  src="https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.page.js"
  defer>
</script>

<script>
  // Ensure the GTM dataLayer exists
  // Used here only to optionally push a "OneSignalInitialized" event
  window.dataLayer = window.dataLayer || [];

  // OneSignalDeferred is a queue that runs once the SDK is fully loaded
  window.OneSignalDeferred = window.OneSignalDeferred || [];

  // 2. Initialize OneSignal once the SDK is ready
  window.OneSignalDeferred.push(function (OneSignal) {

    OneSignal.init({
      /*
        REQUIRED
        It is recommended to set the OneSignal App ID as a GTM variable.
        You can find this in your OneSignal Dashboard under:
        Settings > Keys & IDs
      */
      appId: "{{ONESIGNAL_APP_ID}}",

      /*
        OPTIONAL – ONLY NEEDED IF YOUR SERVICE WORKER IS NOT AT THE ROOT

        If your service worker is hosted at:
          /OneSignalSDKWorker.js

        …then you should NOT set serviceWorkerPath or serviceWorkerParam.

        Uncomment and update the options below ONLY if your service worker
        is hosted in a subdirectory (for example: /push/onesignal/).
      */

      //serviceWorkerPath: "push/onesignal/OneSignalSDKWorker.js",
      //serviceWorkerParam: { scope: "/push/onesignal/" },

      /*
        OPTIONAL
        Enable the OneSignal Subscription Bell (notifyButton),
        which allows users to subscribe or unsubscribe from notifications.
        For more prompt options, see: https://documentation.onesignal.com/docs/en/permission-requests
      */
      notifyButton: {
        enable: true
      }
    })
    .then(function () {
      // OneSignal initialized successfully
      console.log("[OneSignal] init success");

      // Recommended: push an event to GTM for triggering other tags
      window.dataLayer.push({
        event: "OneSignalInitialized"
      });
    })
    .catch(function (e) {
      // Initialization failed (invalid App ID, missing service worker, etc.)
      console.log("[OneSignal] init failed", e);
    });
  });
</script>
```

<Frame caption="Configurando a tag OneSignal - Init">
  <img src="https://mintcdn.com/onesignal/Y9PryqrHCRmPv_BC/images/web-push/gtm-init-tag.png?fit=max&auto=format&n=Y9PryqrHCRmPv_BC&q=85&s=6cec423472cb84777bddd893a59c83ff" alt="Configurando a tag OneSignal - Init no Google Tag Manager" width="2442" height="2296" data-path="images/web-push/gtm-init-tag.png" />
</Frame>

<Warning>
  Se você usar um banner de consentimento / CMP, consulte as opções de [Consent Mode e considerações de privacidade](#consent-mode-and-privacy-considerations) abaixo.
</Warning>

### 4. Defina External ID e Tags

Definir o [External ID](./users#external-id) é opcional, mas recomendado, pois permite identificar usuários em dispositivos e sincronizar com seu backend.

**Enviar `ONESIGNAL_EXTERNAL_ID` para o dataLayer**

Este exemplo mostra como você pode enviar um ID de usuário para o dataLayer para que o GTM possa lê-lo via a variável `ONESIGNAL_EXTERNAL_ID` (criada no passo 2).

```html HTML theme={null}
<script>
  window.dataLayer = window.dataLayer || [];

  // Get your user ID from your database or auth system.
  // Ensure this is a string value.
  var userId = "your_user_id_here";

  dataLayer.push({
    ONESIGNAL_EXTERNAL_ID: String(userId),
  });
</script>
```

**Crie uma tag GTM para definir o External ID**

Configuração da tag:

* Nome da tag: `OneSignal – Set External ID`
* Tipo da tag: **Custom HTML**
* Opções de disparo da tag: **Once per page**
* Trigger:
  * Crie um gatilho de evento personalizado para `OneSignalInitialized` (definido na tag **OneSignal - Init** acima) e
  * Opcionalmente se você souber que o ID do usuário está disponível no carregamento da página.

<Warning>
  O método necessário para definir o External ID é `OneSignal.login(externalId)` onde `externalId` é uma string.

  Se `{{ONESIGNAL_EXTERNAL_ID}}` estiver vazio (ou o GTM substituir por "undefined" / "null"), a chamada de login será ignorada e o External ID não será definido. Este é um problema comum de timing do GTM.
</Warning>

<CodeGroup>
  ```html Exemplo básico para definir o External ID theme={null}
  <script>
    // OneSignalDeferred ensures this runs after the OneSignal SDK is ready
    window.OneSignalDeferred = window.OneSignalDeferred || [];

    window.OneSignalDeferred.push(function (OneSignal) {
      /*
        Read the External ID from Google Tag Manager.
        This should be a GTM variable (Data Layer Variable or Custom JS Variable).
      */
      var externalId = "{{ONESIGNAL_EXTERNAL_ID}}";

      console.log("[OneSignal] raw external ID from GTM:", externalId);

      /*
        Basic validation:
        - GTM may substitute undefined/null as strings
        - OneSignal.login requires a string
      */
      if (!externalId || externalId === "undefined" || externalId === "null") {
        console.log("[OneSignal] External ID missing, skipping login");
        return;
      }

      // Ensure the External ID is a clean string
      externalId = String(externalId).trim();

      console.log("[OneSignal] Calling OneSignal.login with External ID:", externalId);

      /*
        Log the user into OneSignal using the External ID.
        This links the current browser/device to this user.
      */
      OneSignal.login(externalId)
        .then(function () {
          console.log("[OneSignal] External ID set successfully:", externalId);
        })
        .catch(function (e) {
          console.log("[OneSignal] Failed to set External ID", e);
        });
    });
  </script>
  ```

  ```html Exemplo avançado para tentar se o External ID não estiver sendo definido theme={null}
  <script>
    window.dataLayer = window.dataLayer || [];
    window.OneSignalDeferred = window.OneSignalDeferred || [];

    OneSignalDeferred.push(function (OneSignal) {
      var rawExternalId = "{{ONESIGNAL_EXTERNAL_ID}}";

      // ---- Helpers ----
      function log() {
        console.log.apply(console, ["[OneSignal External ID]"].concat([].slice.call(arguments)));
      }

      function normalizeExternalId(v) {
        // GTM commonly substitutes these as strings
        if (
          v === undefined ||
          v === null ||
          v === "undefined" ||
          v === "null"
        ) return null;

        var s = String(v).trim();
        if (!s.length) return null;

        return s;
      }

      function pushDL(eventName, extra) {
        try {
          var payload = Object.assign({ event: eventName }, extra || {});
          window.dataLayer.push(payload);
        } catch (e) {
          // no-op
        }
      }

      function readStateSnapshot() {
        var snapshot = {
          onesignalId: null,
          externalId: null,
          pushSubscriptionId: null
        };

        try {
          snapshot.onesignalId = OneSignal.User && OneSignal.User.onesignalId;
          snapshot.externalId = OneSignal.User && OneSignal.User.externalId;
          snapshot.pushSubscriptionId =
            OneSignal.User &&
            OneSignal.User.PushSubscription &&
            OneSignal.User.PushSubscription.id;
        } catch (e) {
          log("Error reading OneSignal.User state", e);
        }

        return snapshot;
      }

      function isExternalIdApplied(targetExternalId) {
        var current = normalizeExternalId(OneSignal.User && OneSignal.User.externalId);
        return current === targetExternalId;
      }

      // ---- Initial logging ----
      log("Tag fired. rawExternalId:", rawExternalId, "type:", typeof rawExternalId);

      var externalId = normalizeExternalId(rawExternalId);
      log("Normalized externalId:", externalId, "type:", typeof externalId);

      if (!externalId) {
        log("Not calling login(): externalId missing/invalid");
        pushDL("OneSignalExternalIdMissing", { reason: "invalid_or_missing_external_id" });
        return;
      }

      // Optional: enable verbose OneSignal logs during testing
      if (OneSignal.Debug && OneSignal.Debug.setLogLevel) {
        OneSignal.Debug.setLogLevel("trace");
        log("Enabled OneSignal Debug log level: trace");
      }

      // ---- Attach User State observer ----
      var changeFired = false;

      OneSignal.User.addEventListener("change", function (event) {
        changeFired = true;

        log("User change event fired:", event);

        var snapshot = readStateSnapshot();
        log("User state snapshot:", snapshot);

        // Helpful: push snapshot-ish DL event (optional)
        pushDL("OneSignalUserStateChanged", {
          onesignal_id: snapshot.onesignalId || "",
          external_id: normalizeExternalId(snapshot.externalId) || "",
          push_subscription_id: snapshot.pushSubscriptionId || ""
        });
      });

      // ---- Login + confirm + retry ----
      var attempt = 0;
      var MAX_RETRIES = 3;
      var CONFIRM_WINDOW_MS = 1500;
      var BASE_BACKOFF_MS = 500;

      function doLogin() {
        attempt += 1;
        changeFired = false;

        log("Calling OneSignal.login()", { externalId: externalId, attempt: attempt });

        OneSignal.login(externalId)
          .then(function () {
            log("OneSignal.login() promise resolved");
            waitForConfirmation();
          })
          .catch(function (e) {
            log("OneSignal.login() promise rejected", e);
            retry("promise_rejected");
          });
      }

      function waitForConfirmation() {
        var start = Date.now();

        (function check() {
          if (isExternalIdApplied(externalId)) {
            log("Confirmed externalId applied via state check:", externalId);

            var snapshot = readStateSnapshot();
            log("Final state snapshot:", snapshot);

            pushDL("OneSignalExternalIdSet", {
              external_id: externalId,
              attempt: attempt,
              push_subscription_id: snapshot.pushSubscriptionId || ""
            });

            return;
          }

          if (changeFired) {
            log("Change event observed but externalId not yet reflected; waiting...");
          }

          if (Date.now() - start >= CONFIRM_WINDOW_MS) {
            log("No confirmation within window", {
              attempt: attempt,
              changeFired: changeFired,
              currentExternalId: normalizeExternalId(OneSignal.User && OneSignal.User.externalId)
            });

            retry("no_confirmation");
            return;
          }

          setTimeout(check, 100);
        })();
      }

      function retry(reason) {
        if (attempt >= MAX_RETRIES) {
          log("Giving up after max retries", { attempts: attempt, reason: reason });

          var snapshot = readStateSnapshot();
          log("State at give-up:", snapshot);

          pushDL("OneSignalExternalIdSetFailed", {
            external_id: externalId,
            reason: reason,
            attempts: attempt,
            push_subscription_id: snapshot.pushSubscriptionId || ""
          });

          return;
        }

        var delay = BASE_BACKOFF_MS * Math.pow(2, attempt - 1);
        log("Retrying login after delay", { delayMs: delay, reason: reason, nextAttempt: attempt + 1 });

        setTimeout(doLogin, delay);
      }

      // If already applied, don't spam login()
      if (isExternalIdApplied(externalId)) {
        log("ExternalId already applied; skipping login.", externalId);

        var snapshot = readStateSnapshot();
        log("Current state snapshot:", snapshot);

        pushDL("OneSignalExternalIdAlreadySet", {
          external_id: externalId,
          push_subscription_id: snapshot.pushSubscriptionId || ""
        });

        return;
      }

      // Kick it off
      doLogin();
    });
  </script>
  ```
</CodeGroup>

#### Definir Tags

Isto envia [Tags do OneSignal](./add-user-data-tags) usando nosso Web SDK.

Configuração da tag:

* Nome: `OneSignal - Add Tags`
* Tipo da tag: **Custom HTML**
* Opções de disparo da tag: **Once per page**
* Trigger:
  * `OneSignalInitialized`, e
  * Sua condição para quando os dados da tag estiverem disponíveis (por exemplo: após login, em uma página de perfil, após compra).

Cole este código e substitua o exemplo de tag TAG e VALUE.

```html HTML theme={null}
<script>
  window.OneSignalDeferred = window.OneSignalDeferred || [];
  window.OneSignalDeferred.push(function (OneSignal) {
    OneSignal.User.addTags({
      TAG_1: "VALUE_1",
      TAG_2: "VALUE_2",
    });
  });
</script>
```

<Note> Envie tags apenas quando você tiver os dados do usuário disponíveis (por exemplo: após login, após o carregamento de um perfil ou após um evento de conversão conhecido). </Note>

### Consent Mode e considerações de privacidade

Se o seu site usar Consent Mode / um CMP, decida se o OneSignal deve carregar:

* Apenas após consentimento (comum para UE/Reino Unido), ou
* Imediatamente (comum onde o armazenamento "funcional" é permitido por padrão).

O GTM suporta um gatilho de inicialização de consentimento e controles de consentimento em nível de tag para gerenciar o comportamento da tag com base no consentimento do usuário. No entanto, o OneSignal também fornece métodos de consentimento de privacidade para controlar quando o SDK é carregado.

* [Manipulação de dados pessoais](./handling-personal-data)
* [Métodos de privacidade do Web SDK](./web-sdk-reference#privacy)

***

## Testes

1. No GTM, abra o modo Preview.
2. Carregue seu site e confirme:
   * `OneSignal - Init` dispara uma vez.
   * `OneSignalInitialized` aparece na linha do tempo de eventos do GTM (se você manteve o push de evento).
3. Inscreva-se no seu site. Consulte [Solicitações de permissão web](./permission-requests) para detalhes de solicitação.
4. No painel do OneSignal, vá para **Audience > Subscriptions** e confirme:
   * Uma inscrição aparece após você aceitar.
   * Um External ID é visível se você definiu um.
5. **Envie um push de teste de Messages > New Push.**

<Check> Se a inicialização estiver funcionando, você verá as inscrições aparecendo no OneSignal após aceitar. </Check>

### Solução de problemas

* A tag Init dispara, mas o SDK nunca carrega
  * Verifique se a Content Security Policy (CSP) está bloqueando `https://cdn.onesignal.com`.
  * Verifique bloqueadores de anúncios/bloqueadores de scripts.

* Erros de `dataLayer`
  * Certifique-se de que `window.dataLayer = window.dataLayer || []` esteja definido antes de qualquer chamada `dataLayer.push()`.

* Solicitações duplicadas / carregamento duplicado do SDK
  * Certifique-se de que você não está carregando o OneSignal também através do código do site, um plugin de CMS ou outra tag do GTM.

* Add Tags executa mas não aparece no OneSignal
  * Confirme que o Trigger Group espera `OneSignalInitialized`.
  * Confirme que seu gatilho de ação do usuário realmente dispara.
  * Confirme que as tags são pares chave/valor válidos e dentro dos [limites do plano](https://onesignal.com/pricing).

<Warning>
  Se você ainda precisar de ajuda, consulte [Solução de problemas do Web SDK](./troubleshooting-web-push) para correções comuns.
</Warning>

## Próximos passos

* [Solicitações de permissão web](./permission-requests)
* [Tags](./add-user-data-tags)
* [Referência do Web SDK](./web-sdk-reference)

***
