Inscreva-se em minha Newsletter
Está recebendo eventos no seu Google Analytics 4 que você não criou? Eventos que podem corromper seus dados, gerar eventos com loops infinitos e muitos outros problemas.
Conforme esperado, muitas empresas começaram a adicionar integrações do Google Analytics 4, e muitos deles podem simplesmente enviar eventos para a função gtag
, e você provavelmente acabará tendo alguns eventos indesejados em seus relatórios.
Não apenas sobre fornecedores, spammers têm uma maneira fácil de mexer programaticamente com seus dados, apenas usando os objetos globais.
Vou ensinar alguns truques de implementação para evitar que outras ferramentas poluam nossos dados do GA4 e também como podemos garantir que ninguém além de nós envie dados para nosso dataLayer, como de costume, usarei exemplos para o Google Tag Manager e o Google Analytics 4, mas a mesma lógica pode ser aplicável a qualquer outra ferramenta.
Protegendo o GTAG da poluição de Bots e Vendors
Para proteger nossa configuração de eventos ou pushes não solicitados, modificaremos levemente nossas chamadas gtag
. A primeira modificação é adicionar alguma verificação de guarda na função gtag
, o que os bloqueou.
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
// Guarda, o primeiro argumento não é nosso token de proteção? Ignorar
if (arguments[0] !== 'protectToken') return;
// Esta função nos permitirá passar de volta um objeto do tipo argumento para o dataLayer
function passArgumentsBack() {
dataLayer.push(arguments)
}
// Remova o primeiro argumento e passe o restante de volta
passArgumentsBack.apply(this, Array.prototype.slice.call(arguments, 1));
}
gtag('protectToken', 'js', new Date());
gtag('protectToken', 'config', 'G-XXXXXX');
</script>
Agora, qualquer chamada de função gtag
, onde o primeiro argumento não é nosso protectionToken
, será bloqueada. Fazendo com que qualquer terceiro ou bot que tente enviar dados para nosso namespace
, seja simplesmente ignorado furtivamente
Pode acontecer de você não conseguir modificar o gtag
na criação, talvez porque ele esteja codificado na página ou porque outra pessoa já o inicializou. Não se preocupe, você pode executar este código para substituir o método atual.
if (window.gtag && {}.toString.call(window.gtag) === '[object Function]') {
function gtag() {
if (arguments[0] !== 'protectToken') return;
function passArgumentsBack() {
dataLayer.push(arguments)
}
passArgumentsBack.apply(this, Array.prototype.slice.call(arguments, 1));
}
}
Você precisa lembrar que agora precisa anexar seu protectionToken
a qualquer chamada que queira enviar.
gtag('protectToke', ... )
Protegendo nosso Datalayer da poluição de bots e terceiros
Aposto que você já deve ter pensado em apenas adicionar um evento personalizado a todos os seus pushes e, em seguida, adicionar uma condição de bloqueio no GTM, e essa é realmente uma ótima ideia, mas neste momento não estamos tentando bloquear eventos sendo enviados, mas nosso dataLayer
sendo poluído e bagunçado. Nós realmente queremos um dataLayer
limpo e de boa aparência que seja totalmente governado por nós, se alguém quiser popular dados em nosso dataLayer
, deve nos perguntar primeiro.
Proteger o dataLayer
é um pouco mais complicado (pelo menos o Google Tag Manager), e isso ocorre porque quando o GTM carrega, ele modifica o método push original do array. Que acabaremos perdendo a reatividade ou causando qualquer outro mau funcionamento se mexermos com ele, ao mesmo tempo e pelo mesmo motivo, não podemos adicionar a modificação na inicialização do dataLayer
porque ela será perdida quando o GTM a substituir.
O truque que precisamos fazer aqui é esperar até que o dataLayer.push
tenha sido totalmente inicializado e então adicionar algum método para interceptar as chamadas feitas a ele.
Neste exemplo, usarei um padrão de proxy simples, mas há algumas soluções alternativas mais adequadas (e ao mesmo tempo mais difíceis de implementar) como trabalhar com setters
e getters
ou usar um ES6 Proxies. Em qualquer caso, esse método é bem direto e tem um suporte muito bom para vários navegadores.
Tentei me concentrar em ter um código incompreensível em vez de um código com aparência legal. Usaremos uma solução baseada em Promises para consultar o método dataLayer.push
até detectarmos que ele já foi inicializado pelo Google Tag Manager e então adicionaremos nosso proxy.
<script>
(function() {
var settings = {
dataLayerName: 'dataLayer',
pollingTime: 25,
limit: 1000,
protectKey: 'ptoken',
protectValue: 'xxxxxxxxxxxxxxxxxxxx'
}
var waitForDataLayerReady = function(settings) {
var count = 1;
function waitFor(result) {
if (result) {
var proxiedDataLayerPush = window[settings.dataLayerName].push;
window[settings.dataLayerName].push = function() {
if ((arguments && arguments[0] && arguments[0][settings.protectKey] && arguments[0][settings.protectKey] === settings.protectValue) || arguments && arguments[0] && arguments[0].event && String(arguments[0].event).match(/^gtm\./)) {
if (arguments && arguments[0] && arguments[0][settings.protectKey] && arguments[0][settings.protectKey]) delete arguments[0][settings.protectKey]
return proxiedDataLayerPush.apply(this, arguments);
}
}
return settings.dataLayerName
}
if (count >= settings.limit) {
return null;
}
count++;
return new Promise(function(resolve) {
setTimeout(resolve, settings.pollingTime || 1000)
}).then(function() {
Promise.resolve(window[settings.dataLayerName || 'dataLayer'] && window[settings.dataLayerName].push && window[settings.dataLayerName || 'dataLayer'].push.toString().includes('SANDBOXED_JS_SEMAPHORE'))
}).then(function(res) {
waitFor(res)
});
}
return waitFor();
}
waitForDataLayerReady(settings).then(function(result) {
if (result === true) {
var proxied = window[settings.dataLayerName || 'dataLayer'];
window[settings.dataLayerName || 'dataLayer'] = function() {
return proxied.apply(this, arguments);
}
}
});
})()
</script>
Nome | Descrição |
---|---|
dataLayerName | Este é o nome da nossa variável dataLayer, o padrão será dataLayer |
pollingTime | O período de verificação, por padrão, é verificado a cada 25 ms |
limit | Não queremos realmente esperar para sempre, limit + pollingTime irá parar o observador. Se você quiser calcular isso em segundos, o total de segundos que o código continuará esperando por um dataLayer é secs = (limit * pollingTime) / 1000 |
protectKey | Esta é a chave que precisamos adicionar aos nossos pushes, se ela não estiver presente o push não será executado |
protectValue | E este é o valor esperado do ProtectToken |
Definição de parâmetros de configuração
Se você verificar o código cuidadosamente, adicionamos uma regra especial para permitir que todos os eventos que começam com /^gtm\..*/
ignorem a verificação, para permitir que os pushes do sistema continuem indo para o dataLayer
.
Então agora, se alguém fizer o seguinte, o push será interceptado e nunca alcançará nosso dataLayer
.
window.dataLayer.push({
event: 'evilVendor',
opted_in_groups: '1,2,3,4'
})
Do outro lado, nossos pushes devem conter a chave de proteção e o token para que possam terminar no dataLayer
.
window.dataLayer.push({
event: 'add_to_wishlist',
ptoken: 'xxxxxxxxxxxxxxxxxxxxxxxx'
})
Deste ponto em diante, a lógica pode ser estendida o quanto você quiser, por exemplo, você pode querer definir uma lista de eventos em um whitelist em vez de trabalhar com um token, depende apenas da sua imaginação.
Este padrão de proxy é extensível a quase todas as ferramentas, o que significa que você pode aplicar este conceito a qualquer outro fornecedor. Por favor, tenha em mente que isso não é algo trivial para adicionar, então meu conselho é confiar em suas equipes de desenvolvimento ou alguma agência contratada que possa tomar o cuidado adequado para implementar este tipo de solução.