Web SDK - Guia de implementação do Google Tag Manager

Documento

Síntese

INFORMAÇÃO: A Atribuição da Web é uma funcionalidade empresarial. Contacte o seu Gestor de Sucesso do Cliente para ativar esta funcionalidade para a sua conta.

Este guia explica como implementar o Singular Web SDK usando o Google Tag Manager (GTM). Este método é ideal para equipas sem acesso direto ao código do site ou para aqueles que pretendem gerir o acompanhamento através do GTM.

IMPORTANTE! Não use as implementações GTM e JavaScript nativo no mesmo site. Escolha apenas um método para evitar rastreamento duplicado e contagens de eventos inflacionadas. O Singular não desduplica eventos automaticamente.

  • Não implemente os métodos Native JavaScript e Google Tag Manager. Escolha apenas um para evitar rastreamento duplicado.
  • O Singular Web SDK foi projetado para ser executado no lado do cliente no navegador do usuário. Ele requer acesso aos recursos do navegador, como localStorage e o DOM (Document Object Model), para funcionar corretamente. Não tente executar o SDK no lado do servidor (por exemplo, via SSR Next.js ou node.js) - isso causará falhas de rastreamento, pois os ambientes de servidor não fornecem acesso às APIs do navegador.

Pré-requisitos

Antes de começar, verifique se você tem:

Etapas de implementação


Etapa 1: Adicionar os modelos do Singular Web Tracking ao seu contêiner do GTM

  1. Faça login na sua conta do Google Tag Manager e selecione o contêiner do seu site.
  2. Vá para Tags > Novo.
  3. Dê um nome para a tag: "Singular Init Tag"
  4. Clique na caixa Configuração de tag para iniciar a configuração da tag.
  5. Escolha Tipo de tag: e selecione "Descubra mais tipos de tag na Galeria de modelos da comunidade".
  6. Procure por "Singular" e selecione "Singular Web Tracking". Clique no botão "Adicionar ao espaço de trabalho".

Etapa 2: Inicializar o SDK

  1. Preencha os campos do formulário com o seguinte:
    • Defina o Tipo de rastreamento como Inicialização
    • Introduza a sua chave SDK real para o campo Chave Api
    • Introduza o seu SDK Secret atual para o campo Secret
    • Introduza o seu ID de produto real. Ela deve ser semelhante a: com.website-name e deve corresponder ao valor BundleID na página Apps na plataforma Singular.

      DICA: use uma ID de produto específica para testar com.website-name.dev e atualize-a antes de enviar para a produção. Isso mantém todos os seus dados de teste separados do aplicativo de produção nos relatórios do Singular.

    • Opcional:
      • Nível de log: A configuração do registro de depuração do SDK no console. O padrão é nenhum.
      • Tempo limite da sessão: O tempo que o utilizador tem de estar inativo antes de o SDK criar uma nova sessão. A Singular envia sessões de utilizador para calcular a retenção de utilizadores e permitir a atribuição de reengajamento. O valor padrão é 30 minutos.
      • Rastreamento entre subdomínios
  2. Escolha Acionamento para configurar um acionador para fazer essa tag funcionar.
  3. Escolha Novo e nomeie o gatilho: "Singular Init Trigger".
  4. Clique na Configuração do acionador e escolha"Exibição de página - Janela carregada" e clique em"Salvar".
  5. Clique em"Salvar" novamente para salvar a tag.
  6. Clique em"Preview" (Pré-visualizar) na página da Tag e teste se a Tag de Inicialização Singular é activada.

    singular_init_tag_fired.png

SUCESSO! Se vir a"Singular Init Tag" na secção Tags Fired da consola Preview, configurou com sucesso a Tag de Inicialização.

IMPORTANTE! Para SPAs (Single Page Applications), você deve acionar o trackType Page Visit sempre que for direcionado para uma página diferente. Não chame Page Visit na primeira página que é carregada, pois a Inicialização já relata uma visita à página.

Visão geral da solução

  • Use uma variável JavaScript personalizada para detetar se é o primeiro carregamento de página.
  • Configure duas tags:
    • "Singular Init Tag" (Track Type = Initialization) para disparar apenas no carregamento inicial da página.
    • Tag "Singular Page Visit" (Track Type = Page Visit) para disparar em cada alteração de rota (excluindo o carregamento inicial) usando o acionador History Change.
  • Certifique-se de que seu SPA envia eventos de histórico para o dataLayer para alterações de rota.

image5.png


Etapa 3: Acompanhamento de eventos

Depois de inicializar o SDK, você pode rastrear eventos personalizados quando os usuários realizam ações importantes no seu site.

IMPORTANTE! O Singular não bloqueia eventos duplicados! É responsabilidade do desenvolvedor adicionar proteções contra atualizações de página ou duplicação. É recomendável incorporar algum método de deduplicação especificamente para eventos de receita para evitar dados de receita incorretos. Consulte "Etapa 5: Prevenção de eventos duplicados" abaixo para obter um exemplo.

Basic EventConversion EventRevenue Event

Rastreamento básico de eventos

Rastreie um evento simples ou adicione atributos personalizados usando JSON válido para fornecer mais contexto sobre o evento:

  1. Crie uma nova tag para o seu evento personalizado usando o modelo Singular Web Tracking.

  2. Dê um nome à tag de evento.

  3. Escolha Tipo de rastreamento = Evento personalizado

  4. Ajuste o campo "Nome do evento" ou defina a variável apropriada.

  5. Ajuste o campo "Custom User Id" (ID do usuário personalizado) ou defina a variável apropriada.

  6. Ajuste os "Atributos" se desejar passar pares Chave/Valor no Evento.

  7. Configure um acionador adequado para disparar a etiqueta apenas quando esperado.

  8. Guarde o acionador e a etiqueta e teste na pré-visualização.

custom_event.png

Padrões comuns de implementação de eventos

Page Load EventsButton Click EventsForm Submission Events

Criação de gatilhos GTM para eventos de carregamento de página

Para implementar o Singular Web SDK com o Google Tag Manager, é necessário criar um acionador de carregamento de página que seja acionado quando suas páginas forem carregadas.

Configuração rápida: No GTM, navegue até Gatilhos Nova configuração de gatilho e selecione "Exibição de página" como seu tipo de gatilho. Para a maioria das implementações, escolha "Todas as exibições de página" para disparar o gatilho em cada carregamento de página.

Para obter instruções completas de configuração: Consulte a documentação oficial do Google Tag Manager:


Passo 4: Definir o ID de utilizador do cliente

O usuário pode enviar seu ID de usuário interno para a Singular usando um método do SDK da Singular.

NOTA: Se utilizar a solução Cross-Device da Singular, deve recolher a ID de utilizador em todas as plataformas.

OBSERVAÇÃO : Se vários usuários usarem um único dispositivo, recomendamos a implementação de um fluxo de logout para definir e cancelar a definição da ID de usuário para cada login e logout.

DICA! Utilize o mesmo ID de utilizador do cliente que utiliza nos seus SDKs móveis. Isto permite a atribuição entre dispositivos e fornece uma visão completa do comportamento do utilizador em todas as plataformas.

Enquanto o usuário executa ações em seu site sem estar conectado, os eventos são enviados para a Singular com uma ID de usuário gerada pela Singular. Mas depois que o usuário se registra ou faz login, você pode ter eventos enviados para a Singular junto com o ID de usuário que é usado no seu site, por exemplo, um endereço de e-mail com hash.

A Singular usa a ID de usuário em exportações de dados no nível do usuário (consulte Exportando logs de atribuição), bem como em postbacks internos de BI, se você os tiver configurado (consulte Configurando postbacks internos de BI).

Há duas maneiras de enviar a ID de usuário para o Singular:

  • Recomendado: Se você souber a ID do usuário quando o site for aberto, defina a ID do usuário no tipo de faixa Inicialização ao inicializar o SDK. Isso torna a ID de usuário disponível para a Singular desde a primeira visita à página.
  • Como alternativa, é possível acionar uma Tag com Track Type = Login a qualquer momento, geralmente após a ocorrência de uma autenticação. Recomendamos chamá-la assim que o ID do usuário estiver disponível. Observação: chamar essa tag não aciona um evento. Apenas define o ID do utilizador para ser adicionado a quaisquer accionadores de eventos no futuro!

Para definir o ID de usuário com o Singular, adicione uma tag Singular com o tipo de rastreamento "Login":

  1. Na sua conta do Google Tag Manager, clique em Tags > Novo.
  2. Na janela Configuração de tag, clique em Configuração de tag e, no menu Tipo de tag, selecione "Singular Web Tracking".
  3. Em Tipo de rastreio, selecione "Início de sessão".
  4. Em ID de utilizador personalizado, introduza a variável do Google Tag Manager que contém o ID de utilizador.
  5. Clique em Desencadeamento e adicione o evento de desencadeamento: início de sessão do utilizador ou registo.
  6. Clique em Guardar.

image4.png

Para anular o ID de utilizador, adicione uma etiqueta com o tipo de pista " Terminar sessão":

  1. Na sua conta do Google Tag Manager, clique em Tags > Novo.
  2. Na janela Configuração de tags, clique em Configuração de tags e, no menu Tipo de tag, selecione "Seguimento singular da Web".
  3. Em Tipo de seguimento, selecione "Terminar sessão".
  4. Clique em Desencadeamento e adicione o evento de desencadeamento: fim de sessão do utilizador.
  5. Clique em Guardar.

image1.png

Notas:

  • A ID de utilizador persiste até a anular utilizando o tipo de seguimento de fim de sessão ou até o utilizador eliminar o seu armazenamento local.
  • Fechar/refrescar o sítio Web não anula a definição do ID de utilizador.
  • A navegação em modo privado, como incógnito, impedirá que o Singular mantenha a ID de utilizador, porque o armazenamento local é eliminado automaticamente ao fechar o browser.

Etapa 5: Evitar eventos duplicados

Como evitar eventos duplicados no Gerenciador de tags do Google

IMPORTANTE! Este é um dos erros mais comuns de implementação do GTM. Sem as devidas proteções, os eventos do Singular Web SDK podem ser acionados várias vezes quando os usuários atualizam as páginas, voltam a navegar ou acionam novamente as ações, inflacionando gravemente suas métricas.

Por que ocorrem duplicatas no GTM

O Google Tag Manager avalia os accionadores em cada carregamento de página, fazendo com que as etiquetas sejam acionadas novamente quando os utilizadores actualizam as páginas de agradecimento, reenviam formulários ou navegam utilizando os botões de retrocesso/avanço do browser. Isso acontece porque o GTM não possui reconhecimento de sessão incorporado para eventos personalizados.


Métodos de deduplicação do GTM

Abordagem de armazenamento de sessão: Armazene identificadores de eventos exclusivos no sessionStorage do navegador para rastrear quais eventos já foram disparados durante a sessão do usuário.

Variáveis JavaScript personalizadas: Crie variáveis que verifiquem o localStorage em busca de eventos disparados anteriormente antes de permitir o disparo de novos eventos.

Condições de acionamento: Adicionar lógica condicional aos accionadores que evita o disparo quando estão presentes indicadores duplicados.


Etapas de implementação

Criar variável de armazenamento: Crie uma variável JavaScript personalizada que gere identificadores exclusivos para cada evento Singular com base nos parâmetros do evento e na sessão do usuário.

Criar variável de verificação: Crie outra variável JavaScript personalizada que verifica se o identificador de evento atual já existe no armazenamento do navegador.

Adicionar condições de acionamento: Modifique os acionadores do Singular Web SDK para incluir uma condição de que a variável "verificação duplicada" seja igual a "false".

Armazenar após disparar: Use o recurso Sequenciamento de tags do GTM para disparar uma tag HTML personalizada que armazena o identificador do evento no sessionStorage após o disparo bem-sucedido do evento Singular.


Considerações específicas do GTM

Sequenciamento de tags: Use o Sequenciamento de tags das Configurações avançadas para garantir que as tags de armazenamento sejam disparadas após a conclusão das principais tags Singular.

Avaliação de variáveis: Lembre-se de que as variáveis JavaScript personalizadas são avaliadas cada vez que são referenciadas, portanto, otimize o desempenho.

Limitações entre domínios: O SessionStorage é específico do domínio, portanto, implemente soluções baseadas em cookies para rastreamento entre domínios, se necessário.

Para uma implementação detalhada: Consulte os guias abrangentes de deduplicação do GTM:


Etapa 6: Testar sua implementação do GTM

  1. Abra o modo de visualização do GTM e carregue seu site.
  2. Verifique se:
  • O SDK é carregado (solicitação de rede para singular-sdk.js)
  • Os eventos são acionados como esperado e apenas uma vez por ação
  • Não há erros no console do navegador relacionados a singular
  • Os pedidos de rede são enviados para sdk-api-v1.singular.net
  1. Utilize o separador Rede nas ferramentas de desenvolvimento do browser para verificar se o payload adequado é enviado

SUCESSO! Se vir eventos Singular corretos nos pedidos de rede e nenhuma duplicação, está pronto para entrar em funcionamento!


Passo 7: Implementar o reencaminhamento da Web para a aplicação

Encaminhamento de Atribuição Web-para-App

Use o Singular Web SDK para rastrear as jornadas do usuário do seu site para o seu aplicativo móvel, permitindo a atribuição precisa de campanhas da web a instalações e reengajamentos de aplicativos móveis. Siga estas etapas para configurar o encaminhamento da web para o aplicativo, incluindo o suporte a código QR para usuários de desktop.

  1. Siga nosso Guia de Encaminhamento de Atribuição de Website para Aplicativo Móvelpara configurar o Singular Web SDK para atribuição de web móvel.
  2. Para rastreamento Web-to-App para desktop:
    • Criar uma tag de limpeza do gerador de código QR
      1. Navegue até Tags > Novo no GTM e selecione HTML personalizado.
      2. Adicione código para:
        • Injetar a biblioteca QRCode que escolher
        • Recuperar o link Web-to-App em window.singularSdk.buildWebToAppLink(baselink);
        • Gerar o QRCode a partir do link retornado.
        • Atualizar a imagem QRCode na página.
      3. Nomear a etiqueta: "Singular - Gerador de código QR (Limpeza)"
      4. Não é necessário acionador: As tags de limpeza herdam os gatilhos da tag principal
      5. Configure a sua tag Singular Init:
        • Clique em Configuração de etiquetas
        • Aceda a Definições avançadas > Sequenciação de etiquetas
        • Selecione "Disparar uma etiqueta de limpeza após o disparo da [Etiqueta de inicialização singular]".
        • Selecione a sua etiqueta Gerador de código QR no menu pendente
        • Guarde a etiqueta e teste-a no modo de pré-visualização.

DICA! As visualizações da Web do navegador in-app para dispositivos móveis (como as usadas pelo Facebook, Instagram e TikTok) podem fazer com que o Singular Device ID mude se um usuário mudar para o navegador nativo do dispositivo, interrompendo a atribuição.

Para evitar isso, use sempre o formato de link de rastreamento Singular adequado para cada rede de anúncios:


Tópicos avançados

Adição de propriedades globais

Propriedades globais
#

O Singular SDK permite-lhe definir propriedades personalizadas a serem enviadas para os servidores Singular juntamente com cada sessão e evento enviado a partir da aplicação. Essas propriedades podem representar qualquer informação que você queira sobre o usuário, o modo/status do aplicativo ou qualquer outra coisa.

  • É possível definir até 5 propriedades globais como um objeto JSON válido. As propriedades globais são mantidas nos navegadores localstorage até que sejam apagadas ou o contexto do navegador seja alterado.

  • Cada nome e valor de propriedade pode ter até 200 caracteres. Se passar um nome ou valor de propriedade mais longo, este será truncado para 200 caracteres.

  • As propriedades globais são atualmente reflectidas nos registos de eventos ao nível do utilizador do Singular (consulte Exportar registos de atribuição) e em postbacks.

  • As propriedades globais estão disponíveis para serem enviadas em postbacks do Singular para um terceiro para fins de correspondência, se necessário.

Atualmente, a definição de uma propriedade global antes da inicialização do SDK não é suportada com a Tag de inicialização do Google Tag Manager. No entanto, para lidar com Propriedades globais após a inicialização, deve criar Tags HTML personalizadas e executar a função JavaScript nativa: setGlobalProperties(), getGlobalProperties(), clearGlobalProperties().

Como criar uma tag HTML personalizada para manipular as Propriedades globais

  1. Na interface do Google Tag Manager, clique em Tags no menu de navegação esquerdo e, em seguida, clique no botão Novo para criar uma nova tag.

  2. Clique em Configuração de tags e selecione HTML personalizado na lista de tipos de tags disponíveis.

  3. No campo HTML, cole o código do Método de propriedade global. Veja as opções abaixo:

  4. Clique em Acionamento e atribua uma opção de acionamento à tag.

  5. Dê à sua tag um nome descritivo como "Singular - Definir propriedades globais" no campo de nome da tag na parte superior.

A definição das Propriedades globais manterá a Propriedade global em todos os eventos até que seja desactivada ou limpa.

Clique em Visualizar para testar sua implementação. Verifique no console do navegador se as propriedades globais estão definidas.

Para Configuração avançada: Consulte a documentação HTML personalizada oficial do Google

Setting Global PropertiesGetting GlobalPropertiesClearing Global Properties

Código da etiqueta HTML personalizada para definir propriedades globais

<script>
/**
 * Set a Singular global property before SDK initialization.
 * Allows up to 5 key/value pairs. Optionally overwrites existing value for a key.
 * 
 * @param {string} propertyKey - The property key to set.
 * @param {string} propertyValue - The property value to set.
 * @param {boolean} overrideExisting - Whether to overwrite the property if it already exists.
 */

// Example usage - customize these values for your implementation
window.singularSdk.setGlobalProperties('user_type', 'premium', true);
window.singularSdk.setGlobalProperties('app_version', '2.1.0', false);
</script>

Rastreamento de pesquisa orgânica

Exemplo de rastreamento de pesquisa orgânica
#

Criando a tag de configuração de rastreamento de pesquisa orgânica

CRÍTICO!- Essa tag deve ser disparada antes da inicialização do SDK singular!

Esta tag HTML personalizada modifica o URL do documento para adicionar parâmetros de rastreamento de pesquisa orgânica (wpsrc e wpcn) que o Singular Web SDK precisa ler durante a inicialização. A sequência de tags é essencial para garantir a ordem de execução adequada.

Este exemplo é fornecido como uma solução alternativa para ativar o rastreamento da Pesquisa orgânica. O código deve ser utilizado apenas como exemplo e atualizado e mantido pelo programador Web com base nas necessidades do seu departamento de marketing. O rastreio da Pesquisa orgânica pode ter significados diferentes consoante o anunciante. Reveja o exemplo e ajuste-o de acordo com as suas necessidades.

Porquê utilizar isto?

  • Assegura que as visitas de pesquisa orgânica são corretamente controladas, mesmo que não estejam presentes parâmetros de campanha.

  • Anexa o parâmetro Singular "Source" wpsrccom o valor do (referrer) e o parâmetro "Campaign Name" wpcn como "OrganicSearch" ao URL para uma atribuição clara.

  • Armazena o URL atual e o referenciador em localStoragepara utilização posterior.

  • JavaScript puro, zero dependências e fácil de integrar.

Como funciona

  1. Verifica o URL da página em busca de parâmetros de campanha conhecidos (Google, Facebook, TikTok, UTMs, etc.).

  2. Se nenhum parâmetro de campanha estiver presente e o referenciador for um mecanismo de pesquisa, anexa:

    • wpsrc (com o referenciador como valor)
    • wpcn (com OrganicSearch como valor)
  3. Actualiza o URL no browser sem recarregar a página.

  4. Armazena o URL atual e o referenciador em localStoragecomo sng_url e sng_ref.

Utilização

  1. Navegue até Tags > Novo no GTM e clique em Configuração de tags e, em seguida, selecione HTML personalizado.
  2. Cole o código JavaScript completo conforme mostrado abaixo.
  3. Ignore a criação do gatilho para essa tag.Como essa tag deve ser executada antes da Tag de inicialização singular, vamos configurá-la para disparar antes da inicialização usando a Sequência de tags.

    1. Use um nome descritivo como "Singular - Configuração de pesquisa orgânica".
    2. Abra sua tag de inicialização do Singular Web SDK.
    3. Clique em Configuração de tag
    4. Vá para Configurações avançadas > Sequenciamento de tags.
    5. Marque "Disparar uma tag de configuração antes do disparo da [Singular Init Tag]".
    6. Selecione sua tag "Singular - Organic Search Setup" no menu suspenso.
    7. Recomendado: Marque "Não disparar [Singular Init Tag] se [tag de configuração] falhar" para evitar a inicialização com modificação incompleta do URL.
    8. organic_search.png
    9. Salve a tag.
  4. Use o modo de visualização do GTM para verificar:

    • A tag de configuração é acionada primeiro e modifica o URL.
    • A tag Singular Init dispara em segundo lugar e lê os parâmetros de URL modificados.
    • Não há conflitos de tempo entre as tags.

Para o Sequenciamento avançado de tags: Consulte a documentação oficial do Google:


Organic Search Tracking Code
<script>
(function() {
    // singular-web-organic-search-tracking: setupOrganicSearchTracking.js
    // Tracks organic search referrals by appending wpsrc and wpcn to the URL if no campaign parameters exist and the referrer is a search engine.

    // Configuration for debugging (set to true to enable logs)
    var debug = true;

    // List of campaign parameters to check for exclusion
    var campaignParams = [
        'gclid', 'fbclid', 'ttclid', 'msclkid', 'twclid', 'li_fat_id',
        'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'wpsrc'
    ];

    // Whitelist of legitimate search engine domains (prevents false positives)
    var legitimateSearchEngines = new Set([
        // Google domains
        'google.com', 'google.co.uk', 'google.ca', 'google.com.au', 'google.de', 
        'google.fr', 'google.it', 'google.es', 'google.co.jp', 'google.co.kr',
        'google.com.br', 'google.com.mx', 'google.co.in', 'google.ru', 'google.com.sg',
        
        // Bing domains  
        'bing.com', 'bing.co.uk', 'bing.ca', 'bing.com.au', 'bing.de',
        
        // Yahoo domains
        'yahoo.com', 'yahoo.co.uk', 'yahoo.ca', 'yahoo.com.au', 'yahoo.de',
        'yahoo.fr', 'yahoo.it', 'yahoo.es', 'yahoo.co.jp',
        
        // Other search engines
        'baidu.com', 'duckduckgo.com', 'yandex.com', 'yandex.ru',
        'ask.com', 'aol.com', 'ecosia.org', 'startpage.com', 
        'qwant.com', 'seznam.cz', 'naver.com', 'daum.net'
    ]);

    // Extract main domain from hostname (removes subdomains)
    function getMainDomain(hostname) {
        if (!hostname) return '';
        
        var lowerHost = hostname.toLowerCase();
        
        // Handle special cases for known search engines with country codes
        var searchEnginePatterns = {
            'google': function(host) {
                // Match google.TLD patterns more precisely
                if (host.indexOf('google.co.') !== -1 || host.indexOf('google.com') !== -1) {
                    var parts = host.split('.');
                    for (var i = 0; i < parts.length - 1; i++) {
                        if (parts[i] === 'google') {
                            return parts.slice(i).join('.');
                        }
                    }
                }
                return null;
            },
            'bing': function(host) {
                if (host.indexOf('bing.co') !== -1 || host.indexOf('bing.com') !== -1) {
                    var parts = host.split('.');
                    for (var i = 0; i < parts.length - 1; i++) {
                        if (parts[i] === 'bing') {
                            return parts.slice(i).join('.');
                        }
                    }
                }
                return null;
            },
            'yahoo': function(host) {
                if (host.indexOf('yahoo.co') !== -1 || host.indexOf('yahoo.com') !== -1) {
                    var parts = host.split('.');
                    for (var i = 0; i < parts.length - 1; i++) {
                        if (parts[i] === 'yahoo') {
                            return parts.slice(i).join('.');
                        }
                    }
                }
                return null;
            }
        };
        
        // Try specific patterns for major search engines
        for (var engine in searchEnginePatterns) {
            if (lowerHost.indexOf(engine) !== -1) {
                var result = searchEnginePatterns[engine](lowerHost);
                if (result) return result;
            }
        }
        
        // Handle other known engines with simple mapping
        var otherEngines = {
            'baidu.com': 'baidu.com',
            'duckduckgo.com': 'duckduckgo.com', 
            'yandex.ru': 'yandex.ru',
            'yandex.com': 'yandex.com',
            'ask.com': 'ask.com',
            'aol.com': 'aol.com',
            'ecosia.org': 'ecosia.org',
            'startpage.com': 'startpage.com',
            'qwant.com': 'qwant.com',
            'seznam.cz': 'seznam.cz',
            'naver.com': 'naver.com',
            'daum.net': 'daum.net'
        };
        
        for (var domain in otherEngines) {
            if (lowerHost.indexOf(domain) !== -1) {
                return otherEngines[domain];
            }
        }
        
        // Fallback: Extract main domain by taking last 2 parts (for unknown domains)
        var parts = hostname.split('.');
        if (parts.length >= 2) {
            return parts[parts.length - 2] + '.' + parts[parts.length - 1];
        }
        
        return hostname;
    }

    // Get query parameter by name, using URL.searchParams with regex fallback for IE11
    function getParameterByName(name, url) {
        if (!url) url = window.location.href;
        try {
            return new URL(url).searchParams.get(name) || null;
        } catch (e) {
            if (debug) console.warn('URL API not supported, falling back to regex:', e);
            name = name.replace(/[\[\]]/g, '\\$&');
            var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');
            var results = regex.exec(url);
            if (!results) return null;
            if (!results[2]) return '';
            return decodeURIComponent(results[2].replace(/\+/g, ' '));
        }
    }

    // Check if any campaign parameters exist in the URL
    function hasAnyParameter(url, params) {
        for (var i = 0; i < params.length; i++) {
            if (getParameterByName(params[i], url) !== null) {
                return true;
            }
        }
        return false;
    }

    // Improved search engine detection - only checks hostname, uses whitelist
    function isSearchEngineReferrer(referrer) {
        if (!referrer) return false;
        
        var hostname = '';
        try {
            hostname = new URL(referrer).hostname.toLowerCase();
        } catch (e) {
            // Fallback regex for hostname extraction (IE11 compatibility)
            var match = referrer.match(/^(?:https?:\/\/)?([^\/\?#]+)/i);
            hostname = match ? match[1].toLowerCase() : '';
        }
        
        if (!hostname) return false;
        
        // First check: exact match against whitelist
        if (legitimateSearchEngines.has(hostname)) {
            if (debug) console.log('Exact match found for:', hostname);
            return true;
        }
        
        // Second check: subdomain of legitimate search engine
        var hostParts = hostname.split('.');
        if (hostParts.length >= 3) {
            // Try domain.tld combination (e.g., google.com from www.google.com)
            var mainDomain = hostParts[hostParts.length - 2] + '.' + hostParts[hostParts.length - 1];
            if (legitimateSearchEngines.has(mainDomain)) {
                if (debug) console.log('Subdomain match found for:', hostname, '-> main domain:', mainDomain);
                return true;
            }
            
            // Try last 3 parts for country codes (e.g., google.co.uk from www.google.co.uk)
            if (hostParts.length >= 3) {
                var ccDomain = hostParts[hostParts.length - 3] + '.' + hostParts[hostParts.length - 2] + '.' + hostParts[hostParts.length - 1];
                if (legitimateSearchEngines.has(ccDomain)) {
                    if (debug) console.log('Country code domain match found for:', hostname, '-> cc domain:', ccDomain);
                    return true;
                }
            }
        }
        
        if (debug) {
            console.log('Hostname not recognized as legitimate search engine:', hostname);
        }
        
        return false;
    }

    // Main function to update URL with organic search tracking parameters
    function setupOrganicSearchTracking() {
        var url = window.location.href;
        var referrer = document.referrer || '';

        // Store URL and referrer in localStorage
        try {
            localStorage.setItem('sng_url', url);
            localStorage.setItem('sng_ref', referrer);
        } catch (e) {
            if (debug) console.warn('localStorage not available:', e);
        }

        if (debug) {
            console.log('Current URL:', url);
            console.log('Referrer:', referrer);
        }

        // Skip if campaign parameters exist or referrer is not a search engine
        var hasCampaignParams = hasAnyParameter(url, campaignParams);
        if (hasCampaignParams || !isSearchEngineReferrer(referrer)) {
            if (debug) console.log('Skipping URL update: Campaign params exist or referrer is not a legitimate search engine');
            return;
        }

        // Extract and validate referrer hostname
        var referrerHostname = '';
        try {
            referrerHostname = new URL(referrer).hostname;
        } catch (e) {
            if (debug) console.warn('Invalid referrer URL, falling back to regex:', e);
            var match = referrer.match(/^(?:https?:\/\/)?([^\/]+)/i);
            referrerHostname = match ? match[1] : '';
        }

        // Extract main domain from hostname
        var mainDomain = getMainDomain(referrerHostname);
        
        if (debug) {
            console.log('Full hostname:', referrerHostname);
            console.log('Main domain:', mainDomain);
        }

        // Only proceed if main domain is valid and contains safe characters
        if (!mainDomain || !/^[a-zA-Z0-9.-]+$/.test(mainDomain)) {
            if (debug) console.log('Skipping URL update: Invalid or unsafe main domain');
            return;
        }

        // Update URL with wpsrc and wpcn parameters
        var urlObj;
        try {
            urlObj = new URL(url);
        } catch (e) {
            if (debug) console.warn('URL API not supported, cannot modify URL:', e);
            return;
        }
        
        // Set wpsrc to the main domain (e.g., google.com instead of tagassistant.google.com)
        urlObj.searchParams.set('wpsrc', mainDomain);
        
        // Set wpcn to 'Organic Search' to identify the campaign type
        urlObj.searchParams.set('wpcn', 'Organic Search');

        // Update the URL without reloading (check if history API is available)
        if (window.history && window.history.replaceState) {
            try {
                window.history.replaceState({}, '', urlObj.toString());
                if (debug) console.log('Updated URL with organic search tracking:', urlObj.toString());
            } catch (e) {
                if (debug) console.warn('Failed to update URL:', e);
            }
        } else {
            if (debug) console.warn('History API not supported, cannot update URL');
        }
    }

    // Execute the function
    setupOrganicSearchTracking();
})();
</script>

Rastreamento entre subdomínios

Por predefinição, o Singular Website SDK gera uma ID de dispositivo Singular e persiste-a utilizando o armazenamento do browser. Como esse armazenamento não pode ser compartilhado entre subdomínios, o SDK acaba gerando uma nova ID para cada subdomínio.

Se quiser manter a ID de Dispositivo Singular em todos os subdomínios, pode usar uma das seguintes opções:

Método B (Avançado): Definir manualmente a ID de dispositivo singular
#

Método B (Avançado): Definir manualmente o ID do dispositivo singular

Se não quiser que o Singular SDK mantenha a ID do dispositivo automaticamente, é possível manter a ID manualmente entre domínios - por exemplo, usando um cookie de domínio de nível superior ou um cookie do lado do servidor. O valor deve ser uma ID gerada anteriormente pelo Singular no formato uuid4 válido.

Nota: É possível ler a ID do dispositivo Singular definindo uma variável JavaScript personalizada e chamando singularSdk.getSingularDeviceId() após chamar a tag Init track-type.

mceclip2.png


Problemas comuns de implementação do GTM

Identificadores de dispositivo necessários
O evento é disparado várias vezes Refine ou limite seus acionadores, use "Uma vez por página" ou adicione condições
Formato incorreto da ID do produto A ID do produto deve usar a notação DNS inversa (com.company.site)
Eventos não rastreados Verifique a ortografia e as maiúsculas e minúsculas dos nomes dos eventos; certifique-se de que o SDK singularé carregado antes de a etiqueta do evento ser activada
Script SDK bloqueado Bloqueadores de anúncios ou política de segurança de conteúdo restritiva; considere mudar para a implementação JS nativa se os problemas persistirem

Práticas recomendadas

  • Mantenha o GTM organizado: Nomeie claramente as tags e os acionadores e documente sua finalidade.
  • Auditar regularmente as tags não utilizadas ou antigas.
  • Minimize o número de accionadores para reduzir o risco de eventos duplicados.
  • Após as alterações, sempre teste completamente no modo de visualização do GTM antes de colocar em produção.
  • Se você usa rastreamento baseado em cookies(rastreamento entre subdomínios), atualize sua política de privacidadede acordo.

Artigos relacionados