cdp-edge 1.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.
Files changed (128) hide show
  1. package/README.md +367 -0
  2. package/bin/cdp-edge.js +61 -0
  3. package/contracts/api-versions.json +368 -0
  4. package/dist/commands/analyze.js +52 -0
  5. package/dist/commands/infra.js +54 -0
  6. package/dist/commands/install.js +168 -0
  7. package/dist/commands/server.js +174 -0
  8. package/dist/commands/setup.js +123 -0
  9. package/dist/commands/validate.js +84 -0
  10. package/dist/index.js +12 -0
  11. package/docs/CI-CD-SETUP.md +217 -0
  12. package/docs/PixelBuilder-Documentacao-Completa (2).docx +0 -0
  13. package/docs/events-reference.md +359 -0
  14. package/docs/installation.md +155 -0
  15. package/docs/quick-start.md +185 -0
  16. package/docs/sdk-reference.md +371 -0
  17. package/docs/whatsapp-ctwa.md +209 -0
  18. package/extracted-skill/tracking-events-generator/INDEX.md +94 -0
  19. package/extracted-skill/tracking-events-generator/INSTALACAO-CDPEDGE.md +58 -0
  20. package/extracted-skill/tracking-events-generator/INTEGRACAO-COMPLETA.md +594 -0
  21. package/extracted-skill/tracking-events-generator/MELHORIAS-IMPLEMENTADAS.md +412 -0
  22. package/extracted-skill/tracking-events-generator/Premium-Tracking-Intelligence-Resumo.md +333 -0
  23. package/extracted-skill/tracking-events-generator/SKILL.md +257 -0
  24. package/extracted-skill/tracking-events-generator/advanced-matching.js +364 -0
  25. package/extracted-skill/tracking-events-generator/agents/ab-testing-agent.md +54 -0
  26. package/extracted-skill/tracking-events-generator/agents/attribution-agent.md +1304 -0
  27. package/extracted-skill/tracking-events-generator/agents/bing-agent.md +76 -0
  28. package/extracted-skill/tracking-events-generator/agents/browser-tracking.md +264 -0
  29. package/extracted-skill/tracking-events-generator/agents/code-guardian-agent.md +149 -0
  30. package/extracted-skill/tracking-events-generator/agents/compliance-agent.md +2077 -0
  31. package/extracted-skill/tracking-events-generator/agents/crm-integration-agent.md +1419 -0
  32. package/extracted-skill/tracking-events-generator/agents/dashboard-agent.md +456 -0
  33. package/extracted-skill/tracking-events-generator/agents/database-agent.md +667 -0
  34. package/extracted-skill/tracking-events-generator/agents/debug-agent.md +1455 -0
  35. package/extracted-skill/tracking-events-generator/agents/domain-setup-agent.md +224 -0
  36. package/extracted-skill/tracking-events-generator/agents/email-agent.md +61 -0
  37. package/extracted-skill/tracking-events-generator/agents/fingerprint-agent.md +52 -0
  38. package/extracted-skill/tracking-events-generator/agents/google-agent.md +109 -0
  39. package/extracted-skill/tracking-events-generator/agents/intelligence-agent.md +365 -0
  40. package/extracted-skill/tracking-events-generator/agents/intelligence-scheduling.md +643 -0
  41. package/extracted-skill/tracking-events-generator/agents/linkedin-agent.md +62 -0
  42. package/extracted-skill/tracking-events-generator/agents/localization-agent.md +55 -0
  43. package/extracted-skill/tracking-events-generator/agents/ltv-predictor-agent.md +59 -0
  44. package/extracted-skill/tracking-events-generator/agents/master-feedback-loop.md +900 -0
  45. package/extracted-skill/tracking-events-generator/agents/master-orchestrator.md +1922 -0
  46. package/extracted-skill/tracking-events-generator/agents/memory-agent.json +109 -0
  47. package/extracted-skill/tracking-events-generator/agents/memory-agent.md +703 -0
  48. package/extracted-skill/tracking-events-generator/agents/meta-agent.md +110 -0
  49. package/extracted-skill/tracking-events-generator/agents/page-analyzer.md +255 -0
  50. package/extracted-skill/tracking-events-generator/agents/performance-agent.md +1157 -0
  51. package/extracted-skill/tracking-events-generator/agents/performance-optimization-agent.md +1432 -0
  52. package/extracted-skill/tracking-events-generator/agents/pinterest-agent.md +310 -0
  53. package/extracted-skill/tracking-events-generator/agents/premium-tracking-intelligence-agent.md +849 -0
  54. package/extracted-skill/tracking-events-generator/agents/r2-setup-agent.md +250 -0
  55. package/extracted-skill/tracking-events-generator/agents/reddit-agent.md +313 -0
  56. package/extracted-skill/tracking-events-generator/agents/security-enterprise-agent.md +1752 -0
  57. package/extracted-skill/tracking-events-generator/agents/server-tracking.md +1188 -0
  58. package/extracted-skill/tracking-events-generator/agents/spotify-agent.md +383 -0
  59. package/extracted-skill/tracking-events-generator/agents/tiktok-agent.md +111 -0
  60. package/extracted-skill/tracking-events-generator/agents/tracking-plan-agent.md +364 -0
  61. package/extracted-skill/tracking-events-generator/agents/validator-agent.md +267 -0
  62. package/extracted-skill/tracking-events-generator/agents/webhook-agent.md +69 -0
  63. package/extracted-skill/tracking-events-generator/agents/whatsapp-agent.md +76 -0
  64. package/extracted-skill/tracking-events-generator/agents/whatsapp-ctwa-setup-agent.md +699 -0
  65. package/extracted-skill/tracking-events-generator/agents/youtube-agent.md +422 -0
  66. package/extracted-skill/tracking-events-generator/anti-blocking.js +285 -0
  67. package/extracted-skill/tracking-events-generator/cdpTrack.js +641 -0
  68. package/extracted-skill/tracking-events-generator/contracts/api-versions.json +368 -0
  69. package/extracted-skill/tracking-events-generator/docs/guia-cloudflare-iniciante.md +107 -0
  70. package/extracted-skill/tracking-events-generator/engagement-scoring.js +226 -0
  71. package/extracted-skill/tracking-events-generator/evals/evals.json +235 -0
  72. package/extracted-skill/tracking-events-generator/integration-test.js +497 -0
  73. package/extracted-skill/tracking-events-generator/knowledge-base.md +2894 -0
  74. package/extracted-skill/tracking-events-generator/micro-events.js +992 -0
  75. package/extracted-skill/tracking-events-generator/models/captura-de-lead.md +78 -0
  76. package/extracted-skill/tracking-events-generator/models/captura-lead-evento-externo.md +99 -0
  77. package/extracted-skill/tracking-events-generator/models/checkout-proprio.md +111 -0
  78. package/extracted-skill/tracking-events-generator/models/multi-step-checkout.md +672 -0
  79. package/extracted-skill/tracking-events-generator/models/pagina-obrigado.md +55 -0
  80. package/extracted-skill/tracking-events-generator/models/pinterest/conversions-api-template.js +144 -0
  81. package/extracted-skill/tracking-events-generator/models/pinterest/event-mappings.json +48 -0
  82. package/extracted-skill/tracking-events-generator/models/pinterest/tag-template.js +28 -0
  83. package/extracted-skill/tracking-events-generator/models/quiz-funnel.md +68 -0
  84. package/extracted-skill/tracking-events-generator/models/reddit/conversions-api-template.js +205 -0
  85. package/extracted-skill/tracking-events-generator/models/reddit/event-mappings.json +56 -0
  86. package/extracted-skill/tracking-events-generator/models/reddit/pixel-template.js +19 -0
  87. package/extracted-skill/tracking-events-generator/models/scenarios/behavior-engine.js +425 -0
  88. package/extracted-skill/tracking-events-generator/models/scenarios/real-estate-logic.md +50 -0
  89. package/extracted-skill/tracking-events-generator/models/scenarios/sales-page-logic.md +50 -0
  90. package/extracted-skill/tracking-events-generator/models/trafego-direto.md +582 -0
  91. package/extracted-skill/tracking-events-generator/models/webinar-registration.md +63 -0
  92. package/extracted-skill/tracking-events-generator/tracking.config.js +46 -0
  93. package/extracted-skill/tracking-events-generator/walkthrough.md +26 -0
  94. package/package.json +75 -0
  95. package/server-edge-tracker/INSTALAR.md +328 -0
  96. package/server-edge-tracker/migrate-new-db.sql +137 -0
  97. package/server-edge-tracker/migrate-v2.sql +16 -0
  98. package/server-edge-tracker/migrate-v3.sql +6 -0
  99. package/server-edge-tracker/migrate-v4.sql +18 -0
  100. package/server-edge-tracker/migrate-v5.sql +17 -0
  101. package/server-edge-tracker/migrate-v6.sql +24 -0
  102. package/server-edge-tracker/migrate.sql +111 -0
  103. package/server-edge-tracker/schema.sql +265 -0
  104. package/server-edge-tracker/worker.js +2574 -0
  105. package/server-edge-tracker/wrangler.toml +85 -0
  106. package/templates/afiliado-sem-landing.md +312 -0
  107. package/templates/captura-de-lead.md +78 -0
  108. package/templates/captura-lead-evento-externo.md +99 -0
  109. package/templates/checkout-proprio.md +111 -0
  110. package/templates/install/.claude/commands/cdp.md +1 -0
  111. package/templates/install/CLAUDE.md +65 -0
  112. package/templates/linkedin/tag-template.js +46 -0
  113. package/templates/multi-step-checkout.md +673 -0
  114. package/templates/pagina-obrigado.md +55 -0
  115. package/templates/pinterest/conversions-api-template.js +144 -0
  116. package/templates/pinterest/event-mappings.json +48 -0
  117. package/templates/pinterest/tag-template.js +28 -0
  118. package/templates/quiz-funnel.md +68 -0
  119. package/templates/reddit/conversions-api-template.js +205 -0
  120. package/templates/reddit/event-mappings.json +56 -0
  121. package/templates/reddit/pixel-template.js +46 -0
  122. package/templates/scenarios/behavior-engine.js +402 -0
  123. package/templates/scenarios/real-estate-logic.md +50 -0
  124. package/templates/scenarios/sales-page-logic.md +50 -0
  125. package/templates/spotify/pixel-template.js +46 -0
  126. package/templates/trafego-direto.md +582 -0
  127. package/templates/vsl-page.md +292 -0
  128. package/templates/webinar-registration.md +63 -0
@@ -0,0 +1,673 @@
1
+ # Modelo: Multi-Step Checkout
2
+
3
+ > ⚠️ **STATUS: Browser-Only — Migração para Quantum Tier pendente (PRIORIDADE ALTA)**
4
+ >
5
+ > Este modelo ainda usa captura apenas via browser (sem Worker server-side).
6
+ > Checkout multi-etapa é um dos funis mais comuns em infoprodutos (Ticto, Kiwify, Hotmart têm checkouts multi-step próprios).
7
+ > Até a migração ser concluída, use `checkout-proprio.md` como referência de arquitetura Quantum Tier e adapte as etapas manualmente.
8
+
9
+ Checkout próprio dividido em múltiplas etapas: dados pessoais → endereço → pagamento → confirmação.
10
+
11
+ **Quando usar:** checkout integrado na página com múltiplas telas/abas (cartão de crédito, boleto, PIX), sem redirecionamento para plataforma externa.
12
+
13
+ ---
14
+
15
+ ## 🏗️ ARQUITETURA TÉCNICA (Quantum Tier)
16
+
17
+ O rastreamento segue a lógica de progressão de checkout com enriquecimento de identidade:
18
+ 1. **Site**: Captura progressivamente dados de identidade ao preencher campos.
19
+ 2. **Worker**: Recebe cada etapa, enriquece Identity Graph e despacha para APIs.
20
+ 3. **D1 Database**: Mantém estado do checkout vinculado ao `cdp_uid`.
21
+
22
+ ---
23
+
24
+ ## Estrutura típica
25
+
26
+ ```
27
+ Step 1: Dados pessoais (nome, email, CPF)
28
+ Step 2: Dados de entrega (endereço) — opcional em infoprodutos
29
+ Step 3: Pagamento (cartão/PIX/boleto)
30
+ Step 4: Confirmação / Obrigado
31
+ ```
32
+
33
+ ---
34
+
35
+ ## 📘 EVENTOS PRINCIPAIS
36
+
37
+ | Evento | Trigger | Meta | GA4 | TikTok | Prioridade |
38
+ |--------|---------|------|-----|--------|-----------|
39
+ | `InitiateCheckout` | Chegada no step 1 | `InitiateCheckout` | `begin_checkout` | `InitiateCheckout` | 🔴 Crítico |
40
+ | `AddPaymentInfo` | Preenchimento dos dados de pagamento (step 3) | `AddPaymentInfo` | `add_payment_info` | `AddPaymentInfo` | 🟡 Importante |
41
+ | `Purchase` | Confirmação de pagamento (step 4) | `Purchase` (CAPI) | `purchase` (MP) | `CompletePayment` | 🔴 Crítico |
42
+ | `CheckoutAbandonment` | Saída sem completar (visibilitychange) | `CustomEvent` | `checkout_abandon` | — | 🟢 Recomendado |
43
+
44
+ ---
45
+
46
+ ## 🛠️ PASSO 1: CONFIGURAÇÃO DO SITE
47
+
48
+ ### 1.1 SDK de Rastreamento (Header)
49
+ ```html
50
+ <!-- Inserir no <head> -->
51
+ <script src="/js/cdpTrack.js" async></script>
52
+ <script>
53
+ window.cdpConfig = {
54
+ workerUrl: '/api/tracking', // Same-Domain (furtivo)
55
+ metaId: 'SEU_PIXEL_ID',
56
+ ga4Id: 'G-XXXXXXXX',
57
+ tiktokId: 'C4XXXXXXXXXXXXXXX',
58
+ checkout: {
59
+ value: 197.00, // ⚠️ substituir pelo valor real
60
+ currency: 'BRL',
61
+ productId: 'PROD_001', // ⚠️ substituir pelo ID do produto
62
+ productName: 'Produto Premium' // ⚠️ substituir pelo nome do produto
63
+ }
64
+ };
65
+ </script>
66
+ ```
67
+
68
+ ### 1.2 Geração de cdp_uid (First Access)
69
+ ```javascript
70
+ // Inserir no início do <body> (primeiro script)
71
+ <script>
72
+ (function() {
73
+ // Gera cdp_uid se não existir (1 ano de expiração)
74
+ const existing = document.cookie.match(/cdp_uid=([^;]+)/);
75
+ if (!existing) {
76
+ const uid = 'usr_' + Math.random().toString(36).substring(2, 10) + Date.now();
77
+ const expiry = new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toUTCString();
78
+ document.cookie = `cdp_uid=${encodeURIComponent(uid)}; expires=${expiry}; path=/; SameSite=Lax`;
79
+ }
80
+ })();
81
+ </script>
82
+ ```
83
+
84
+ ### 1.3 STEP 1: InitiateCheckout (Chegada na página)
85
+ ```javascript
86
+ // Ao carregar a página de checkout
87
+ <script>
88
+ window.addEventListener('DOMContentLoaded', async () => {
89
+ const cdp_uid = document.cookie.match(/cdp_uid=([^;]+)/)?.[1] || '';
90
+
91
+ await cdpTrack.track('InitiateCheckout', {
92
+ cdp_uid,
93
+ step: 1,
94
+ value: window.cdpConfig.checkout.value,
95
+ currency: window.cdpConfig.checkout.currency,
96
+ content_name: window.cdpConfig.checkout.productName,
97
+ content_id: window.cdpConfig.checkout.productId
98
+ });
99
+ });
100
+ </script>
101
+ ```
102
+
103
+ ### 1.4 STEP 2: Captura Progressiva de Identidade
104
+ ```javascript
105
+ // Captura email ao preencher (enrichment para Advanced Matching)
106
+ document.querySelector('[name="email"], [type="email"]')?.addEventListener('blur', async function() {
107
+ const email = this.value.trim();
108
+
109
+ // Envia identidade atualizada para o Worker
110
+ await cdpTrack.track('IdentityUpdate', {
111
+ email
112
+ });
113
+ });
114
+
115
+ // Captura telefone ao preencher
116
+ document.querySelector('[name="phone"], [name="telefone"], [type="tel"]')?.addEventListener('blur', async function() {
117
+ const phone = this.value.trim();
118
+
119
+ await cdpTrack.track('IdentityUpdate', {
120
+ phone
121
+ });
122
+ });
123
+
124
+ // Captura nome ao preencher
125
+ document.querySelector('[name="name"], [name="nome"]')?.addEventListener('blur', async function() {
126
+ const full = this.value.trim();
127
+ const parts = full.split(/\s+/);
128
+
129
+ await cdpTrack.track('IdentityUpdate', {
130
+ first_name: parts[0],
131
+ last_name: parts.slice(1).join(' ')
132
+ });
133
+ });
134
+
135
+ // Captura CPF (opcional)
136
+ document.querySelector('[name="cpf"], [name="documento"]')?.addEventListener('blur', async function() {
137
+ const cpf = this.value.replace(/\D/g, '');
138
+
139
+ await cdpTrack.track('IdentityUpdate', {
140
+ cpf
141
+ });
142
+ });
143
+ ```
144
+
145
+ ### 1.5 STEP 3: AddPaymentInfo (Chegada na tela de pagamento)
146
+ ```javascript
147
+ // Adaptar trigger conforme estrutura do checkout (clique em aba, next button, etc.)
148
+ document.querySelector('#btn-pagamento, [data-step="pagamento"]')?.addEventListener('click', async function() {
149
+ const cdp_uid = document.cookie.match(/cdp_uid=([^;]+)/)?.[1] || '';
150
+
151
+ // Capturar método de pagamento selecionado
152
+ const paymentMethod = document.querySelector('[name="payment-method"]:checked')?.value ||
153
+ document.querySelector('.payment-tab.active')?.dataset?.method ||
154
+ 'unknown';
155
+
156
+ await cdpTrack.track('AddPaymentInfo', {
157
+ cdp_uid,
158
+ step: 3,
159
+ payment_method: paymentMethod
160
+ });
161
+ });
162
+ ```
163
+
164
+ ### 1.6 STEP 4: Purchase (Confirmação de pagamento)
165
+ ```javascript
166
+ // Disparar na página de obrigado OU ao receber callback de sucesso da API de pagamento
167
+ <script>
168
+ async function trackPurchaseConfirmed(transactionId) {
169
+ const cdp_uid = document.cookie.match(/cdp_uid=([^;]+)/)?.[1] || '';
170
+
171
+ await cdpTrack.track('Purchase', {
172
+ cdp_uid,
173
+ transaction_id: transactionId,
174
+ step: 4,
175
+ value: window.cdpConfig.checkout.value,
176
+ currency: window.cdpConfig.checkout.currency,
177
+ content_id: window.cdpConfig.checkout.productId,
178
+ content_name: window.cdpConfig.checkout.productName
179
+ });
180
+ }
181
+
182
+ // Exemplo: callback do gateway de pagamento
183
+ // paymentGateway.onSuccess((transactionId) => {
184
+ // trackPurchaseConfirmed(transactionId);
185
+ // });
186
+ </script>
187
+ ```
188
+
189
+ ### 1.7 Checkout Abandonment (Opcional)
190
+ ```javascript
191
+ // Detecta quando usuário sai sem completar o checkout
192
+ <script>
193
+ let checkoutState = { step: 0 };
194
+
195
+ // Atualiza step conforme usuário avança
196
+ document.querySelectorAll('[data-step]').forEach(el => {
197
+ el.addEventListener('click', () => {
198
+ checkoutState.step = parseInt(el.dataset.step);
199
+ });
200
+ });
201
+
202
+ document.addEventListener('visibilitychange', async () => {
203
+ if (document.visibilityState === 'hidden' && checkoutState.step > 0 && checkoutState.step < 4) {
204
+ // Usuário saiu sem completar
205
+ const cdp_uid = document.cookie.match(/cdp_uid=([^;]+)/)?.[1] || '';
206
+
207
+ // Usa navigator.sendBeacon para garantir envio mesmo se browser encerrar
208
+ navigator.sendBeacon('/api/tracking', JSON.stringify({
209
+ event_name: 'CheckoutAbandonment',
210
+ cdp_uid,
211
+ step: checkoutState.step,
212
+ value: window.cdpConfig.checkout.value
213
+ }));
214
+ }
215
+ });
216
+ </script>
217
+ ```
218
+
219
+ ---
220
+
221
+ ## ⚡ PASSO 2: SERVIDOR (CLOUDFLARE WORKER)
222
+
223
+ ### 2.1 Handler Principal
224
+ ```javascript
225
+ // worker.js
226
+
227
+ export default {
228
+ async fetch(request, env, ctx) {
229
+ const url = new URL(request.url);
230
+ const cors = {
231
+ 'Access-Control-Allow-Origin': '*',
232
+ 'Access-Control-Allow-Methods': 'POST, OPTIONS',
233
+ 'Access-Control-Allow-Headers': 'Content-Type',
234
+ };
235
+
236
+ if (request.method === 'OPTIONS') {
237
+ return new Response(null, { headers: cors });
238
+ }
239
+
240
+ if (url.pathname === '/api/tracking') {
241
+ return handleTracking(request, env, ctx);
242
+ }
243
+
244
+ return new Response('Not Found', { status: 404 });
245
+ }
246
+ };
247
+
248
+ async function handleTracking(request, env, ctx) {
249
+ const body = await request.json();
250
+ const cf = request.cf || {};
251
+ const ip = cf.colo === 'XX' ? '8.8.8.8' : request.headers.get('CF-Connecting-IP');
252
+
253
+ // Captura cookies do request
254
+ const fbp = request.headers.get('Cookie')?.match(/_fbp=([^;]+)/)?.[1];
255
+ const fbc = request.headers.get('Cookie')?.match(/_fbc=([^;]+)/)?.[1];
256
+ const ttp = request.headers.get('Cookie')?.match(/_ttp=([^;]+)/)?.[1];
257
+
258
+ const sessionData = {
259
+ cdp_uid: body.cdp_uid,
260
+ fbp,
261
+ fbc,
262
+ ttp,
263
+ ip,
264
+ user_agent: request.headers.get('User-Agent'),
265
+ };
266
+
267
+ // Atualiza Identity Graph no D1
268
+ await updateIdentity(env.DB, sessionData, body);
269
+
270
+ // Dispatch não-bloqueante para APIs
271
+ ctx.waitUntil(dispatchEvents(body, sessionData, env));
272
+
273
+ return new Response(JSON.stringify({ success: true }), {
274
+ headers: { ...cors, 'Content-Type': 'application/json' }
275
+ });
276
+ }
277
+ ```
278
+
279
+ ### 2.2 Atualização de Identity Graph (Enriquecimento Progressivo)
280
+ ```javascript
281
+ async function updateIdentity(DB, sessionData, eventData) {
282
+ const { event_name } = eventData;
283
+
284
+ if (event_name === 'IdentityUpdate') {
285
+ // Enrichment progressivo: atualiza campos conforme usuário preenche
286
+ const updates = {};
287
+ if (eventData.email) updates.email_hash = await sha256(eventData.email);
288
+ if (eventData.phone) updates.phone_hash = await sha256('55' + eventData.phone.replace(/\D/g, ''));
289
+ if (eventData.first_name) updates.first_name_hash = await sha256(eventData.first_name);
290
+ if (eventData.last_name) updates.last_name_hash = await sha256(eventData.last_name);
291
+ if (eventData.cpf) updates.cpf_hash = await sha256(eventData.cpf);
292
+
293
+ await DB.prepare(`
294
+ INSERT INTO identity_graph (cdp_uid, fbp, fbc, ttp, ip, user_agent,
295
+ email_hash, phone_hash, first_name_hash, last_name_hash, cpf_hash, last_seen)
296
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
297
+ ON CONFLICT(cdp_uid) DO UPDATE SET
298
+ fbp = excluded.fbp,
299
+ fbc = excluded.fbc,
300
+ ttp = excluded.ttp,
301
+ ip = excluded.ip,
302
+ email_hash = COALESCE(excluded.email_hash, updates.email_hash),
303
+ phone_hash = COALESCE(excluded.phone_hash, updates.phone_hash),
304
+ first_name_hash = COALESCE(excluded.first_name_hash, updates.first_name_hash),
305
+ last_name_hash = COALESCE(excluded.last_name_hash, updates.last_name_hash),
306
+ cpf_hash = COALESCE(excluded.cpf_hash, updates.cpf_hash),
307
+ last_seen = datetime('now')
308
+ `).bind(
309
+ sessionData.cdp_uid, sessionData.fbp, sessionData.fbc, sessionData.ttp, sessionData.ip, sessionData.user_agent,
310
+ updates.email_hash || null, updates.phone_hash || null,
311
+ updates.first_name_hash || null, updates.last_name_hash || null, updates.cpf_hash || null
312
+ ).run();
313
+ }
314
+ }
315
+ ```
316
+
317
+ ### 2.3 Dispatch de Eventos
318
+ ```javascript
319
+ async function dispatchEvents(eventBody, sessionData, env) {
320
+ const { event_name } = eventBody;
321
+
322
+ if (event_name === 'InitiateCheckout') {
323
+ await Promise.all([
324
+ dispatchMeta('InitiateCheckout', sessionData, env, {
325
+ content_name: eventBody.content_name,
326
+ content_ids: [eventBody.content_id],
327
+ num_items: 1
328
+ }),
329
+ dispatchGA4('begin_checkout', sessionData, env, {
330
+ items: [{
331
+ item_id: eventBody.content_id,
332
+ item_name: eventBody.content_name,
333
+ price: eventBody.value,
334
+ quantity: 1
335
+ }]
336
+ }),
337
+ dispatchTikTok('InitiateCheckout', sessionData, env, {
338
+ content_id: eventBody.content_id
339
+ }),
340
+ ]);
341
+ } else if (event_name === 'AddPaymentInfo') {
342
+ await Promise.all([
343
+ dispatchMeta('AddPaymentInfo', sessionData, env, {
344
+ value: eventBody.value || window.cdpConfig?.checkout?.value,
345
+ currency: eventBody.currency || 'BRL',
346
+ content_ids: [eventBody.content_id || window.cdpConfig?.checkout?.productId]
347
+ }),
348
+ dispatchGA4('add_payment_info', sessionData, env, {
349
+ payment_type: eventBody.payment_method
350
+ }),
351
+ dispatchTikTok('AddPaymentInfo', sessionData, env, {}),
352
+ ]);
353
+ } else if (event_name === 'Purchase') {
354
+ await Promise.all([
355
+ dispatchMeta('Purchase', sessionData, env, {
356
+ content_ids: [eventBody.content_id],
357
+ num_items: 1
358
+ }),
359
+ dispatchGA4('purchase', sessionData, env, {
360
+ transaction_id: eventBody.transaction_id,
361
+ items: [{
362
+ item_id: eventBody.content_id,
363
+ item_name: eventBody.content_name,
364
+ price: eventBody.value,
365
+ quantity: 1
366
+ }]
367
+ }),
368
+ dispatchTikTok('CompletePayment', sessionData, env, {}),
369
+ ]);
370
+ } else if (event_name === 'CheckoutAbandonment') {
371
+ // Apenas log no D1, não dispara para APIs
372
+ await logAbandonment(env.DB, eventBody, sessionData);
373
+ }
374
+ }
375
+ ```
376
+
377
+ ### 2.4 Meta CAPI v22.0
378
+ ```javascript
379
+ async function dispatchMeta(eventName, sessionData, env, customData = {}) {
380
+ if (!env.META_ACCESS_TOKEN || !env.META_PIXEL_ID) return;
381
+
382
+ const identity = await getIdentity(env.DB, sessionData.cdp_uid);
383
+
384
+ const payload = {
385
+ data: [{
386
+ event_name: eventName,
387
+ event_time: Math.floor(Date.now() / 1000),
388
+ event_id: crypto.randomUUID(),
389
+ event_source_url: sessionData.page_url || '',
390
+ action_source: 'website',
391
+ user_data: {
392
+ em: identity.email_hash ? [identity.email_hash] : undefined,
393
+ ph: identity.phone_hash ? [identity.phone_hash] : undefined,
394
+ fn: identity.first_name_hash ? [identity.first_name_hash] : undefined,
395
+ ln: identity.last_name_hash ? [identity.last_name_hash] : undefined,
396
+ fbp: sessionData.fbp,
397
+ fbc: sessionData.fbc,
398
+ client_ip_address: sessionData.ip,
399
+ client_user_agent: sessionData.user_agent,
400
+ external_id: await sha256(sessionData.cdp_uid),
401
+ },
402
+ custom_data: {
403
+ value: customData.value || 0,
404
+ currency: customData.currency || 'BRL',
405
+ ...customData
406
+ }
407
+ }]
408
+ };
409
+
410
+ const res = await fetch(
411
+ `https://graph.facebook.com/v22.0/${env.META_PIXEL_ID}/events?access_token=${env.META_ACCESS_TOKEN}`,
412
+ {
413
+ method: 'POST',
414
+ headers: { 'Content-Type': 'application/json' },
415
+ body: JSON.stringify(payload)
416
+ }
417
+ );
418
+
419
+ if (!res.ok) {
420
+ console.error('Meta CAPI Error:', await res.text());
421
+ }
422
+ }
423
+ ```
424
+
425
+ ### 2.5 GA4 Measurement Protocol
426
+ ```javascript
427
+ async function dispatchGA4(eventName, sessionData, env, eventData = {}) {
428
+ if (!env.GA4_ID || !env.GA4_API_SECRET) return;
429
+
430
+ const payload = {
431
+ client_id: sessionData.cdp_uid,
432
+ user_id: sessionData.cdp_uid,
433
+ events: [{
434
+ name: eventName,
435
+ params: {
436
+ page_location: sessionData.page_url || '',
437
+ ...eventData
438
+ }
439
+ }]
440
+ };
441
+
442
+ const res = await fetch(
443
+ `https://www.google-analytics.com/mp/collect?measurement_id=${env.GA4_ID}&api_secret=${env.GA4_API_SECRET}`,
444
+ {
445
+ method: 'POST',
446
+ headers: { 'Content-Type': 'application/json' },
447
+ body: JSON.stringify(payload)
448
+ }
449
+ );
450
+
451
+ if (!res.ok) {
452
+ console.error('GA4 Error:', await res.text());
453
+ }
454
+ }
455
+ ```
456
+
457
+ ### 2.6 TikTok Events API v1.3
458
+ ```javascript
459
+ async function dispatchTikTok(eventName, sessionData, env, eventData = {}) {
460
+ if (!env.TIKTOK_PIXEL_ID || !env.TIKTOK_ACCESS_TOKEN) return;
461
+
462
+ const payload = {
463
+ pixel_code: env.TIKTOK_PIXEL_ID,
464
+ event: eventName,
465
+ event_id: crypto.randomUUID(),
466
+ timestamp: new Date().toISOString(),
467
+ context: {
468
+ ad: {
469
+ callback: sessionData.ttp
470
+ },
471
+ page: {
472
+ url: sessionData.page_url || ''
473
+ },
474
+ user: {
475
+ ip_address: sessionData.ip,
476
+ user_agent: sessionData.user_agent,
477
+ external_id: await sha256(sessionData.cdp_uid)
478
+ }
479
+ },
480
+ properties: {
481
+ value: eventData.value || 0,
482
+ currency: eventData.currency || 'BRL',
483
+ ...eventData
484
+ }
485
+ };
486
+
487
+ const res = await fetch(
488
+ 'https://business-api.tiktok.com/open_api/v1.3/event/track/',
489
+ {
490
+ method: 'POST',
491
+ headers: {
492
+ 'Content-Type': 'application/json',
493
+ 'Access-Token': env.TIKTOK_ACCESS_TOKEN
494
+ },
495
+ body: JSON.stringify(payload)
496
+ }
497
+ );
498
+
499
+ if (!res.ok) {
500
+ console.error('TikTok Error:', await res.text());
501
+ }
502
+ }
503
+ ```
504
+
505
+ ### 2.7 Helpers
506
+ ```javascript
507
+ async function sha256(value) {
508
+ if (!value) return null;
509
+ const encoder = new TextEncoder();
510
+ const data = encoder.encode(value);
511
+ const hash = await crypto.subtle.digest('SHA-256', data);
512
+ return Array.from(new Uint8Array(hash)).map(b => b.toString(16).padStart(2, '0')).join('');
513
+ }
514
+
515
+ async function getIdentity(DB, cdp_uid) {
516
+ return await DB.prepare(
517
+ 'SELECT * FROM identity_graph WHERE cdp_uid = ?'
518
+ ).bind(cdp_uid).first();
519
+ }
520
+
521
+ async function logAbandonment(DB, eventData, sessionData) {
522
+ await DB.prepare(`
523
+ INSERT INTO events_log (event_id, event_name, session_id, heat_score, page_url, created_at)
524
+ VALUES (?, ?, ?, ?, ?, datetime('now'))
525
+ `).bind(
526
+ crypto.randomUUID(), 'CheckoutAbandonment', sessionData.cdp_uid,
527
+ eventData.step || 1, sessionData.page_url || ''
528
+ ).run();
529
+ }
530
+ ```
531
+
532
+ ---
533
+
534
+ ## 📊 PASSO 3: SCHEMA D1
535
+
536
+ ```sql
537
+ -- Identity Graph (já definido no Server Agent)
538
+ CREATE TABLE IF NOT EXISTS identity_graph (
539
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
540
+ cdp_uid TEXT UNIQUE NOT NULL,
541
+ fbp TEXT,
542
+ fbc TEXT,
543
+ ttp TEXT,
544
+ ga_client_id TEXT,
545
+ external_id TEXT,
546
+ email_hash TEXT,
547
+ phone_hash TEXT,
548
+ first_name_hash TEXT,
549
+ last_name_hash TEXT,
550
+ cpf_hash TEXT,
551
+ first_utm TEXT,
552
+ heat_score_avg INTEGER DEFAULT 0,
553
+ visit_count INTEGER DEFAULT 1,
554
+ last_seen TEXT DEFAULT (datetime('now')),
555
+ created_at TEXT DEFAULT (datetime('now'))
556
+ );
557
+
558
+ -- Events Log (para Checkout Abandonment)
559
+ CREATE TABLE IF NOT EXISTS events_log (
560
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
561
+ event_id TEXT UNIQUE NOT NULL,
562
+ event_name TEXT NOT NULL,
563
+ platform TEXT,
564
+ session_id TEXT,
565
+ heat_score INTEGER DEFAULT 0,
566
+ page_url TEXT,
567
+ utm_source TEXT,
568
+ utm_campaign TEXT,
569
+ utm_medium TEXT,
570
+ status TEXT DEFAULT 'pending',
571
+ error_msg TEXT,
572
+ created_at TEXT DEFAULT (datetime('now'))
573
+ );
574
+
575
+ CREATE INDEX IF NOT EXISTS idx_cdp_uid ON identity_graph(cdp_uid);
576
+ CREATE INDEX IF NOT EXISTS idx_events_id ON events_log(event_id);
577
+ CREATE INDEX IF NOT EXISTS idx_events_created ON events_log(created_at);
578
+ ```
579
+
580
+ ---
581
+
582
+ ## ✅ CHECKLIST DE VERIFICAÇÃO
583
+
584
+ ### Browser
585
+ - [ ] cdp_uid gerado no primeiro acesso e persistido por 1 ano
586
+ - [ ] InitiateCheckout disparado na chegada ao step 1
587
+ - [ ] IdentityUpdate disparado ao preencher cada campo (email, telefone, nome, CPF)
588
+ - [ ] AddPaymentInfo disparado na tela de pagamento (step 3)
589
+ - [ ] Purchase disparado na confirmação (step 4)
590
+ - [ ] CheckoutAbandonment usa `navigator.sendBeacon` para garantir envio
591
+
592
+ ### Cloudflare Worker
593
+ - [ ] Endpoint `/api/tracking` configurado como Route no Cloudflare
594
+ - [ ] Identity Graph atualizado progressivamente conforme usuário preenche campos
595
+ - [ ] Meta CAPI v22.0 endpoint correto
596
+ - [ ] TikTok Events API v1.3 endpoint correto
597
+ - [ ] GA4 Measurement Protocol configurado
598
+ - [ ] CheckoutAbandonment logado apenas no D1 (não dispara para APIs)
599
+
600
+ ### D1 Database
601
+ - [ ] Identity Graph com campos de hash (email, phone, first_name, last_name, cpf)
602
+ - [ ] Events Log para Checkout Abandonment
603
+ - [ ] Índices configurados para performance
604
+
605
+ ---
606
+
607
+ ## 🔄 FLUXO COMPLETO
608
+
609
+ ```
610
+ 1. Visitante acessa o checkout (Step 1)
611
+ └── JS: gera cdp_uid → salva cookie (1 ano)
612
+ └── JS: dispara InitiateCheckout → Worker
613
+ └── Worker: salva Identity Graph básica (fbp, fbc, ttp)
614
+ └── Worker: dispatch → Meta, GA4, TikTok (InitiateCheckout)
615
+
616
+ 2. Visitante preenche dados pessoais (Step 2)
617
+ └── JS: blur no email → IdentityUpdate
618
+ └── Worker: atualiza Identity Graph com email_hash (enrichment)
619
+ └── JS: blur no telefone → IdentityUpdate
620
+ └── Worker: atualiza Identity Graph com phone_hash
621
+ └── JS: blur no nome → IdentityUpdate
622
+ └── Worker: atualiza Identity Graph com first/last_name_hash
623
+
624
+ 3. Visitante vai para pagamento (Step 3)
625
+ └── JS: clique em botão de pagamento → AddPaymentInfo
626
+ └── Worker: dispatch → Meta, GA4, TikTok (AddPaymentInfo)
627
+
628
+ 4. Visitante finaliza compra (Step 4)
629
+ └── Gateway: callback de sucesso → trackPurchaseConfirmed()
630
+ └── JS: dispara Purchase → Worker
631
+ └── Worker: recupera Identity Graph completa (todos os hashes)
632
+ └── Worker: dispatch → Meta Purchase CAPI (v22.0)
633
+ └── Worker: dispatch → GA4 Purchase (MP)
634
+ └── Worker: dispatch → TikTok CompletePayment (v1.3)
635
+
636
+ 5. Visitante abandona checkout (opcional)
637
+ └── JS: visibilitychange + sendBeacon → CheckoutAbandonment
638
+ └── Worker: log apenas no D1 (não dispara para APIs)
639
+ ```
640
+
641
+ ---
642
+
643
+ ## ⚠️ NOTAS CRÍTICAS
644
+
645
+ - **Enrichment Progressivo**: Identity Graph é atualizado conforme usuário preenche campos, melhorando Advanced Matching
646
+ - **Deduplicação**: Cada evento deve ter `event_id` único (usar `crypto.randomUUID()`)
647
+ - **Hashing**: SHA256 deve ser feito no Worker usando `crypto.subtle.digest` (WebCrypto API)
648
+ - **Privacy**: Nunca logar email/telefone/nome/CPF em texto claro no console do Worker
649
+ - **sendBeacon**: Checkout Abandonment deve usar `navigator.sendBeacon` para garantir envio mesmo se browser encerrar
650
+ - **Mesmo-Domain Protocol**: Worker DEVE rodar no mesmo domínio do site para evitar CORS e bloqueios
651
+
652
+ ---
653
+
654
+ ## 🚀 DEPLOY DO ZERO (Resumo)
655
+
656
+ 1. **Criar Worker**: `npx wrangler init cdp-edge-ms`
657
+ 2. **Configurar D1**: `npx wrangler d1 create cdp-edge-ms-db`
658
+ 3. **Aplicar Schema**: `npx wrangler d1 execute cdp-edge-ms-db --file=schema.sql`
659
+ 4. **Configurar Secrets**:
660
+ ```bash
661
+ wrangler secret put META_ACCESS_TOKEN
662
+ wrangler secret put META_PIXEL_ID
663
+ wrangler secret put GA4_ID
664
+ wrangler secret put GA4_API_SECRET
665
+ wrangler secret put TIKTOK_PIXEL_ID
666
+ wrangler secret put TIKTOK_ACCESS_TOKEN
667
+ ```
668
+ 5. **Deploy**: `npx wrangler deploy`
669
+ 6. **Configurar Route**: Cloudflare Dashboard → Workers & Pages → Routes → `seusite.com/api/*` → Worker
670
+
671
+ ---
672
+
673
+ *Este modelo é 100% Cloudflare Native e elimina qualquer dependência de pixels diretos no browser.*