@funnel10x/tracking 2.0.0 → 2.2.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 +287 -47
- package/dist/direct-init.js +13 -0
- package/dist/direct-rewrites.json +7 -0
- package/dist/gtm-fallback.html +24 -0
- package/dist/gtm-official.html +17 -0
- package/dist/gtm.html +38 -3
- package/dist/index.d.ts +8 -0
- package/dist/index.js +7 -7
- package/dist/tag.js +7 -7
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -28,6 +28,9 @@ CDN, no canal 1.x, e o SDK não vem neste ficheiro. O que faz numa página:
|
|
|
28
28
|
acrescentados), no URL do iframe de um form, inquérito ou calendário do GHL,
|
|
29
29
|
e nos links do checkout. O email, o `token` e o resto do URL não seguem: iam
|
|
30
30
|
para o URL do Stripe e para os campos do GHL, que é entregá-los a terceiros;
|
|
31
|
+
- **o `checkout` no clique num link do checkout** (desde a 2.2.0, Fase A41),
|
|
32
|
+
uma vez por link e por página: o início do checkout, do contrato dos
|
|
33
|
+
eventos (abaixo);
|
|
31
34
|
- **o identify pelo id do contacto** num link de email ou de SMS
|
|
32
35
|
(`?contact_id={{contact.id}}`);
|
|
33
36
|
- **o email e o telefone que a pessoa envia** (desde a 1.1.0, como a HYROS;
|
|
@@ -45,26 +48,47 @@ CDN, no canal 1.x, e o SDK não vem neste ficheiro. O que faz numa página:
|
|
|
45
48
|
- **a versão do snippet em cada evento** (`tracking_version`), e, num site
|
|
46
49
|
`direct`, **a versão da página e o teste** (`page_version`, `ab_test`), o
|
|
47
50
|
**interruptor de consentimento** do `site.json`, e a guarda das
|
|
48
|
-
pré-visualizações
|
|
51
|
+
pré-visualizações;
|
|
52
|
+
- **os extras isolados do arranque do SDK** (desde a 2.1.0, Fase A2c): os
|
|
53
|
+
forms, o iframe e o checkout (`dom`), o email e o telefone (`contact`), o
|
|
54
|
+
FingerprintJS (`fingerprint`) e o cross-domain (`linker`) correm cada um no
|
|
55
|
+
seu `try`. Um que lance deixa na consola *the dom extra failed* (com o nome
|
|
56
|
+
dele) e, em cada evento, o `tracking_degraded` com a lista dos que falharam
|
|
57
|
+
(`['dom']`), e o PostHog mede na mesma, com o `tracking_version`. No 2.0.0 um
|
|
58
|
+
erro em qualquer deles impedia o SDK de carregar. Um erro no próprio arranque
|
|
59
|
+
(o núcleo: o stub, o consentimento, o carregamento do `array.js`, o
|
|
60
|
+
`before_send`, a API) deixa a página como estava: o stub sai, o
|
|
61
|
+
`window.f10xTracking` fica sem `version`, e numa tag do GTM arranca a tag
|
|
62
|
+
oficial de reserva (*A reserva*, abaixo);
|
|
63
|
+
- **o cross-domain entre domínios ligados, opcional** (`linkedDomains`, desde a
|
|
64
|
+
2.1.0): os links e os forms para o outro domínio levam a pessoa e a sessão do
|
|
65
|
+
PostHog num parâmetro que expira em 2 minutos, como o `_gl` do GA (*O
|
|
66
|
+
cross-domain*, abaixo).
|
|
49
67
|
|
|
50
68
|
**Quem lê isto do lado do admin** (Fase A3 do plano da atribuição): a fonte
|
|
51
69
|
PostHog da ingestão guarda de cada toque o `tracking_version`, a
|
|
52
70
|
`page_version`, o `ab_test`, o `fingerprint`, e desde a A2b a versão do SDK e a
|
|
53
71
|
data dos `defaults` (`$lib_version` e `$config_defaults`), e o email e o
|
|
54
|
-
telefone do `contact_captured` só em hash
|
|
72
|
+
telefone do `contact_captured` só em hash; desde a A2c, o `tracking_fallback`
|
|
73
|
+
que a tag de reserva carimba e o `linked_distinct_id` do cross-domain (em hash
|
|
74
|
+
quando é um email, como o `distinct_id`). O `tracking_degraded` fica só no
|
|
75
|
+
PostHog, como o `fingerprint_ms`. **Apara cada URL pela mesma lista**
|
|
55
76
|
de `src/params.js`: um parâmetro que entre na `ALLOWED_PARAMS` entra também na
|
|
56
77
|
entrada `posthog` da `ingest/pii.json` e na `supabase/verify/atr3.sql` do
|
|
57
78
|
admin, no mesmo PR (um teste do admin prova que as três listas são a mesma).
|
|
58
79
|
|
|
59
|
-
### Uma
|
|
80
|
+
### Uma instalação activa por página: o snippet, e a oficial como reserva
|
|
60
81
|
|
|
61
|
-
Cada site, de qualquer account, escolhe **uma** de duas instalações, e nunca
|
|
62
|
-
duas na mesma página (decisão 1 da A2b
|
|
63
|
-
GTM, o snippet oficial no código do site, ou
|
|
64
|
-
ou **este snippet** (embutido num repo
|
|
65
|
-
`dist/gtm.html` em qualquer outro site).
|
|
66
|
-
|
|
67
|
-
|
|
82
|
+
Cada site, de qualquer account, escolhe **uma** de duas instalações, e nunca há
|
|
83
|
+
duas activas na mesma página (decisão 1 da A2b, revista pela decisão 1 da A2c):
|
|
84
|
+
a **oficial do PostHog** (a tag no GTM, o snippet oficial no código do site, ou
|
|
85
|
+
o posthog-js no código de uma app) ou **este snippet** (embutido num repo
|
|
86
|
+
`direct`, ou pela tag do `dist/gtm.html` em qualquer outro site). Num site com
|
|
87
|
+
a tag do GTM, a oficial pode lá estar **só como reserva**: outra tag, que
|
|
88
|
+
arranca quando o snippet não carregou, e nunca ao lado dele (*A reserva*,
|
|
89
|
+
abaixo). Quem escolhe este não perde nada da oficial: é o mesmo SDK, com os
|
|
90
|
+
extras. Com duas activas, a segunda ou toma o arranque da primeira ou duplica
|
|
91
|
+
cada evento:
|
|
68
92
|
|
|
69
93
|
- **a oficial antes deste**: o primeiro `init` da fila manda, e este não
|
|
70
94
|
arranca; avisa na consola (*another PostHog is already on this page*) e o
|
|
@@ -76,8 +100,13 @@ arranque da primeira ou duplica cada evento:
|
|
|
76
100
|
`supabase/verify/atr2b.sql` do admin guarda o resto: num host com este
|
|
77
101
|
snippet, nenhum `$pageview` de outra instalação no mesmo minuto.
|
|
78
102
|
|
|
79
|
-
Num contentor GTM partilhado por vários sites, a tag oficial dispara
|
|
80
|
-
|
|
103
|
+
Num contentor GTM partilhado por vários sites, a tag oficial dispara nos hosts
|
|
104
|
+
que ainda não passaram ao snippet: em All Pages, com o acionador *Snippet hosts*
|
|
105
|
+
(o da tag do snippet) como **excepção**, e o *Direct hosts* (os sites `direct`,
|
|
106
|
+
com o snippet no build) como outra (Fase A2d do admin, que revê a lista de
|
|
107
|
+
inclusão da A2c: passar um host é uma edição da RegEx, e um host que ninguém
|
|
108
|
+
listou fica medido pela oficial, em vez de calado). A reserva é outra tag.
|
|
109
|
+
**Dentro de um
|
|
81
110
|
domínio registável, todas as instalações levam a mesma data de `defaults`**: o
|
|
82
111
|
cookie do PostHog é partilhado pelos subdomínios, e a data muda a regra entre o
|
|
83
112
|
cookie e o `localStorage` (`cookieWinsOnConflict`). A deste pacote é
|
|
@@ -129,7 +158,7 @@ de vir no ficheiro. É uma das razões de a 2.0.0 ser major.
|
|
|
129
158
|
O `package.json` do repo pina a versão exacta (sem `^`), e o build embute-o:
|
|
130
159
|
|
|
131
160
|
```json
|
|
132
|
-
{ "dependencies": { "@funnel10x/tracking": "2.
|
|
161
|
+
{ "dependencies": { "@funnel10x/tracking": "2.2.0" } }
|
|
133
162
|
```
|
|
134
163
|
|
|
135
164
|
```js
|
|
@@ -140,6 +169,7 @@ init({
|
|
|
140
169
|
apiHost: '/_t',
|
|
141
170
|
sdkVersion: import.meta.env.VITE_POSTHOG_SDK_VERSION || undefined,
|
|
142
171
|
consent: site.consent,
|
|
172
|
+
linkedDomains: site.linkedDomains,
|
|
143
173
|
pageVersion: 3,
|
|
144
174
|
test: '/pt/acq_f1/webinar/lp#2',
|
|
145
175
|
})
|
|
@@ -185,34 +215,82 @@ init({
|
|
|
185
215
|
(`f10x_consent`), e a página seguinte arranca sozinha. Com `false`, mede
|
|
186
216
|
logo. **O GTM do site arranca depois do stub do snippet**, para uma tag que
|
|
187
217
|
use o `window.posthog` o encontrar.
|
|
218
|
+
- `linkedDomains`: o do `site.json`, opcional, uma lista de hosts (*O
|
|
219
|
+
cross-domain*, abaixo). Sem ele, ou vazio, o cross-domain está desligado.
|
|
188
220
|
- `pageVersion` e `test`: o `version` da página principal no `tests.json` (ou o
|
|
189
221
|
`N` de uma variante) e o nome do teste activo, que o build entrega.
|
|
190
222
|
|
|
191
223
|
Uma página cujo caminho acaba em `_` seguido de algarismos (a pré-visualização
|
|
192
224
|
de uma versão) não mede nada nem mexe nos forms.
|
|
193
225
|
|
|
226
|
+
## Num site com build próprio que não é da base, ou só com o header
|
|
227
|
+
|
|
228
|
+
O cartão PostHog do Account Settings dá as três maneiras, pela ordem do que é
|
|
229
|
+
melhor, já com a chave do projeto:
|
|
230
|
+
|
|
231
|
+
- **No build do site** (um Next.js ou um Vite na Vercel que não nasceu da
|
|
232
|
+
base `direct`): o `dist/direct-init.js` (o `init` com o `apiHost: '/_t'`) e
|
|
233
|
+
o `dist/direct-rewrites.json` (os três rewrites de cima, para o
|
|
234
|
+
`vercel.json`), que o build do pacote escreve e o
|
|
235
|
+
`tests/api/gtm-tags.test.mjs` compara com o bloco da secção de cima. O
|
|
236
|
+
`/_t` é o proxy no domínio do site, e por isso não leva o proxy gerido.
|
|
237
|
+
- **Colado no header** (um funil do GHL, um Webflow): a tag do snippet, o
|
|
238
|
+
`dist/gtm.html`, tal como está. Não depende do GTM, que a EasyPrivacy
|
|
239
|
+
bloqueia inteiro (`||googletagmanager.com^`), mas só passa pelas listas com o
|
|
240
|
+
proxy gerido no `apiHost`: sem ele, vai para o `i.posthog.com`, que a mesma
|
|
241
|
+
lista bloqueia (o `array.js` e o `/i/`). A reserva só corre pelo GTM (o
|
|
242
|
+
`f10x_tracking_failed` é um evento do `dataLayer`), e por isso um site sem
|
|
243
|
+
contentor não mede a visita em que o snippet falha.
|
|
244
|
+
- **Pelo GTM**: só a tag do snippet em All Pages, que é a mais simples (sem
|
|
245
|
+
a reserva, a visita em que o `tag.js` não carrega não se mede), ou as três
|
|
246
|
+
tags, abaixo.
|
|
247
|
+
|
|
248
|
+
Um host das duas primeiras num contentor com a oficial do PostHog entra no
|
|
249
|
+
acionador *Direct hosts*, que é a excepção dela, no dia em que passa.
|
|
250
|
+
|
|
194
251
|
## Num site que não é repo nosso: a tag do GTM
|
|
195
252
|
|
|
196
253
|
Num funil do GHL, num site institucional ou num site em Webflow, onde não há
|
|
197
|
-
build, o mesmo pacote carrega-se por uma tag Custom HTML do GTM
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
hash do ficheiro no `integrity`.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
254
|
+
build, o mesmo pacote carrega-se por uma tag Custom HTML do GTM, **em vez da tag
|
|
255
|
+
oficial do PostHog, que fica só como reserva** (*Uma instalação activa por
|
|
256
|
+
página*, acima, e *A reserva*, abaixo), **pela versão fixa** no URL do jsDelivr
|
|
257
|
+
e com o hash do ficheiro no `integrity`. **As três tags de um contentor geram-se
|
|
258
|
+
no admin**, já com a chave do projeto e o proxy gerido da account: em Account
|
|
259
|
+
Settings › Integrations, no cartão PostHog, *Install the tracking on a site*
|
|
260
|
+
(Fase A2d do plano da atribuição), com os acionadores e os passos de
|
|
261
|
+
instalar, de passar um host e de ligar o proxy. O que o cartão gera são os
|
|
262
|
+
ficheiros do `dist/` sem o comentário de cabeça, com os marcadores trocados, e
|
|
263
|
+
mais nada:
|
|
264
|
+
|
|
265
|
+
| ficheiro | a tag | dispara |
|
|
266
|
+
| --- | --- | --- |
|
|
267
|
+
| `dist/gtm.html` | o snippet, desta versão | no acionador *Snippet hosts* (Page View, *Page Hostname* corresponde à RegEx) |
|
|
268
|
+
| `dist/gtm-fallback.html` | a oficial do PostHog como reserva, com o `tracking_fallback` | só no evento personalizado `f10x_tracking_failed` |
|
|
269
|
+
| `dist/gtm-official.html` | a oficial do PostHog, para os hosts que ainda não passaram | em All Pages, com o *Snippet hosts* e o *Direct hosts* como excepção |
|
|
270
|
+
|
|
271
|
+
As três levam a condição de consentimento de analytics do site, quando ele tem
|
|
272
|
+
banner. Só se trocam a chave, o host (o `apiHost` no snippet, o `api_host` nas
|
|
273
|
+
oficiais: o proxy gerido da account, abaixo, ou o PostHog directo), os hosts do
|
|
274
|
+
checkout, os domínios ligados (*O cross-domain*, abaixo; vazio, desligado) e,
|
|
275
|
+
numa emergência, o `sdkVersion`. Uma oficial que já exista no contentor
|
|
276
|
+
substitui-se pela gerada, que traz a data dos `defaults` do pacote.
|
|
277
|
+
|
|
278
|
+
**Desde a 2.1.0 a tag diz quando o snippet não arrancou**: empurra para o
|
|
279
|
+
`dataLayer` o evento `f10x_tracking_failed`, uma vez por página, quando o
|
|
280
|
+
`tag.js` não chega (o `onerror`: o jsDelivr em baixo ou bloqueado, um
|
|
281
|
+
`integrity` que não bate, uma CSP que o recusa; ou nenhum dos dois ao fim de
|
|
282
|
+
10 s, um pedido pendurado) ou chega e não deixa a `version` no
|
|
283
|
+
`window.f10xTracking` (o `onload`: um erro nosso no arranque). É o evento em
|
|
284
|
+
que a reserva dispara. Um `tag.js` que chegue depois dos 10 s encontra a
|
|
285
|
+
oficial e fica inerte (o `conflict`), e continua a haver uma só instalação
|
|
286
|
+
activa; e uma tag que dispare outra vez com o snippet já a correr não empurra
|
|
287
|
+
nada, mesmo que a rede lhe falhe. **O evento vai para o `window.dataLayer`**:
|
|
288
|
+
num GTM com a data layer renomeada (o `l=` do snippet do GTM) a reserva não
|
|
289
|
+
dispara, e a prova do ponto 8 do checklist apanha-o. O `<script>` do jsDelivr cria-se por código, e não como
|
|
290
|
+
um `<script src>` no HTML: o GTM recria cada `<script>` de um Custom HTML
|
|
291
|
+
copiando-lhe os atributos, e um `onload` escrito como atributo é um handler
|
|
292
|
+
inline, que uma CSP com nonce não deixa correr; posto como propriedade, de
|
|
293
|
+
dentro do script da tag, corre sempre.
|
|
216
294
|
|
|
217
295
|
Uma versão nova é uma tag nova, nunca `@2` nem `@latest`: o GTM de cada site
|
|
218
296
|
diz que versão dos extras corre, e o `tracking_version` de cada evento
|
|
@@ -227,7 +305,9 @@ organização, *Managed reverse proxy*) que recebe os envios e os passa ao
|
|
|
227
305
|
PostHog, e serve também o `array.js`. Com ele, o `apiHost` da tag é esse
|
|
228
306
|
subdomínio: na IR,
|
|
229
307
|
`https://p.infinityresponse.com`, e na IMO Circle, `https://p.imocircle.com`
|
|
230
|
-
(os dois válidos, lidos no PostHog a 2026-10-08; o Piko ainda não tem).
|
|
308
|
+
(os dois válidos, lidos no PostHog a 2026-10-08; o Piko ainda não tem). O
|
|
309
|
+
admin guarda o de cada projeto (o *Managed proxy* do mesmo cartão, que só grava
|
|
310
|
+
um host que sirva o SDK do PostHog), e gera as três tags com ele. As listas que bloqueiam pelo nome do domínio deixam de o apanhar;
|
|
231
311
|
o uBlock Origin no Firefox, que lê o CNAME, apanha na mesma, e quanto se
|
|
232
312
|
recupera não se mede, porque o que é bloqueado não chega para se contar. O
|
|
233
313
|
subdomínio é de outra origem que a página, e por isso o browser só lhe manda a
|
|
@@ -258,6 +338,55 @@ anúncio, e os campos escondidos do form lêem-nos de lá (cada campo com o
|
|
|
258
338
|
código do form: dentro de um iframe o snippet não arranca o PostHog, só passa
|
|
259
339
|
ao form o que veio no URL dele.
|
|
260
340
|
|
|
341
|
+
### A reserva: a tag oficial quando o snippet não carrega
|
|
342
|
+
|
|
343
|
+
Num site com a tag do snippet, a tag oficial do PostHog passa a reserva
|
|
344
|
+
(decisão 1 da A2c): uma tag Custom HTML (o template da galeria não tem onde pôr
|
|
345
|
+
uma função) com o snippet oficial do PostHog, que dispara **só no evento
|
|
346
|
+
personalizado `f10x_tracking_failed`**, e por isso só quando o snippet tentou e
|
|
347
|
+
não conseguiu, nunca antes dele. É o `dist/gtm-fallback.html`, que o build
|
|
348
|
+
escreve e o Account Settings gera já preenchido: o stub do snippet oficial (a
|
|
349
|
+
forma que as definições do projeto dão hoje, a do `snippetFunctions` do
|
|
350
|
+
PostHog, que insere o `array.js` uma vez só e deixa repetir depois de uma
|
|
351
|
+
falha, com a lista de métodos do posthog-js da devDependency), a mesma chave e o mesmo `api_host` da tag do snippet, a data de
|
|
352
|
+
`defaults` e o `custom_campaign_params` do pacote (para os ids de anúncio irem
|
|
353
|
+
como propriedades nas duas instalações), `person_profiles: 'identified_only'`,
|
|
354
|
+
e um **`before_send` que carimba `tracking_fallback: true` em cada evento**, que
|
|
355
|
+
é o que distingue uma visita pela reserva nos dados (o admin guarda-o). Pelo
|
|
356
|
+
`before_send` e não pelo `register`, que persistia e marcava os `$pageview` do
|
|
357
|
+
snippet nas páginas seguintes.
|
|
358
|
+
|
|
359
|
+
**O trigger é um evento personalizado**, com a mesma condição de consentimento
|
|
360
|
+
da tag do snippet. Nunca All Pages nem *Window Loaded*: em All Pages a oficial
|
|
361
|
+
dispara antes de o `tag.js` chegar e toma o arranque (o `conflict`), e num site
|
|
362
|
+
com banner o `load` chega antes do sim, a reserva media sem ele, e quando o sim
|
|
363
|
+
fizesse correr a tag do snippet ela dava `conflict`. Pelo evento, a reserva já
|
|
364
|
+
é segura contra duplicados: com o snippet carregado o evento não sai, e se
|
|
365
|
+
saísse o `init` dela era um no-op no stub do snippet.
|
|
366
|
+
|
|
367
|
+
**Num contentor partilhado** (o `GTM-PM4T6FGX` do Piko) são duas tags oficiais:
|
|
368
|
+
a dos hosts que ainda não passaram (o `dist/gtm-official.html`), em All Pages,
|
|
369
|
+
sem `before_send`, com o *Snippet hosts* e o *Direct hosts* como excepção; e a
|
|
370
|
+
reserva, outra tag, só no `f10x_tracking_failed`, com o `before_send`. Uma tag
|
|
371
|
+
só a fazer as duas coisas disparava em All Pages antes do `tag.js` nos hosts do
|
|
372
|
+
snippet (o `conflict`) e carimbava `tracking_fallback` nos hosts da oficial, que
|
|
373
|
+
não é reserva nenhuma. A tag do snippet dispara só no *Snippet hosts*, e por
|
|
374
|
+
isso nunca nos hosts `direct` (onde o snippet vai no build) nem nos que ainda
|
|
375
|
+
estão na oficial.
|
|
376
|
+
|
|
377
|
+
**O que a reserva cobre**: o jsDelivr em baixo ou bloqueado, um `integrity` que
|
|
378
|
+
não bata, e um erro nosso no arranque. **O que não cobre**: uma versão do SDK
|
|
379
|
+
que parta (a oficial carrega o mesmo `array.js`, e a resposta é o
|
|
380
|
+
`sdkVersion`), e os bloqueadores de anúncios (bloqueiam as duas). Num site
|
|
381
|
+
`direct` não há reserva: o snippet vai no build, a tag do snippet não dispara
|
|
382
|
+
nesses hosts, e o que o protege são os extras isolados.
|
|
383
|
+
|
|
384
|
+
**O que uma visita pela reserva perde**: a visita conta, com o URL inteiro e os
|
|
385
|
+
parâmetros dele no PostHog, e perde-se o que é dos extras: os ids nos campos
|
|
386
|
+
dos forms, no URL do iframe do GHL e nos links do checkout (os `ph_*` e o
|
|
387
|
+
`client_reference_id`), o `contact_captured` (o email e o telefone), o
|
|
388
|
+
fingerprint, o `_f10x` do cross-domain, e o `tracking_version`.
|
|
389
|
+
|
|
261
390
|
## Os campos
|
|
262
391
|
|
|
263
392
|
O que os forms, o iframe e os links do checkout levam:
|
|
@@ -297,6 +426,101 @@ O que os forms, o iframe e os links do checkout levam:
|
|
|
297
426
|
`sale_posthog_links` liga a venda pelo `cs_…` observado no PostHog primeiro,
|
|
298
427
|
senão pelo primeiro id da metadata que o projeto da account tenha visto.
|
|
299
428
|
|
|
429
|
+
## O cross-domain: `linkedDomains`
|
|
430
|
+
|
|
431
|
+
**Desligado por omissão**, e só para um funil que atravesse dois domínios
|
|
432
|
+
registáveis nossos (decisão 3 da A2c). Entre subdomínios do mesmo domínio o
|
|
433
|
+
cookie do PostHog já segue a pessoa, também em sufixos de duas partes
|
|
434
|
+
(`.com.br`, `.co.uk`), e o que hoje atravessa domínios são terceiros (o Stripe,
|
|
435
|
+
o redirect dos links do GHL), que têm os seus caminhos. O posthog-js não tem
|
|
436
|
+
linker; este desenha-se como o `_gl` do GA.
|
|
437
|
+
|
|
438
|
+
**A opção** é uma lista de hosts (`go.marca.pt`) ou de domínios registáveis
|
|
439
|
+
(`marca.pt`, que apanha os subdomínios), sem esquema nem caminho, ou uma string
|
|
440
|
+
com eles separados por vírgulas ou espaços; uma entrada sem forma de hostname
|
|
441
|
+
(um `*.marca.pt`) sai, com um aviso na consola. Vai no
|
|
442
|
+
`window.f10xTracking` da tag, ou no `init` de um repo `direct` (o `linkedDomains`
|
|
443
|
+
do `site.json`, que a base passa). Os dois sites levam o outro na lista: um
|
|
444
|
+
`_f10x` que chegue só se lê numa página com a lista preenchida.
|
|
445
|
+
|
|
446
|
+
**À saída**, os links (`a[href]`) e os forms (`form[action]`) para um host da
|
|
447
|
+
lista ganham, no clique (o esquerdo, e o do meio, que abre noutro separador;
|
|
448
|
+
o direito não, porque o menu dele tem *Copiar endereço do link*, e uma marca
|
|
449
|
+
fresca no instante da cópia é o instante da partilha; e o direito tira o
|
|
450
|
+
`_f10x` que um clique anterior tenha deixado no link) ou no envio, o parâmetro
|
|
451
|
+
`_f10x=<marca de tempo, em base 36>.<i ou a>.<distinct id>.<session id>`,
|
|
452
|
+
codificado para o URL. Só com o PostHog a medir (com `consent: true`, depois do
|
|
453
|
+
sim). Ficam de fora os hosts do checkout, que têm a decoração deles, e um
|
|
454
|
+
destino que partilha com a página um domínio da lista (o cookie já o segue). O
|
|
455
|
+
`i` diz que a origem está identificada (o `distinct_id` já não é o
|
|
456
|
+
`$device_id`: um `contact_id` de um link de email, um identify), e o `a` que é
|
|
457
|
+
anónima. **O `distinct_id` vai sempre, mesmo quando é um email** (o dono,
|
|
458
|
+
2026-10-14): com o sinal `i` o destino arranca identificado no PostHog, e os
|
|
459
|
+
eventos caem logo na pessoa do contacto. Num form GET o browser troca a query
|
|
460
|
+
string do `action` pelos campos, e o `_f10x` vai num campo escondido; num POST
|
|
461
|
+
vai no `action`.
|
|
462
|
+
|
|
463
|
+
**À chegada**, um `_f10x` cuja marca está a **menos de 2 minutos** do
|
|
464
|
+
carregamento da página (contados até ao carregamento, e não até ao sim do
|
|
465
|
+
banner; nos dois sentidos, para um relógio adiantado na origem não deixar um
|
|
466
|
+
link válido mais do que isso):
|
|
467
|
+
|
|
468
|
+
- **sem identidade do PostHog na página** (nada no cookie, no `localStorage` nem
|
|
469
|
+
no `sessionStorage` com o nome dele, `ph_<chave>_posthog`): o snippet passa
|
|
470
|
+
ao posthog-js o `bootstrap` com o `distinctID` e o `sessionID` da origem, e
|
|
471
|
+
`isIdentifiedID` quando o sinal é `i`. O primeiro `$pageview` sai com o
|
|
472
|
+
`distinct_id` e o `$session_id` da origem; de uma origem identificada, com um
|
|
473
|
+
`$device_id` novo (o `ph_anon_id` dos forms nunca é o id do contacto) e o
|
|
474
|
+
estado `identified`. O `bootstrap` junta-se ao que o site passe em
|
|
475
|
+
`posthog.bootstrap`, sem o perder;
|
|
476
|
+
- **com identidade** (anónima ou identificada, guardada ou dada pelo site): o
|
|
477
|
+
browser não a troca, porque o `bootstrap` sobrepunha-a sem evento nenhum, e
|
|
478
|
+
cada evento desta página leva o `linked_distinct_id` (o id que veio no link).
|
|
479
|
+
O admin guarda-o e liga os dois `distinct_id` como factos de ligação;
|
|
480
|
+
- **fora da janela**: nada. A pessoa fica com um id novo, e o admin liga-a por
|
|
481
|
+
outro caminho.
|
|
482
|
+
|
|
483
|
+
**Com `consent: true`** nada acontece antes do sim: o `_f10x` fica em memória,
|
|
484
|
+
o sim aplica-o (a janela conta desde o carregamento), e um não deita-o fora.
|
|
485
|
+
|
|
486
|
+
O que se sabe e se aceitou:
|
|
487
|
+
|
|
488
|
+
- **o `_f10x` fica no URL da página de destino**, onde qualquer tag de
|
|
489
|
+
terceiros o lê, e com o sinal `i` pode levar um email. O PostHog recebe o URL
|
|
490
|
+
inteiro, e a ingestão do admin apara-o como aos `ph_*`;
|
|
491
|
+
- **um link reencaminhado dentro dos 2 minutos junta duas pessoas**: é o preço
|
|
492
|
+
da janela, e 2 minutos é a do `_gl` (apanham 94% dos saltos medidos entre
|
|
493
|
+
hosts do Piko);
|
|
494
|
+
- **um redirect no destino que apague a query string parte o salto**, como no
|
|
495
|
+
GA: a aceitação de um site com a opção prova cada link;
|
|
496
|
+
- **um relógio adiantado no browser de origem perde a sessão, e não a
|
|
497
|
+
pessoa**: o posthog-js ignora um `sessionID` com mais de 1 minuto no futuro.
|
|
498
|
+
|
|
499
|
+
## O contrato dos eventos
|
|
500
|
+
|
|
501
|
+
Um funil manda três eventos custom, e só estes (Fase A41 do plano da
|
|
502
|
+
atribuição, 2026-10-16):
|
|
503
|
+
|
|
504
|
+
| evento | quando | quem o manda |
|
|
505
|
+
| --- | --- | --- |
|
|
506
|
+
| `contact_captured` | o email ou o telefone sai num form, ou chega no URL (`contact_source`: `form` ou `url`), cada valor uma vez por página | o snippet |
|
|
507
|
+
| `checkout` | o **início** do checkout: o clique num link para um host do Stripe ou do `checkoutHosts`, uma vez por link e por página, com o `checkout_host` | o snippet, desde a 2.2.0; um checkout aberto por código (um botão com redirect, um checkout embebido) chama `f10xTracking.capture('checkout')` |
|
|
508
|
+
| `purchase` | o pagamento confirmado, com o `session_id` (o `cs_…` da sessão de checkout do Stripe), o `currency`, o `amount_total` e o `product` | o código do funil, na página de obrigado |
|
|
509
|
+
|
|
510
|
+
- O `contact_captured` é a ponte para o contacto, e **não uma etapa do funil**:
|
|
511
|
+
dispara também num form de checkout, e um opt-in, uma marcação e uma compra
|
|
512
|
+
dão o mesmo. O lead é o contacto no CRM.
|
|
513
|
+
- O `checkout` vai já, e não na fila (o `send_instantly` do posthog-js), porque
|
|
514
|
+
a página sai a seguir. Um site cujo código já mande o seu `checkout` tira-o
|
|
515
|
+
quando passar ao snippet, senão conta dois.
|
|
516
|
+
- O `purchase` liga a venda pelo `cs_…`, por isso tem de disparar em todas as
|
|
517
|
+
compras: no Piko, a 2026-10-16, o `purchase` ligava 78% das vendas e o
|
|
518
|
+
`checkout_completed` todas.
|
|
519
|
+
- Não há evento de marcação: o calendário do GHL vem num iframe, onde o
|
|
520
|
+
PostHog não arranca, e a marcação, a presença e o no-show vêm do GHL.
|
|
521
|
+
- O `lead` e o `checkout_completed` deixaram de ser contrato; o admin continua
|
|
522
|
+
a aceitá-los, pelo histórico e pelos funis que ainda os mandam.
|
|
523
|
+
|
|
300
524
|
## A API
|
|
301
525
|
|
|
302
526
|
`init(options)` (ou a tag) devolve, e põe em `window.f10xTracking`:
|
|
@@ -308,8 +532,9 @@ O que os forms, o iframe e os links do checkout levam:
|
|
|
308
532
|
- `fields()`: os valores de cima, agora;
|
|
309
533
|
- `grant()`, `deny()`, `consent()`: o interruptor de um site `direct`;
|
|
310
534
|
- `onReady(fn)`: quando o PostHog estiver a medir;
|
|
311
|
-
- `capture(event, properties)`: um evento pelo mesmo PostHog (o `
|
|
312
|
-
|
|
535
|
+
- `capture(event, properties)`: um evento pelo mesmo PostHog (o `purchase` da
|
|
536
|
+
página de obrigado, o `checkout` de um checkout aberto por código), que sem
|
|
537
|
+
consentimento não faz nada;
|
|
313
538
|
- `posthog`: a instância do PostHog depois de o SDK arrancar, e o stub até lá
|
|
314
539
|
(o que se lhe chamar fica na fila, como no stub oficial). O
|
|
315
540
|
`window.posthog` é o mesmo, e é por ele que as tags do GTM o usam.
|
|
@@ -397,10 +622,12 @@ Antes de ligar o tráfego:
|
|
|
397
622
|
do `/_t` no `vercel.json`; num site de fora, a tag do `dist/gtm.html` da
|
|
398
623
|
versão, com a chave da account e, se ela tiver o proxy gerido, o `apiHost`.
|
|
399
624
|
O `sdkVersion` fica vazio.
|
|
400
|
-
2. **
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
625
|
+
2. **O snippet, e a oficial como reserva**: este snippet é a única instalação
|
|
626
|
+
activa na página. Ao escolher este, o snippet do PostHog que o site já tenha
|
|
627
|
+
no head ou no código sai quando este entra, e no GTM a tag oficial passa a
|
|
628
|
+
reserva (*A reserva*, acima: só no `f10x_tracking_failed`, com o
|
|
629
|
+
`before_send`); num contentor partilhado, a oficial de sempre fica com a
|
|
630
|
+
condição de inclusão por hostname, e a reserva é outra tag. Com a mesma
|
|
404
631
|
chave não se perde nada: quem volta mantém o id anónimo. **O `apiHost` da
|
|
405
632
|
tag nova é o `api_host` que a antiga tinha** (o proxy, se ela o usava):
|
|
406
633
|
vazio, perdia quem hoje chega por ele. **A data dos `defaults` é a mesma em
|
|
@@ -415,15 +642,25 @@ Antes de ligar o tráfego:
|
|
|
415
642
|
campos de atribuição da tabela, com o *query key* igual ao nome.
|
|
416
643
|
5. **Os links de email e de SMS** levam `contact_id={{contact.id}}`.
|
|
417
644
|
6. **O checkout**: o host em `checkoutHosts` (o Stripe já lá está), e num
|
|
418
|
-
checkout em código os `fields()` na metadata
|
|
645
|
+
checkout em código os `fields()` na metadata e o `capture('checkout')` no
|
|
646
|
+
clique. Um clique de teste num link do checkout deixa um `checkout` no
|
|
647
|
+
PostHog, e a página de obrigado manda o `purchase` com o `cs_…` em todas as
|
|
648
|
+
compras (*O contrato dos eventos*, acima); nenhum outro evento custom.
|
|
419
649
|
7. **Os anúncios**: o texto do gerador de links nos anúncios da Meta e da
|
|
420
650
|
Google, e os links orgânicos gerados por ele, com as UTMs da Traffic Sources.
|
|
421
|
-
8. **A prova**: na consola,
|
|
422
|
-
|
|
423
|
-
PostHog (Activity, no
|
|
424
|
-
|
|
425
|
-
`
|
|
426
|
-
`
|
|
651
|
+
8. **A prova**: na consola, com a reserva instalada,
|
|
652
|
+
`window.f10xTracking.mode` não é `conflict`; um pageview aberto com
|
|
653
|
+
`?email=teste@example.com&utm_source=teste` chega ao PostHog (Activity, no
|
|
654
|
+
projeto da account) uma vez só, inteiro, com o `tracking_version` da versão,
|
|
655
|
+
o `$lib_version` que o CDN serve e nenhum `tracking_conflict` nem
|
|
656
|
+
`tracking_fallback`; os campos do form e o link do checkout levam a
|
|
657
|
+
`utm_source` e não o `email`; e com o jsDelivr bloqueado no browser (nas
|
|
658
|
+
DevTools, *Network request blocking*, `cdn.jsdelivr.net`) chega um só
|
|
659
|
+
`$pageview`, com `tracking_fallback: true` e sem `tracking_version` (sem ele,
|
|
660
|
+
a reserva não disparou: o trigger, a condição de consentimento, ou um GTM com
|
|
661
|
+
a data layer renomeada, onde o evento não chega). Num site
|
|
662
|
+
com `linkedDomains`, cada link para o outro domínio abre com o `_f10x`, e o
|
|
663
|
+
destino, num browser limpo, com o `distinct_id` da origem.
|
|
427
664
|
|
|
428
665
|
## Desenvolver e publicar
|
|
429
666
|
|
|
@@ -442,7 +679,10 @@ serve nesse dia, e abre uma issue quando falha.
|
|
|
442
679
|
|
|
443
680
|
Uma versão nova: subir a `version` no `package.json` (semver: uma mudança no
|
|
444
681
|
que os forms ou os eventos levam é minor, uma que parte uma integração é
|
|
445
|
-
major), `npm run build`,
|
|
682
|
+
major), `npm run build`, e no mesmo PR, em `apps-src/account-settings`, o
|
|
683
|
+
`npm install` e o `npm run install-build` (o Account Settings importa as três
|
|
684
|
+
tags do `dist/` pelo nome do pacote, e a CI falha se o bundle não for o que
|
|
685
|
+
elas dão); depois do merge, da `main`, nesta pasta:
|
|
446
686
|
|
|
447
687
|
```bash
|
|
448
688
|
npm publish --dry-run
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
@funnel10x/tracking@2.2.0: o arranque num site com build próprio, uma vez por carregamento da página, no browser (num Next.js, um
|
|
3
|
+
componente 'use client' no layout de raiz, como o Tracking.tsx da base direct). Só se muda a chave; o consent, os checkoutHosts e os
|
|
4
|
+
linkedDomains são do site (o README do pacote). O /_t só existe com os rewrites do dist/direct-rewrites.json no vercel.json do site.
|
|
5
|
+
*/
|
|
6
|
+
import { init } from '@funnel10x/tracking'
|
|
7
|
+
|
|
8
|
+
init({
|
|
9
|
+
key: '{{PostHog project key}}',
|
|
10
|
+
apiHost: '/_t',
|
|
11
|
+
checkoutHosts: [],
|
|
12
|
+
linkedDomains: []
|
|
13
|
+
})
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"rewrites": [
|
|
3
|
+
{ "source": "/_t/static/:path(.*)", "destination": "https://us-assets.i.posthog.com/static/:path" },
|
|
4
|
+
{ "source": "/_t/array/:path(.*)", "destination": "https://us-assets.i.posthog.com/array/:path" },
|
|
5
|
+
{ "source": "/_t/:path(.*)", "destination": "https://us.i.posthog.com/:path" }
|
|
6
|
+
]
|
|
7
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@funnel10x/tracking@2.2.0: a tag de reserva do GTM (Custom HTML), num site com a tag do gtm.html (decisão 1 da A2c).
|
|
3
|
+
Dispara só no evento personalizado f10x_tracking_failed, com a mesma condição de consentimento da tag do snippet; nunca em All Pages
|
|
4
|
+
nem em Window Loaded. O before_send carimba tracking_fallback em cada evento, que é o que distingue uma visita pela reserva nos dados.
|
|
5
|
+
Só se mudam a chave e o api_host (o proxy gerido da account, se o tiver, e senão o PostHog directo), os mesmos da tag do gtm.html.
|
|
6
|
+
O Account Settings do admin (Integrations, no cartão PostHog) gera-a já preenchida, com a do snippet e os acionadores.
|
|
7
|
+
-->
|
|
8
|
+
<script>
|
|
9
|
+
!function(t,e){var o,n,p,r;e.__SV||(window.posthog && window.posthog.__loaded)||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}p||((p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",p.onerror=function(){p=null},(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r));var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],Object.defineProperty(u,"toString",{configurable:!0,enumerable:!0,writable:!0,value:function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e}}),Object.defineProperty(u.people,"toString",{configurable:!0,enumerable:!0,writable:!0,value:function(){return u.toString(1)+".people (stub)"}}),o="addExceptionStep alias calculateEventProperties canRenderSurvey canRenderSurveyAsync cancelPendingSurvey capture captureException captureLog captureTraceFeedback captureTraceMetric clearIdentity clear_opt_in_out_capturing createPersonProfile debug displaySurvey getActiveMatchingSurveys getAllFeatureFlags getEarlyAccessFeatures getExtension getFeatureFlag getFeatureFlagPayload getFeatureFlagResult getGroups getPageViewId getSessionProperty getSurveys get_distinct_id get_explicit_consent_status get_property get_session_id get_session_replay_url group has_opted_in_capturing has_opted_out_capturing identify init isFeatureEnabled is_capturing loadToolbar on onActiveMatchingSurveysChanged onFeatureFlags onSessionId onSurveysLoaded opt_in_capturing opt_out_capturing register register_for_session register_once reloadFeatureFlags renderSurvey reset resetGroupPropertiesForFlags resetGroups resetPersonPropertiesForFlags sessionRecordingStarted setGroupPropertiesForFlags setIdentity setInternalOrTestUser setPersonProperties setPersonPropertiesForFlags set_config shutdown startExceptionAutocapture startSessionRecording stopExceptionAutocapture stopSessionRecording unregister unregister_for_session unsetPersonProperties updateEarlyAccessFeatureEnrollment updateFlags".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
|
|
10
|
+
posthog.init('{{PostHog project key}}', {
|
|
11
|
+
api_host: 'https://us.i.posthog.com',
|
|
12
|
+
ui_host: 'https://us.posthog.com',
|
|
13
|
+
defaults: '2026-08-30',
|
|
14
|
+
person_profiles: 'identified_only',
|
|
15
|
+
custom_campaign_params: ['a_campaign_id', 'a_adset_id', 'a_ad_id', 'h_ad_id', 'fbc_id', 'utm_id', 'utm_placement', 'lp', 'narrative'],
|
|
16
|
+
before_send: function (event) {
|
|
17
|
+
if (event && event.event !== '$snapshot') {
|
|
18
|
+
event.properties = event.properties || {}
|
|
19
|
+
event.properties.tracking_fallback = true
|
|
20
|
+
}
|
|
21
|
+
return event
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
</script>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@funnel10x/tracking@2.2.0: a tag oficial do PostHog (Custom HTML) para os hosts que ainda não passaram ao snippet, num contentor com a tag do gtm.html.
|
|
3
|
+
Dispara em All Pages, com o acionador Snippet hosts (os hosts da tag do snippet) como excepção, e o Direct hosts (os sites direct, com o
|
|
4
|
+
snippet no build) como outra. Passar um host ao snippet é acrescentá-lo à RegEx do Snippet hosts, numa só publicação.
|
|
5
|
+
Só se mudam a chave e o api_host (o proxy gerido da account, se o tiver, e senão o PostHog directo), os mesmos da tag do gtm.html.
|
|
6
|
+
O Account Settings do admin (Integrations, no cartão PostHog) gera-a já preenchida, com a do snippet e os acionadores.
|
|
7
|
+
-->
|
|
8
|
+
<script>
|
|
9
|
+
!function(t,e){var o,n,p,r;e.__SV||(window.posthog && window.posthog.__loaded)||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}p||((p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",p.onerror=function(){p=null},(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r));var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],Object.defineProperty(u,"toString",{configurable:!0,enumerable:!0,writable:!0,value:function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e}}),Object.defineProperty(u.people,"toString",{configurable:!0,enumerable:!0,writable:!0,value:function(){return u.toString(1)+".people (stub)"}}),o="addExceptionStep alias calculateEventProperties canRenderSurvey canRenderSurveyAsync cancelPendingSurvey capture captureException captureLog captureTraceFeedback captureTraceMetric clearIdentity clear_opt_in_out_capturing createPersonProfile debug displaySurvey getActiveMatchingSurveys getAllFeatureFlags getEarlyAccessFeatures getExtension getFeatureFlag getFeatureFlagPayload getFeatureFlagResult getGroups getPageViewId getSessionProperty getSurveys get_distinct_id get_explicit_consent_status get_property get_session_id get_session_replay_url group has_opted_in_capturing has_opted_out_capturing identify init isFeatureEnabled is_capturing loadToolbar on onActiveMatchingSurveysChanged onFeatureFlags onSessionId onSurveysLoaded opt_in_capturing opt_out_capturing register register_for_session register_once reloadFeatureFlags renderSurvey reset resetGroupPropertiesForFlags resetGroups resetPersonPropertiesForFlags sessionRecordingStarted setGroupPropertiesForFlags setIdentity setInternalOrTestUser setPersonProperties setPersonPropertiesForFlags set_config shutdown startExceptionAutocapture startSessionRecording stopExceptionAutocapture stopSessionRecording unregister unregister_for_session unsetPersonProperties updateEarlyAccessFeatureEnrollment updateFlags".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
|
|
10
|
+
posthog.init('{{PostHog project key}}', {
|
|
11
|
+
api_host: 'https://us.i.posthog.com',
|
|
12
|
+
ui_host: 'https://us.posthog.com',
|
|
13
|
+
defaults: '2026-08-30',
|
|
14
|
+
person_profiles: 'identified_only',
|
|
15
|
+
custom_campaign_params: ['a_campaign_id', 'a_adset_id', 'a_ad_id', 'h_ad_id', 'fbc_id', 'utm_id', 'utm_placement', 'lp', 'narrative']
|
|
16
|
+
})
|
|
17
|
+
</script>
|
package/dist/gtm.html
CHANGED
|
@@ -1,10 +1,45 @@
|
|
|
1
|
-
<!--
|
|
1
|
+
<!--
|
|
2
|
+
@funnel10x/tracking@2.2.0: a tag do GTM (Custom HTML, em All Pages, com a condição de consentimento do site, se ele tiver banner).
|
|
3
|
+
Num site com esta tag, a tag oficial do PostHog só existe como reserva (decisão 1 da A2c): outra tag Custom HTML, com a mesma chave, que dispara
|
|
4
|
+
só no evento personalizado f10x_tracking_failed, que esta empurra para o dataLayer, uma vez, quando o tag.js não carrega (o jsDelivr em baixo ou
|
|
5
|
+
bloqueado, um integrity que não bate) ou carrega e não arranca (o window.f10xTracking sem version). A reserva é o dist/gtm-fallback.html, ao lado.
|
|
6
|
+
Só se mudam a chave, o apiHost (o proxy gerido da account, se o tiver), os checkoutHosts, os linkedDomains (o cross-domain, desligado com a
|
|
7
|
+
lista vazia) e, numa emergência, o sdkVersion (uma versão exacta do posthog-js); uma versão nova do pacote é um ficheiro novo.
|
|
8
|
+
O script do jsDelivr cria-se por código, com o onload e o onerror como propriedades: um atributo onload no HTML é um handler inline, que o GTM
|
|
9
|
+
copia ao recriar o script e que uma CSP com nonce não deixa correr. Um pedido pendurado conta como falhado ao fim de 10 s.
|
|
10
|
+
O evento vai para o window.dataLayer: num GTM com a data layer renomeada (o l= do snippet do GTM) a reserva não dispara, e o ponto 8 do
|
|
11
|
+
checklist do README apanha-o.
|
|
12
|
+
-->
|
|
2
13
|
<script>
|
|
3
14
|
window.f10xTracking = {
|
|
4
15
|
key: '{{PostHog project key}}',
|
|
5
16
|
apiHost: '',
|
|
6
17
|
sdkVersion: '',
|
|
7
|
-
checkoutHosts: []
|
|
18
|
+
checkoutHosts: [],
|
|
19
|
+
linkedDomains: []
|
|
8
20
|
}
|
|
21
|
+
;(function () {
|
|
22
|
+
var timer
|
|
23
|
+
function failed() {
|
|
24
|
+
clearTimeout(timer)
|
|
25
|
+
if (window.__f10xTracking && window.__f10xTracking.version) {
|
|
26
|
+
window.f10xTracking = window.__f10xTracking
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
if (window.__f10xTrackingFailed) return
|
|
30
|
+
window.__f10xTrackingFailed = true
|
|
31
|
+
;(window.dataLayer = window.dataLayer || []).push({ event: 'f10x_tracking_failed' })
|
|
32
|
+
}
|
|
33
|
+
var script = document.createElement('script')
|
|
34
|
+
script.src = 'https://cdn.jsdelivr.net/npm/@funnel10x/tracking@2.2.0/dist/tag.js'
|
|
35
|
+
script.integrity = 'sha384-2j0oWs30fSU+6UtXb4WcrJ0Gi3Ezss5xWEwZ+jFI+8tqVvyJa3zwOPP5n+l99Ksn'
|
|
36
|
+
script.crossOrigin = 'anonymous'
|
|
37
|
+
script.onload = function () {
|
|
38
|
+
clearTimeout(timer)
|
|
39
|
+
if (!(window.f10xTracking && window.f10xTracking.version)) failed()
|
|
40
|
+
}
|
|
41
|
+
script.onerror = failed
|
|
42
|
+
timer = setTimeout(failed, 10000)
|
|
43
|
+
document.head.appendChild(script)
|
|
44
|
+
})()
|
|
9
45
|
</script>
|
|
10
|
-
<script src="https://cdn.jsdelivr.net/npm/@funnel10x/tracking@2.0.0/dist/tag.js" integrity="sha384-vl05BcvhQ0/QtZcEpJZuNM5QB/vPrQB7HVeN58LFs+oG43IoUfgu6Oi6SntNrjyH" crossorigin="anonymous"></script>
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,14 @@ export interface TrackingOptions {
|
|
|
17
17
|
checkoutHosts?: string[]
|
|
18
18
|
/** Add the missing hidden fields to lead forms (default true). */
|
|
19
19
|
addFields?: boolean
|
|
20
|
+
/**
|
|
21
|
+
* Linked domains for cross-domain tracking (off by default): hosts, or registrable domains that also cover their
|
|
22
|
+
* subdomains, as a list or a string separated by commas or spaces (an entry that is not a hostname, like
|
|
23
|
+
* `*.example.com`, is ignored with a console warning). Links and forms to them carry `_f10x` on click or submit, and
|
|
24
|
+
* an `_f10x` that arrives within 2 minutes links the visitor: the origin's person and session when the page has no
|
|
25
|
+
* PostHog identity yet, or `linked_distinct_id` on every event when it has one.
|
|
26
|
+
*/
|
|
27
|
+
linkedDomains?: string[] | string
|
|
20
28
|
/** posthog-js options on top of this package's (turning a feature off on one site, tests). */
|
|
21
29
|
posthog?: Record<string, unknown>
|
|
22
30
|
}
|