cdp-edge 1.2.2 → 1.3.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.
Files changed (141) hide show
  1. package/README.md +153 -306
  2. package/bin/cdp-edge.js +71 -61
  3. package/contracts/agent-versions.json +682 -0
  4. package/contracts/api-versions.json +372 -368
  5. package/contracts/types.ts +81 -0
  6. package/dist/commands/analyze.js +52 -52
  7. package/dist/commands/infra.js +54 -54
  8. package/dist/commands/install.js +26 -3
  9. package/dist/commands/server.js +174 -174
  10. package/dist/commands/setup.js +332 -100
  11. package/dist/commands/validate.js +248 -84
  12. package/dist/index.js +12 -12
  13. package/dist/sdk/cdpTrack.js +2095 -0
  14. package/dist/sdk/cdpTrack.min.js +64 -0
  15. package/dist/sdk/install-snippet.html +10 -0
  16. package/docs/whatsapp-ctwa.md +5 -4
  17. package/extracted-skill/tracking-events-generator/INTEGRACAO-COMPLETA.md +89 -0
  18. package/extracted-skill/tracking-events-generator/MELHORIAS-IMPLEMENTADAS.md +101 -0
  19. package/extracted-skill/tracking-events-generator/advanced-matching.js +364 -364
  20. package/extracted-skill/tracking-events-generator/agents/ab-ltv-agent.md +196 -0
  21. package/extracted-skill/tracking-events-generator/agents/ab-testing-agent.md +1 -1
  22. package/extracted-skill/tracking-events-generator/agents/attribution-agent.md +41 -41
  23. package/extracted-skill/tracking-events-generator/agents/bidding-agent.md +347 -0
  24. package/extracted-skill/tracking-events-generator/agents/bing-agent.md +40 -50
  25. package/extracted-skill/tracking-events-generator/agents/browser-tracking.md +174 -74
  26. package/extracted-skill/tracking-events-generator/agents/code-guardian-agent.md +1 -1
  27. package/extracted-skill/tracking-events-generator/agents/compliance-agent.md +25 -5
  28. package/extracted-skill/tracking-events-generator/agents/dashboard-agent.md +10 -10
  29. package/extracted-skill/tracking-events-generator/agents/database-agent.md +43 -42
  30. package/extracted-skill/tracking-events-generator/agents/debug-agent.md +22 -22
  31. package/extracted-skill/tracking-events-generator/agents/devops-agent.md +232 -0
  32. package/extracted-skill/tracking-events-generator/agents/domain-setup-agent.md +23 -9
  33. package/extracted-skill/tracking-events-generator/agents/email-agent.md +28 -1
  34. package/extracted-skill/tracking-events-generator/agents/evo-crm-agent.md +244 -0
  35. package/extracted-skill/tracking-events-generator/agents/fingerprint-agent.md +206 -1
  36. package/extracted-skill/tracking-events-generator/agents/fraud-detection-agent.md +143 -0
  37. package/extracted-skill/tracking-events-generator/agents/google-agent.md +128 -2
  38. package/extracted-skill/tracking-events-generator/agents/intelligence-agent.md +191 -31
  39. package/extracted-skill/tracking-events-generator/agents/lead-scoring-agent.md +282 -0
  40. package/extracted-skill/tracking-events-generator/agents/linkedin-agent.md +145 -34
  41. package/extracted-skill/tracking-events-generator/agents/localization-agent.md +1 -1
  42. package/extracted-skill/tracking-events-generator/agents/ltv-predictor-agent.md +5 -5
  43. package/extracted-skill/tracking-events-generator/agents/master-feedback-loop.md +81 -21
  44. package/extracted-skill/tracking-events-generator/agents/master-orchestrator.md +313 -93
  45. package/extracted-skill/tracking-events-generator/agents/match-quality-agent.md +304 -0
  46. package/extracted-skill/tracking-events-generator/agents/memory-agent.md +190 -15
  47. package/extracted-skill/tracking-events-generator/agents/meta-agent.md +10 -2
  48. package/extracted-skill/tracking-events-generator/agents/ml-clustering-agent.md +749 -0
  49. package/extracted-skill/tracking-events-generator/agents/page-analyzer.md +21 -4
  50. package/extracted-skill/tracking-events-generator/agents/performance-agent.md +41 -31
  51. package/extracted-skill/tracking-events-generator/agents/performance-optimization-agent.md +18 -8
  52. package/extracted-skill/tracking-events-generator/agents/pinterest-agent.md +14 -6
  53. package/extracted-skill/tracking-events-generator/agents/premium-tracking-intelligence-agent.md +7 -7
  54. package/extracted-skill/tracking-events-generator/agents/r2-setup-agent.md +16 -8
  55. package/extracted-skill/tracking-events-generator/agents/reddit-agent.md +15 -7
  56. package/extracted-skill/tracking-events-generator/agents/security-enterprise-agent.md +157 -48
  57. package/extracted-skill/tracking-events-generator/agents/server-tracking.md +35 -35
  58. package/extracted-skill/tracking-events-generator/agents/spotify-agent.md +15 -7
  59. package/extracted-skill/tracking-events-generator/agents/tiktok-agent.md +73 -2
  60. package/extracted-skill/tracking-events-generator/agents/tracking-plan-agent.md +104 -9
  61. package/extracted-skill/tracking-events-generator/agents/utm-agent.md +322 -0
  62. package/extracted-skill/tracking-events-generator/agents/validator-agent.md +13 -9
  63. package/extracted-skill/tracking-events-generator/agents/webhook-agent.md +112 -4
  64. package/extracted-skill/tracking-events-generator/agents/whatsapp-agent.md +58 -5
  65. package/extracted-skill/tracking-events-generator/agents/whatsapp-ctwa-setup-agent.md +26 -18
  66. package/extracted-skill/tracking-events-generator/agents/youtube-agent.md +152 -37
  67. package/extracted-skill/tracking-events-generator/anti-blocking.js +285 -285
  68. package/extracted-skill/tracking-events-generator/cdpTrack.js +642 -641
  69. package/extracted-skill/tracking-events-generator/contracts/api-versions.json +14 -10
  70. package/extracted-skill/tracking-events-generator/engagement-scoring.js +226 -226
  71. package/extracted-skill/tracking-events-generator/evals/evals.json +235 -235
  72. package/extracted-skill/tracking-events-generator/integration-test.js +497 -497
  73. package/extracted-skill/tracking-events-generator/knowledge-base.md +172 -0
  74. package/extracted-skill/tracking-events-generator/micro-events.js +992 -992
  75. package/extracted-skill/tracking-events-generator/models/lancamento-imobiliario.md +344 -0
  76. package/extracted-skill/tracking-events-generator/models/pinterest/conversions-api-template.js +144 -144
  77. package/extracted-skill/tracking-events-generator/models/pinterest/event-mappings.json +48 -48
  78. package/extracted-skill/tracking-events-generator/models/pinterest/tag-template.js +28 -28
  79. package/extracted-skill/tracking-events-generator/models/quiz-funnel.md +83 -19
  80. package/extracted-skill/tracking-events-generator/models/reddit/conversions-api-template.js +205 -205
  81. package/extracted-skill/tracking-events-generator/models/reddit/event-mappings.json +56 -56
  82. package/extracted-skill/tracking-events-generator/models/reddit/pixel-template.js +19 -19
  83. package/extracted-skill/tracking-events-generator/models/scenarios/behavior-engine.js +425 -425
  84. package/extracted-skill/tracking-events-generator/route-intent-capture.js +222 -0
  85. package/extracted-skill/tracking-events-generator/tracking.config.js +3 -3
  86. package/package.json +89 -75
  87. package/scripts/build-sdk.js +106 -0
  88. package/server-edge-tracker/.client.env.example +14 -0
  89. package/server-edge-tracker/INSTALAR.md +222 -23
  90. package/server-edge-tracker/SEGMENTATION-DOCS.md +513 -0
  91. package/server-edge-tracker/config/utm-mapping.json +64 -0
  92. package/server-edge-tracker/deploy-client.cjs +76 -0
  93. package/server-edge-tracker/index.ts +1230 -0
  94. package/server-edge-tracker/migrate-v7.sql +64 -0
  95. package/server-edge-tracker/modules/db.ts +710 -0
  96. package/server-edge-tracker/modules/dispatch/crm.ts +382 -0
  97. package/server-edge-tracker/modules/dispatch/ga4.ts +72 -0
  98. package/server-edge-tracker/modules/dispatch/meta.ts +143 -0
  99. package/server-edge-tracker/modules/dispatch/platforms.ts +255 -0
  100. package/server-edge-tracker/modules/dispatch/tiktok.ts +107 -0
  101. package/server-edge-tracker/modules/dispatch/whatsapp.ts +296 -0
  102. package/server-edge-tracker/modules/intelligence.ts +589 -0
  103. package/server-edge-tracker/modules/ml/bidding.ts +247 -0
  104. package/server-edge-tracker/modules/ml/fraud.ts +302 -0
  105. package/server-edge-tracker/modules/ml/logistic.ts +226 -0
  106. package/server-edge-tracker/modules/ml/ltv.ts +531 -0
  107. package/server-edge-tracker/modules/ml/matchquality.ts +232 -0
  108. package/server-edge-tracker/modules/ml/quiz.ts +343 -0
  109. package/server-edge-tracker/modules/ml/roas.ts +255 -0
  110. package/server-edge-tracker/modules/ml/segmentation.ts +407 -0
  111. package/server-edge-tracker/modules/nurture.ts +257 -0
  112. package/server-edge-tracker/modules/utils.ts +311 -0
  113. package/server-edge-tracker/modules/utm/utm-enricher.ts +231 -0
  114. package/server-edge-tracker/schema-ab-ltv.sql +97 -0
  115. package/server-edge-tracker/schema-bidding.sql +86 -0
  116. package/server-edge-tracker/schema-fraud.sql +90 -0
  117. package/server-edge-tracker/schema-indexes.sql +67 -0
  118. package/server-edge-tracker/schema-ltv-feedback.sql +11 -0
  119. package/server-edge-tracker/schema-quiz.sql +52 -0
  120. package/server-edge-tracker/schema-sales-engine.sql +113 -0
  121. package/server-edge-tracker/schema-segmentation.sql +219 -0
  122. package/server-edge-tracker/schema-utm.sql +82 -0
  123. package/server-edge-tracker/schema.sql +281 -265
  124. package/server-edge-tracker/types.ts +275 -0
  125. package/server-edge-tracker/wrangler.toml +140 -85
  126. package/templates/lancamento-imobiliario.md +344 -0
  127. package/templates/multi-step-checkout.md +3 -4
  128. package/templates/pinterest/conversions-api-template.js +144 -144
  129. package/templates/pinterest/event-mappings.json +48 -48
  130. package/templates/pinterest/tag-template.js +28 -28
  131. package/templates/quiz-funnel.md +83 -19
  132. package/templates/reddit/conversions-api-template.js +205 -205
  133. package/templates/reddit/event-mappings.json +56 -56
  134. package/templates/reddit/pixel-template.js +12 -39
  135. package/templates/scenarios/behavior-engine.js +45 -22
  136. package/docs/PixelBuilder-Documentacao-Completa (2).docx +0 -0
  137. package/docs/installation.md +0 -155
  138. package/docs/quick-start.md +0 -185
  139. package/extracted-skill/tracking-events-generator/agents/crm-integration-agent.md +0 -1419
  140. package/extracted-skill/tracking-events-generator/agents/intelligence-scheduling.md +0 -643
  141. package/server-edge-tracker/worker.js +0 -2574
@@ -5,6 +5,14 @@ Sua missão: configurar o rastreamento completo de anúncios Click to WhatsApp d
5
5
 
6
6
  ---
7
7
 
8
+ ## ✅ REGRAS CRÍTICAS
9
+
10
+ 0. **CONSULTA OBRIGATÓRIA À MEMÓRIA**: Extraia o ID de Número WhatsApp, Token de API e Token de Verificação (`WHATSAPP_PHONE_NUMBER_ID`, `WHATSAPP_ACCESS_TOKEN`, `WA_WEBHOOK_VERIFY_TOKEN`) consultando ativamente o "memory-agent.json". Solicite ao Orquestrador tudo o que faltar. Execute configurações de WhatsApp exclusivamente com os dados oficiais guardados na Memória para garantir alinhamento sistêmico.
11
+ 1. Cloudflare-Only: Sem dependências externas.
12
+ 2. Same-Domain: Worker no domínio do site (anti-adblock).
13
+
14
+ ---
15
+
8
16
  ## PARTE 1 — FUNDAMENTOS: O QUE É CTWA E COMO OS DADOS FLUEM
9
17
 
10
18
  ### O que é Click to WhatsApp (CTWA)
@@ -164,8 +172,8 @@ message_body | Olá, vi o anúncio e tenho interesse
164
172
  [ ] META_APP_ID — ID do app no Meta for Developers ← usuário fornece
165
173
  [ ] META_APP_SECRET — App Secret (developers.facebook.com → Básico) ← usuário fornece
166
174
  [ ] WA_WEBHOOK_VERIFY_TOKEN — gerado pelo agente (crypto.randomUUID) ← agente cria
167
- [ ] WA_PHONE_ID — descoberto automaticamente via API ← agente descobre
168
- [ ] WA_ACCESS_TOKEN — mesmo que META_ACCESS_TOKEN ← agente reutiliza
175
+ [ ] WHATSAPP_PHONE_NUMBER_ID — descoberto automaticamente via API ← agente descobre
176
+ [ ] WHATSAPP_ACCESS_TOKEN — mesmo que META_ACCESS_TOKEN ← agente reutiliza
169
177
  [ ] WHATSAPP_BUSINESS_ACCOUNT_ID — descoberto automaticamente via API ← agente descobre
170
178
  ```
171
179
 
@@ -175,7 +183,7 @@ message_body | Olá, vi o anúncio e tenho interesse
175
183
  3. `META_APP_SECRET`
176
184
 
177
185
  **O agente gera/descobre o restante automaticamente:**
178
- ```javascript
186
+ ```typescript
179
187
  // WA_WEBHOOK_VERIFY_TOKEN — gerado pelo agente antes de registrar o webhook
180
188
  const WA_WEBHOOK_VERIFY_TOKEN = crypto.randomUUID().replace(/-/g, '') + crypto.randomUUID().replace(/-/g, '');
181
189
  // Exemplo: "a3f8c1d2e4b5a6f7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1"
@@ -490,16 +498,16 @@ Deve mostrar o app com `override_callback_uri` (se não-SMB) ou apenas o app sub
490
498
 
491
499
  ```bash
492
500
  echo "{WABA_ID}" | wrangler secret put WHATSAPP_BUSINESS_ACCOUNT_ID
493
- echo "{PHONE_ID}" | wrangler secret put WA_PHONE_ID
494
- echo "{META_ACCESS_TOKEN}" | wrangler secret put WA_ACCESS_TOKEN
501
+ echo "{PHONE_ID}" | wrangler secret put WHATSAPP_PHONE_NUMBER_ID
502
+ echo "{META_ACCESS_TOKEN}" | wrangler secret put WHATSAPP_ACCESS_TOKEN
495
503
  echo "{META_APP_SECRET}" | wrangler secret put META_APP_SECRET
496
504
  echo "{META_ACCESS_TOKEN}" | wrangler secret put META_ACCESS_TOKEN
497
505
 
498
506
  # ── Secrets para Auto-Resposta WhatsApp (enviar mensagens de saída) ─────────
499
- # Necessários para: worker.js → auto-resposta após Lead/Purchase
500
- # WHATSAPP_TOKEN = mesmo token Meta (Cloud API) — pode reutilizar META_ACCESS_TOKEN
507
+ # Necessários para: index.ts → auto-resposta após Lead/Purchase
508
+ # WHATSAPP_ACCESS_TOKEN = mesmo token Meta (Cloud API) — pode reutilizar META_ACCESS_TOKEN
501
509
  # WHATSAPP_PHONE_NUMBER_ID = mesmo {PHONE_ID} descoberto acima
502
- echo "{META_ACCESS_TOKEN}" | wrangler secret put WHATSAPP_TOKEN
510
+ echo "{META_ACCESS_TOKEN}" | wrangler secret put WHATSAPP_ACCESS_TOKEN
503
511
  echo "{PHONE_ID}" | wrangler secret put WHATSAPP_PHONE_NUMBER_ID
504
512
 
505
513
  # Confirmar todos
@@ -510,15 +518,15 @@ Secrets esperados no worker ao final:
510
518
  ```
511
519
  META_ACCESS_TOKEN
512
520
  META_APP_SECRET
513
- WA_ACCESS_TOKEN
514
- WA_PHONE_ID
521
+ WHATSAPP_ACCESS_TOKEN
522
+ WHATSAPP_PHONE_NUMBER_ID
515
523
  WA_WEBHOOK_VERIFY_TOKEN
516
524
  WHATSAPP_BUSINESS_ACCOUNT_ID
517
- WHATSAPP_TOKEN ← auto-resposta outbound (mesmo valor de META_ACCESS_TOKEN)
518
- WHATSAPP_PHONE_NUMBER_ID ← auto-resposta outbound (mesmo valor de WA_PHONE_ID)
525
+ WHATSAPP_ACCESS_TOKEN ← auto-resposta outbound (mesmo valor de META_ACCESS_TOKEN)
526
+ WHATSAPP_PHONE_NUMBER_ID ← auto-resposta outbound (mesmo valor de WHATSAPP_PHONE_NUMBER_ID)
519
527
  ```
520
528
 
521
- > **Nota:** `WHATSAPP_TOKEN` e `WHATSAPP_PHONE_NUMBER_ID` são usados pela função de auto-resposta no worker (envio de mensagens de saída para o lead após eventos de conversão). São o mesmo token/phone_id da CTWA — apenas referenciados por nomes distintos no código.
529
+ > **Nota:** `WHATSAPP_ACCESS_TOKEN` e `WHATSAPP_PHONE_NUMBER_ID` são usados pela função de auto-resposta no worker (envio de mensagens de saída para o lead após eventos de conversão). São o mesmo token/phone_id da CTWA — apenas referenciados por nomes distintos no código.
522
530
 
523
531
  ---
524
532
 
@@ -603,13 +611,13 @@ App: {META_APP_ID} — subscriptions: messages ✅
603
611
 
604
612
  SECRETS NO WORKER:
605
613
  ✅ META_ACCESS_TOKEN
606
- WA_ACCESS_TOKEN
607
- WA_PHONE_ID → {PHONE_ID}
614
+ WHATSAPP_ACCESS_TOKEN
615
+ WHATSAPP_PHONE_NUMBER_ID → {PHONE_ID}
608
616
  ✅ WA_WEBHOOK_VERIFY_TOKEN
609
617
  ✅ WHATSAPP_BUSINESS_ACCOUNT_ID → {WABA_ID}
610
618
  ✅ META_APP_SECRET
611
- WHATSAPP_TOKEN → mesmo valor de META_ACCESS_TOKEN (auto-resposta)
612
- ✅ WHATSAPP_PHONE_NUMBER_ID → mesmo valor de WA_PHONE_ID (auto-resposta)
619
+ WHATSAPP_ACCESS_TOKEN → mesmo valor de META_ACCESS_TOKEN (auto-resposta)
620
+ ✅ WHATSAPP_PHONE_NUMBER_ID → mesmo valor de WHATSAPP_PHONE_NUMBER_ID (auto-resposta)
613
621
 
614
622
  TESTE E2E:
615
623
  ✅ GET verificação → challenge retornado
@@ -674,7 +682,7 @@ PRÓXIMO PASSO:
674
682
 
675
683
  | Arquivo | Função |
676
684
  |---------|--------|
677
- | `server-edge-tracker/worker.js` | `processWhatsAppWebhook()` (linha ~943) + rotas `GET/POST /webhook/whatsapp` (linha ~2182) |
685
+ | `server-edge-tracker/index.ts` | `processWhatsAppWebhook()` + rotas `GET/POST /webhook/whatsapp` |
678
686
  | `server-edge-tracker/migrate-v6.sql` | Criação da tabela `whatsapp_contacts` com índices |
679
687
  | `server-edge-tracker/wrangler.toml` | Configuração do worker + lista de secrets documentados |
680
688
  | `docs/whatsapp-ctwa.md` | Documentação técnica completa do módulo CTWA |
@@ -33,7 +33,7 @@ YouTube Ad (TrueView / Bumper / Non-skip)
33
33
 
34
34
  ### PASSO 0 — Ler Versões Atuais
35
35
 
36
- ```javascript
36
+ ```typescript
37
37
  const apiVersions = await readJSON('contracts/api-versions.json');
38
38
  const googleVersions = apiVersions.google;
39
39
 
@@ -53,7 +53,7 @@ if (consentModeVersion !== 'v2') {
53
53
 
54
54
  ### TrueView In-Stream (pulável após 5s)
55
55
  - **Evento de billing**: view confirmada após 30s ou clique
56
- - **Rastrear**: `video_start`, `video_progress_30s`, `video_complete`, clique no CTA
56
+ - **Rastrear**: `video_start`, `video_complete`, clique no CTA
57
57
  - **Conversão Google Ads**: `engaged_view` (30s assistidos = 1 conversão de vídeo)
58
58
 
59
59
  ### Bumper Ads (6s não-puláveis)
@@ -89,39 +89,152 @@ const _gbraid = _urlParams.get('gbraid') || ''; // App campaigns (privacy)
89
89
  **ATENÇÃO wbraid/gbraid**: São os click IDs para campanhas YouTube em iOS (pós ATT).
90
90
  Nunca hashear — enviar como texto plano para Google Ads API.
91
91
 
92
- ### 2. Rastreamento de vídeo YouTube na página
92
+ ### 2. Rastreamento de vídeo YouTube na página — YouTube IFrame API
93
93
 
94
- O `behavior-engine.js` já implementa rastreamento de vídeos via YouTube IFrame API.
95
94
  Para usar, o iframe deve ter `enablejsapi=1`:
96
95
 
97
96
  ```html
98
- <!-- Embed YouTube com JS API habilitada -->
97
+ <!-- Embed YouTube com JS API habilitada (obrigatório) -->
99
98
  <iframe
100
99
  id="video-tour-imovel"
101
- src="https://www.youtube.com/embed/VIDEO_ID?enablejsapi=1"
100
+ src="https://www.youtube.com/embed/VIDEO_ID?enablejsapi=1&origin=https://seudominio.com.br"
102
101
  allow="autoplay"
103
102
  ></iframe>
104
103
  ```
105
104
 
106
- O BehaviorEngine detecta automaticamente e dispara via `cdpTrack.track()`:
107
- - `video_milestone` com `percent: 25, 50, 75, 100`
108
- - Score: +10 (25%), +15 (50%), +25 (75%/100%)
105
+ #### Implementação real do YouTube IFrame API listener
106
+
107
+ ```javascript
108
+ /**
109
+ * YouTube IFrame API Listener — injeta no behavior-engine.js ou tracking.js
110
+ * Rastreia: video_start, video_25, video_50, video_75, video_complete
111
+ * Dispara via cdpTrack.track() para o Worker → GA4 MP + demais plataformas
112
+ */
113
+
114
+ // Carregar YouTube IFrame API (uma vez por página)
115
+ (function initYouTubeTracking() {
116
+ if (window._ytTrackingInitialized) return;
117
+ window._ytTrackingInitialized = true;
118
+
119
+ // Mapa de iframes já trackeados
120
+ const trackedPlayers = new Map();
121
+
122
+ // Injetar API script do YouTube (não carrega 2x se já existe)
123
+ if (!document.getElementById('youtube-iframe-api')) {
124
+ const tag = document.createElement('script');
125
+ tag.id = 'youtube-iframe-api';
126
+ tag.src = 'https://www.youtube.com/iframe_api';
127
+ document.head.appendChild(tag);
128
+ }
129
+
130
+ // Callback global chamado pelo YouTube quando API estiver pronta
131
+ window.onYouTubeIframeAPIReady = function() {
132
+ // Auto-detectar todos os iframes com enablejsapi=1
133
+ document.querySelectorAll('iframe[src*="youtube.com/embed"]').forEach(iframe => {
134
+ if (trackedPlayers.has(iframe.id)) return;
135
+
136
+ const videoTitle = iframe.title || iframe.id || 'YouTube Video';
137
+
138
+ const player = new YT.Player(iframe.id, {
139
+ events: {
140
+ onStateChange: (event) => handlePlayerStateChange(event, player, videoTitle),
141
+ onReady: (event) => handlePlayerReady(event, player, videoTitle)
142
+ }
143
+ });
144
+
145
+ trackedPlayers.set(iframe.id, { player, milestone: new Set() });
146
+ });
147
+ };
148
+
149
+ // Se API já carregada (SPA reload), inicializar diretamente
150
+ if (typeof YT !== 'undefined' && YT.Player) {
151
+ window.onYouTubeIframeAPIReady();
152
+ }
153
+
154
+ function handlePlayerReady(event, player, videoTitle) {
155
+ // Iniciar polling de progresso
156
+ const iframeId = player.getIframe().id;
157
+ const state = trackedPlayers.get(iframeId);
158
+
159
+ const interval = setInterval(() => {
160
+ if (!player.getDuration) return;
161
+ const duration = player.getDuration();
162
+ const current = player.getCurrentTime();
163
+ if (duration <= 0) return;
164
+
165
+ const percent = Math.floor((current / duration) * 100);
166
+
167
+ // Disparar milestones: 25, 50, 75 (100% é coberto pelo estado ENDED)
168
+ const milestoneEvents = { 25: 'video_25', 50: 'video_50', 75: 'video_75' };
169
+ [25, 50, 75].forEach(milestone => {
170
+ if (percent >= milestone && !state.milestone.has(milestone)) {
171
+ state.milestone.add(milestone);
172
+
173
+ window.cdpTrack?.track(milestoneEvents[milestone], {
174
+ content_name: videoTitle,
175
+ video_percent: milestone,
176
+ video_duration: Math.round(duration),
177
+ video_provider: 'youtube',
178
+ value: 0,
179
+ currency: 'BRL'
180
+ });
181
+ }
182
+ });
183
+ }, 1000); // checar a cada 1s
184
+
185
+ state.progressInterval = interval;
186
+ }
187
+
188
+ function handlePlayerStateChange(event, player, videoTitle) {
189
+ const iframeId = player.getIframe().id;
190
+ const state = trackedPlayers.get(iframeId);
191
+
192
+ // YT.PlayerState: PLAYING=1, PAUSED=2, ENDED=0, BUFFERING=3
193
+ switch (event.data) {
194
+ case YT.PlayerState.PLAYING:
195
+ if (!state.started) {
196
+ state.started = true;
197
+ window.cdpTrack?.track('video_start', {
198
+ content_name: videoTitle,
199
+ video_duration: Math.round(player.getDuration() || 0),
200
+ video_provider: 'youtube'
201
+ });
202
+ }
203
+ break;
204
+
205
+ case YT.PlayerState.ENDED:
206
+ clearInterval(state.progressInterval);
207
+ window.cdpTrack?.track('video_complete', {
208
+ content_name: videoTitle,
209
+ video_duration: Math.round(player.getDuration() || 0),
210
+ video_provider: 'youtube'
211
+ });
212
+ break;
213
+ }
214
+ }
215
+ })();
216
+ ```
217
+
218
+ O listener dispara via `cdpTrack.track()`:
219
+ - `video_start` — primeiros 2s de play
220
+ - `video_25`, `video_50`, `video_75` — marcos de progresso (25/50/75%)
221
+ - `video_complete` — 100% assistido
109
222
 
110
223
  ### 3. Evento de Lead após assistir vídeo (imóveis)
111
224
 
112
225
  ```javascript
113
226
  // Disparar Lead qualificado quando usuário assiste 75%+ do tour
114
- document.addEventListener('pb:video_milestone', (e) => {
115
- if (e.detail.percent >= 75) {
116
- cdpTrack.track('InitiateCheckout', {
117
- content_name: 'Tour_Virtual_Empreendimento',
118
- value: 0,
119
- currency: 'BRL',
120
- // Sinaliza alta intenção para Meta + Google
121
- meta_intensity: 'high',
122
- });
123
- }
124
- });
227
+ // Adicionar dentro do callback de milestoneEvents no IFrame API listener:
228
+ // milestoneEvents[75] 'video_75' — adicionar lógica abaixo no bloco forEach
229
+ if (milestone === 75) {
230
+ window.cdpTrack?.track('InitiateCheckout', {
231
+ content_name: 'Tour_Virtual_Empreendimento',
232
+ value: 0,
233
+ currency: 'BRL',
234
+ // Sinaliza alta intenção para Meta + Google
235
+ meta_intensity: 'high',
236
+ });
237
+ }
125
238
  ```
126
239
 
127
240
  ### 4. Consent Mode v2 — OBRIGATÓRIO para YouTube/Google Ads
@@ -140,7 +253,7 @@ cdpTrack.updateConsent({ analytics: true, ads: true });
140
253
 
141
254
  ---
142
255
 
143
- ## 🛠️ IMPLEMENTAÇÃO SERVER — worker.js
256
+ ## 🛠️ IMPLEMENTAÇÃO SERVER — index.ts
144
257
 
145
258
  ### 1. Extrair e persistir Click IDs do YouTube
146
259
 
@@ -149,7 +262,7 @@ O `upsertProfile()` já persiste `gclid`, `wbraid`, `gbraid` no D1.
149
262
 
150
263
  Para verificar persistência correta:
151
264
 
152
- ```javascript
265
+ ```typescript
153
266
  // D1: user_profiles — colunas já existentes
154
267
  // gclid TEXT — Google Ads standard click ID
155
268
  // wbraid TEXT — iOS privacy-preserving (YouTube)
@@ -158,12 +271,14 @@ Para verificar persistência correta:
158
271
 
159
272
  ### 2. GA4 Measurement Protocol — Eventos de Vídeo
160
273
 
161
- ```javascript
274
+ ```typescript
162
275
  // No sendGA4Mp() — adicionar mapeamento de eventos YouTube
163
276
  const VIDEO_GA4_MAP = {
164
- video_start: 'video_start',
165
- video_milestone: 'video_progress', // GA4 usa video_progress com percent
166
- video_complete: 'video_complete',
277
+ video_start: 'video_start',
278
+ video_25: 'video_progress', // GA4 usa video_progress com percent
279
+ video_50: 'video_progress',
280
+ video_75: 'video_progress',
281
+ video_complete: 'video_complete',
167
282
  };
168
283
 
169
284
  // Params obrigatórios para video_progress (GA4)
@@ -178,7 +293,7 @@ const videoParams = {
178
293
 
179
294
  ### 3. Google Ads Enhanced Conversions — Lead de Vídeo
180
295
 
181
- ```javascript
296
+ ```typescript
182
297
  // Conversão de Lead gerada por campanha YouTube
183
298
  // Envia para GA4 MP com user_data para Enhanced Conversions
184
299
  const enhancedConversionPayload = {
@@ -211,7 +326,7 @@ const enhancedConversionPayload = {
211
326
  Para campanhas Bumper/Non-skip, o usuário converte DEPOIS sem clicar.
212
327
  O Worker detecta isso quando um Lead chega SEM gclid mas com histórico de impressão YouTube:
213
328
 
214
- ```javascript
329
+ ```typescript
215
330
  // No upsertProfile() — verificar se perfil tem impressão YouTube recente
216
331
  // (requer webhook do Google Ads — avançado, Fase 5)
217
332
  // Por ora: registrar ausência de gclid + utm_source=youtube como view-through candidate
@@ -228,9 +343,9 @@ if (!payload.gclid && payload.utmSource === 'youtube') {
228
343
  | Evento cdpTrack | Mapeamento GA4 | Mapeamento Google Ads | Quando Disparar |
229
344
  |---|---|---|---|
230
345
  | `video_start` | `video_start` | — | Primeiros 2s de reprodução |
231
- | `video_milestone` (25%) | `video_progress` | — | 25% assistido |
232
- | `video_milestone` (50%) | `video_progress` | `engaged_view` candidate | 50% assistido |
233
- | `video_milestone` (75%) | `video_progress` | `engaged_view` | 75% assistido — alta intenção |
346
+ | `video_25` | `video_progress` | — | 25% assistido |
347
+ | `video_50` | `video_progress` | `engaged_view` candidate | 50% assistido |
348
+ | `video_75` | `video_progress` | `engaged_view` | 75% assistido — alta intenção |
234
349
  | `video_complete` | `video_complete` | `video_view_complete` | 100% assistido |
235
350
  | `Lead` (após vídeo) | `generate_lead` | Conversão primária | Formulário submetido |
236
351
  | `InitiateCheckout` | `begin_checkout` | Conversão micro | Clique em "Quero saber mais" |
@@ -244,7 +359,7 @@ if (!payload.gclid && payload.utmSource === 'youtube') {
244
359
  ```
245
360
  FASE 1: AWARENESS (YouTube TrueView 30s)
246
361
  ↓ Tour aéreo do empreendimento / lifestyle do bairro
247
- ↓ Rastrear: video_milestone 50% + 75% → score alto no LTV
362
+ ↓ Rastrear: video_50 + video_75 → score alto no LTV
248
363
  ↓ Remarketing: quem assistiu 50%+ vira audiência no Google Ads
249
364
 
250
365
  FASE 2: CONSIDERAÇÃO (YouTube Non-skip 15s + Display)
@@ -303,7 +418,7 @@ const YOUTUBE_AUDIENCES_IMOVEIS = {
303
418
 
304
419
  ### Customer Match — Exportar leads do D1 para Google Ads
305
420
 
306
- ```javascript
421
+ ```typescript
307
422
  // Endpoint no Worker: GET /export/customer-match
308
423
  // Gera CSV criptografado para upload no Google Ads
309
424
 
@@ -334,7 +449,7 @@ async function exportCustomerMatchList(env) {
334
449
 
335
450
  O Intelligence Agent (cron semanal) deve incluir check de YouTube:
336
451
 
337
- ```javascript
452
+ ```typescript
338
453
  // Adicionar ao checkApiVersionsIntelligence():
339
454
  // Verificar se wbraid/gbraid estão chegando nos leads
340
455
  // (indica que campanhas YouTube iOS estão funcionando)
@@ -390,7 +505,7 @@ if (youtubeMobileLeads.count === 0) {
390
505
 
391
506
  ## RESPONSABILIDADE
392
507
 
393
- - Gerar eventos de progresso de vídeo (`video_start`, `video_progress_25/50/75/90`, `video_complete`) via GA4
508
+ - Gerar eventos de progresso de vídeo (`video_start`, `video_25`, `video_50`, `video_75`, `video_complete`) via GA4
394
509
  - Implementar YouTube IFrame API listener para rastreamento de VSL no browser
395
510
  - Garantir `gclid`, `wbraid`, `gbraid` chegando ao Worker (nunca hashear estes campos)
396
511
  - Persistir `ga_client_id` no D1 para cruzamento com conversões YouTube Ads
@@ -403,11 +518,11 @@ if (youtubeMobileLeads.count === 0) {
403
518
  {
404
519
  "arquivos_gerados": {
405
520
  "browser": "cdpTrack.js (eventos YouTube + IFrame API listener)",
406
- "server": "cloudflare/google-mp.js (já inclui YouTube via GA4)"
521
+ "server": "modules/dispatch/ga4.ts (já inclui YouTube via GA4)"
407
522
  },
408
523
  "eventos_implementados": [
409
524
  "video_start",
410
- "video_progress_25", "video_progress_50", "video_progress_75", "video_progress_90",
525
+ "video_25", "video_50", "video_75",
411
526
  "video_complete",
412
527
  "generate_lead",
413
528
  "purchase"