@funnel10x/tracking 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -16
- package/dist/gtm.html +2 -2
- package/dist/index.js +7 -7
- package/dist/tag.js +7 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,6 +40,15 @@ O que faz numa página:
|
|
|
40
40
|
**interruptor de consentimento** do `site.json`, e a guarda das
|
|
41
41
|
pré-visualizações.
|
|
42
42
|
|
|
43
|
+
**Quem lê isto do lado do admin** (Fase A3 do plano da atribuição): a fonte
|
|
44
|
+
PostHog da ingestão guarda o `tracking_version`, a `page_version`, o `ab_test`
|
|
45
|
+
e o `fingerprint` de cada evento, e o email e o telefone do `contact_captured`
|
|
46
|
+
só em hash. O histórico de um funil, que chegou ao PostHog antes deste snippet
|
|
47
|
+
com o URL inteiro, é aparado lá pela mesma allow-list do `src/clean.js`: um
|
|
48
|
+
parâmetro que entre na `ALLOWED_PARAMS` entra também na entrada `posthog` da
|
|
49
|
+
`ingest/pii.json` e na `supabase/verify/atr3.sql` do admin, no mesmo PR (um
|
|
50
|
+
teste do admin prova que as três listas são a mesma).
|
|
51
|
+
|
|
43
52
|
O posthog-js e o FingerprintJS vão dentro do ficheiro, pela versão que este
|
|
44
53
|
pacote fixa, e não se resolvem no site. O que fica de fora são as extensões que
|
|
45
54
|
o posthog-js carrega quando o projeto as liga (o gravador de sessão, os dead
|
|
@@ -63,7 +72,7 @@ init({
|
|
|
63
72
|
apiHost: '/_t',
|
|
64
73
|
consent: site.consent,
|
|
65
74
|
pageVersion: 3,
|
|
66
|
-
test: '/pt/
|
|
75
|
+
test: '/pt/acq_f1/webinar/lp#2',
|
|
67
76
|
})
|
|
68
77
|
```
|
|
69
78
|
|
|
@@ -120,15 +129,16 @@ os hosts do checkout.
|
|
|
120
129
|
checkoutHosts: []
|
|
121
130
|
}
|
|
122
131
|
</script>
|
|
123
|
-
<script src="https://cdn.jsdelivr.net/npm/@funnel10x/tracking@1.
|
|
132
|
+
<script src="https://cdn.jsdelivr.net/npm/@funnel10x/tracking@1.4.0/dist/tag.js" integrity="sha384-…" crossorigin="anonymous"></script>
|
|
124
133
|
```
|
|
125
134
|
|
|
126
135
|
Uma versão nova é uma tag nova, nunca `@1` nem `@latest`: o GTM de cada site
|
|
127
136
|
diz que versão corre, e o `tracking_version` de cada evento confirma-o.
|
|
128
137
|
|
|
129
|
-
**O proxy gerido do PostHog.** Sem build não há o `/_t`, e com o
|
|
130
|
-
vazio os envios vão para o `us.i.posthog.com
|
|
131
|
-
visita de quem tem um bloqueador não chega ao
|
|
138
|
+
**O proxy gerido do PostHog, opcional.** Sem build não há o `/_t`, e com o
|
|
139
|
+
`apiHost` vazio os envios vão para o `us.i.posthog.com`: funciona, mas a
|
|
140
|
+
EasyPrivacy bloqueia-o, e a visita de quem tem um bloqueador não chega ao
|
|
141
|
+
PostHog. O PostHog tem um proxy
|
|
132
142
|
gerido, um subdomínio da account (um CNAME para o PostHog, nas definições da
|
|
133
143
|
organização, *Managed reverse proxy*) que recebe os envios e os passa ao
|
|
134
144
|
PostHog. Com ele, o `apiHost` da tag é esse subdomínio: na IR,
|
|
@@ -178,6 +188,7 @@ O que os forms, o iframe e os links do checkout levam:
|
|
|
178
188
|
| os click ids | `fbclid`, `gclid`, `gbraid`, `wbraid`, `gad_source`, `gad_campaignid`, `msclkid`, `ctwa_clid` | sim, do URL | não |
|
|
179
189
|
| os ids de anúncio | `a_campaign_id`, `a_adset_id`, `a_ad_id` (a convenção, abaixo), e os da HYROS `h_ad_id`, `fbc_id` | sim, do URL | só `a_ad_id`, como as UTMs |
|
|
180
190
|
| `lp` | a página de entrada que o URL declara | sim, do URL | não |
|
|
191
|
+
| `narrative` | o slug da narrativa declarado pela página (desde a 1.4.0) | sim, do URL | `narrative`, com o query key igual ao nome, se a location o tiver |
|
|
181
192
|
|
|
182
193
|
- **Num form da página**, um campo que já existe com o nome recebe o valor se
|
|
183
194
|
for escondido ou estiver vazio; os que faltam acrescentam-se escondidos, só
|
|
@@ -234,10 +245,18 @@ nomes sem prefixo da 1.0.0 à 1.2.0 (`ad_id`, `adset_id`, `campaign_id`,
|
|
|
234
245
|
`adgroup_id`) saíram: nenhum anúncio os usou. Nenhum URL das três accounts
|
|
235
246
|
trazia já um parâmetro `a_` (medido no mesmo dia).
|
|
236
247
|
|
|
248
|
+
**O texto de cada anúncio sai do gerador de links** da Marketing Ops (o módulo
|
|
249
|
+
URL Parameters, Fase M48 do plano da Marketing), que o compõe a partir da regra
|
|
250
|
+
da fonte na Traffic Sources, do funil e do stage: é aí que se gera, e os dois
|
|
251
|
+
modelos de baixo são a forma do que ele dá. O `utm_campaign` deixou de ser o nome
|
|
252
|
+
da campanha (que chega pelo `a_campaign_id`) e é o funil e o stage,
|
|
253
|
+
`<funil>_<stage>[_<temperatura>]`; o nome do ad set e o `utm_id` saíram, porque
|
|
254
|
+
os ids `a_` já os dizem.
|
|
255
|
+
|
|
237
256
|
**Meta**, nos *URL parameters* de cada anúncio:
|
|
238
257
|
|
|
239
258
|
```
|
|
240
|
-
utm_source=meta&utm_medium=paid_social&utm_campaign=
|
|
259
|
+
utm_source=meta&utm_medium=paid_social&utm_campaign=acq_f1_webinar_cold&utm_content={{ad.name}}&utm_placement={{placement}}&a_campaign_id={{campaign.id}}&a_adset_id={{adset.id}}&a_ad_id={{ad.id}}
|
|
241
260
|
```
|
|
242
261
|
|
|
243
262
|
O nome do anúncio acaba no código do asset (decisão 10 do plano), e é por isso
|
|
@@ -245,13 +264,14 @@ que vai no `utm_content`. O `utm_source` é `meta`, como na Traffic Sources e no
|
|
|
245
264
|
anúncios das três accounts (45.819 pageviews com `fbclid` em 90 dias, medidos a
|
|
246
265
|
2026-10-08); até à 1.2.0 este modelo dizia `facebook`, que nenhum usava.
|
|
247
266
|
|
|
248
|
-
**Google**, no *Final URL suffix* da
|
|
249
|
-
`
|
|
250
|
-
|
|
251
|
-
|
|
267
|
+
**Google**, no *Final URL suffix* da campanha (ou do ad group, ou do anúncio:
|
|
268
|
+
o `utm_campaign` é o do funil e do stage, e por isso não vai ao nível da conta),
|
|
269
|
+
com o auto-tagging ligado (o `gclid`) e um parâmetro personalizado, `asset`, em
|
|
270
|
+
cada anúncio (o código do asset, que num anúncio de pesquisa, num responsive
|
|
271
|
+
display ou na Performance Max não chega pelo nome):
|
|
252
272
|
|
|
253
273
|
```
|
|
254
|
-
utm_source=google&utm_medium=cpc&utm_campaign=
|
|
274
|
+
utm_source=google&utm_medium=cpc&utm_campaign=acq_f1_webinar&utm_term={keyword}&utm_content={_asset}&a_campaign_id={campaignid}&a_adset_id={adgroupid}&a_ad_id={creative}
|
|
255
275
|
```
|
|
256
276
|
|
|
257
277
|
## Os links orgânicos
|
|
@@ -262,7 +282,9 @@ tabela **Traffic Sources** do admin, que é nomenclatura partilhada por todas as
|
|
|
262
282
|
accounts. Sem elas a visita chega sem origem, e o referrer de um browser in-app
|
|
263
283
|
ou de um cliente de email vem quase sempre vazio, o que a conta como *direct*.
|
|
264
284
|
Este README não copia a tabela, que é a fonte; o gerador de links da Marketing
|
|
265
|
-
Ops
|
|
285
|
+
Ops (o módulo URL Parameters, Fase M48 do plano da Marketing) monta-os a partir
|
|
286
|
+
dela, junta-os a um URL que já tenha parâmetros sem duplicar nenhum, e guarda
|
|
287
|
+
cada link com o sítio onde foi posto.
|
|
266
288
|
|
|
267
289
|
## O checklist de um funil
|
|
268
290
|
|
|
@@ -277,7 +299,9 @@ Antes de ligar o tráfego:
|
|
|
277
299
|
snippet já é o PostHog, e com outro na página não arranca (avisa na
|
|
278
300
|
consola, e o `window.f10xTracking.mode` fica `conflict`). Com a mesma chave
|
|
279
301
|
não se perde nada: quem volta mantém o id anónimo, e o URL inicial que o
|
|
280
|
-
outro deixou no cookie reescreve-se limpo.
|
|
302
|
+
outro deixou no cookie reescreve-se limpo. **O `apiHost` da tag nova é o
|
|
303
|
+
`api_host` que a antiga tinha** (o proxy, se ela o usava): vazio, perdia
|
|
304
|
+
quem hoje chega por ele.
|
|
281
305
|
3. **O consentimento**: o `consent` do `site.json` escrito, e o banner a chamar
|
|
282
306
|
`grant()` e `deny()`; num site de fora, a tag no GTM com a condição do
|
|
283
307
|
consentimento se o site tiver banner, e no head só se não tiver.
|
|
@@ -289,8 +313,8 @@ Antes de ligar o tráfego:
|
|
|
289
313
|
5. **Os links de email e de SMS** levam `contact_id={{contact.id}}`.
|
|
290
314
|
6. **O checkout**: o host em `checkoutHosts` (o Stripe já lá está), e num
|
|
291
315
|
checkout em código os `fields()` na metadata.
|
|
292
|
-
7. **Os anúncios**:
|
|
293
|
-
orgânicos com as UTMs da Traffic Sources.
|
|
316
|
+
7. **Os anúncios**: o texto do gerador de links nos anúncios da Meta e da
|
|
317
|
+
Google, e os links orgânicos gerados por ele, com as UTMs da Traffic Sources.
|
|
294
318
|
8. **A prova**: um pageview aberto com `?email=teste@example.com&utm_source=teste`
|
|
295
319
|
chega ao PostHog (Activity, no projeto da account) com a `utm_source` e sem
|
|
296
320
|
o `email`, no evento e no perfil, e com o `tracking_version` da versão.
|
|
@@ -309,10 +333,42 @@ admin, em `tests/api/tracking.test.mjs` (a limpeza, sem browser) e
|
|
|
309
333
|
|
|
310
334
|
Uma versão nova: subir a `version` no `package.json` (semver: uma mudança no
|
|
311
335
|
que os forms ou os eventos levam é minor, uma que parte uma integração é
|
|
312
|
-
major), `npm run build`, PR, e depois do merge, da `main
|
|
336
|
+
major), `npm run build`, PR, e depois do merge, da `main`, nesta pasta:
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
npm publish --dry-run
|
|
340
|
+
```
|
|
313
341
|
|
|
314
342
|
```bash
|
|
315
343
|
npm publish
|
|
316
344
|
```
|
|
317
345
|
|
|
346
|
+
O primeiro confere a versão e os ficheiros sem publicar nada. **O segundo é do
|
|
347
|
+
dono**: a conta do npm (`funnel10x-org`) tem 2FA, e o `npm publish` pede uma
|
|
348
|
+
autenticação no browser (*EOTP: This operation requires a one-time
|
|
349
|
+
password*) mesmo com a sessão iniciada (medido a 2026-10-08, na 1.3.0). Um
|
|
350
|
+
agente prepara a pasta na `main` e corre o primeiro, e o dono corre o segundo
|
|
351
|
+
no terminal dele.
|
|
352
|
+
|
|
353
|
+
Depois de publicar, o npm avisa que a versão *may take a few minutes to become
|
|
354
|
+
available*: espera-se, e só então se confirma. O `npm view` lê de uma cache e
|
|
355
|
+
mostrou a versão anterior durante esses minutos; o registo, lido directamente,
|
|
356
|
+
diz a verdade:
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
curl -s https://registry.npmjs.org/@funnel10x%2ftracking | node -e "process.stdin.on('data',d=>b+=d);let b='';process.stdin.on('end',()=>console.log(JSON.parse(b)['dist-tags']))"
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
E o `tag.js` que o jsDelivr serve tem de ter o hash do `integrity` da tag do
|
|
363
|
+
GTM, senão a tag não carrega em site nenhum. As duas linhas têm de dar o mesmo
|
|
364
|
+
`sha384-…`:
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
echo "sha384-$(curl -sL "https://cdn.jsdelivr.net/npm/@funnel10x/tracking@$(node -p "require('./package.json').version")/dist/tag.js" | openssl dgst -sha384 -binary | openssl base64 -A)"
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
grep -o 'sha384-[^"]*' dist/gtm.html
|
|
372
|
+
```
|
|
373
|
+
|
|
318
374
|
O `dist/THIRD_PARTY_LICENSES.txt` leva as licenças do que vai embutido.
|
package/dist/gtm.html
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @funnel10x/tracking@1.
|
|
1
|
+
<!-- @funnel10x/tracking@1.4.0: a tag do GTM (Custom HTML, em All Pages). Só se mudam a chave e, se a account tiver o proxy gerido do PostHog, o apiHost; uma versão nova é um ficheiro novo. -->
|
|
2
2
|
<script>
|
|
3
3
|
window.f10xTracking = {
|
|
4
4
|
key: '{{PostHog project key}}',
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
checkoutHosts: []
|
|
7
7
|
}
|
|
8
8
|
</script>
|
|
9
|
-
<script src="https://cdn.jsdelivr.net/npm/@funnel10x/tracking@1.
|
|
9
|
+
<script src="https://cdn.jsdelivr.net/npm/@funnel10x/tracking@1.4.0/dist/tag.js" integrity="sha384-UTBEFP06SUs6EqWR2bkYb7Rq6QEj2SWvMGpf1/3g4uhyNGYMzyucjjeHtYYoW/xD" crossorigin="anonymous"></script>
|