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.
- package/README.md +153 -306
- package/bin/cdp-edge.js +71 -61
- package/contracts/agent-versions.json +682 -0
- package/contracts/api-versions.json +372 -368
- package/contracts/types.ts +81 -0
- package/dist/commands/analyze.js +52 -52
- package/dist/commands/infra.js +54 -54
- package/dist/commands/install.js +26 -3
- package/dist/commands/server.js +174 -174
- package/dist/commands/setup.js +332 -100
- package/dist/commands/validate.js +248 -84
- package/dist/index.js +12 -12
- package/dist/sdk/cdpTrack.js +2095 -0
- package/dist/sdk/cdpTrack.min.js +64 -0
- package/dist/sdk/install-snippet.html +10 -0
- package/docs/whatsapp-ctwa.md +5 -4
- package/extracted-skill/tracking-events-generator/INTEGRACAO-COMPLETA.md +89 -0
- package/extracted-skill/tracking-events-generator/MELHORIAS-IMPLEMENTADAS.md +101 -0
- package/extracted-skill/tracking-events-generator/advanced-matching.js +364 -364
- package/extracted-skill/tracking-events-generator/agents/ab-ltv-agent.md +196 -0
- package/extracted-skill/tracking-events-generator/agents/ab-testing-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/attribution-agent.md +41 -41
- package/extracted-skill/tracking-events-generator/agents/bidding-agent.md +347 -0
- package/extracted-skill/tracking-events-generator/agents/bing-agent.md +40 -50
- package/extracted-skill/tracking-events-generator/agents/browser-tracking.md +174 -74
- package/extracted-skill/tracking-events-generator/agents/code-guardian-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/compliance-agent.md +25 -5
- package/extracted-skill/tracking-events-generator/agents/dashboard-agent.md +10 -10
- package/extracted-skill/tracking-events-generator/agents/database-agent.md +43 -42
- package/extracted-skill/tracking-events-generator/agents/debug-agent.md +22 -22
- package/extracted-skill/tracking-events-generator/agents/devops-agent.md +232 -0
- package/extracted-skill/tracking-events-generator/agents/domain-setup-agent.md +23 -9
- package/extracted-skill/tracking-events-generator/agents/email-agent.md +28 -1
- package/extracted-skill/tracking-events-generator/agents/evo-crm-agent.md +244 -0
- package/extracted-skill/tracking-events-generator/agents/fingerprint-agent.md +206 -1
- package/extracted-skill/tracking-events-generator/agents/fraud-detection-agent.md +143 -0
- package/extracted-skill/tracking-events-generator/agents/google-agent.md +128 -2
- package/extracted-skill/tracking-events-generator/agents/intelligence-agent.md +191 -31
- package/extracted-skill/tracking-events-generator/agents/lead-scoring-agent.md +282 -0
- package/extracted-skill/tracking-events-generator/agents/linkedin-agent.md +145 -34
- package/extracted-skill/tracking-events-generator/agents/localization-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/ltv-predictor-agent.md +5 -5
- package/extracted-skill/tracking-events-generator/agents/master-feedback-loop.md +81 -21
- package/extracted-skill/tracking-events-generator/agents/master-orchestrator.md +313 -93
- package/extracted-skill/tracking-events-generator/agents/match-quality-agent.md +304 -0
- package/extracted-skill/tracking-events-generator/agents/memory-agent.md +190 -15
- package/extracted-skill/tracking-events-generator/agents/meta-agent.md +10 -2
- package/extracted-skill/tracking-events-generator/agents/ml-clustering-agent.md +749 -0
- package/extracted-skill/tracking-events-generator/agents/page-analyzer.md +21 -4
- package/extracted-skill/tracking-events-generator/agents/performance-agent.md +41 -31
- package/extracted-skill/tracking-events-generator/agents/performance-optimization-agent.md +18 -8
- package/extracted-skill/tracking-events-generator/agents/pinterest-agent.md +14 -6
- package/extracted-skill/tracking-events-generator/agents/premium-tracking-intelligence-agent.md +7 -7
- package/extracted-skill/tracking-events-generator/agents/r2-setup-agent.md +16 -8
- package/extracted-skill/tracking-events-generator/agents/reddit-agent.md +15 -7
- package/extracted-skill/tracking-events-generator/agents/security-enterprise-agent.md +157 -48
- package/extracted-skill/tracking-events-generator/agents/server-tracking.md +35 -35
- package/extracted-skill/tracking-events-generator/agents/spotify-agent.md +15 -7
- package/extracted-skill/tracking-events-generator/agents/tiktok-agent.md +73 -2
- package/extracted-skill/tracking-events-generator/agents/tracking-plan-agent.md +104 -9
- package/extracted-skill/tracking-events-generator/agents/utm-agent.md +322 -0
- package/extracted-skill/tracking-events-generator/agents/validator-agent.md +13 -9
- package/extracted-skill/tracking-events-generator/agents/webhook-agent.md +112 -4
- package/extracted-skill/tracking-events-generator/agents/whatsapp-agent.md +58 -5
- package/extracted-skill/tracking-events-generator/agents/whatsapp-ctwa-setup-agent.md +26 -18
- package/extracted-skill/tracking-events-generator/agents/youtube-agent.md +152 -37
- package/extracted-skill/tracking-events-generator/anti-blocking.js +285 -285
- package/extracted-skill/tracking-events-generator/cdpTrack.js +642 -641
- package/extracted-skill/tracking-events-generator/contracts/api-versions.json +14 -10
- package/extracted-skill/tracking-events-generator/engagement-scoring.js +226 -226
- package/extracted-skill/tracking-events-generator/evals/evals.json +235 -235
- package/extracted-skill/tracking-events-generator/integration-test.js +497 -497
- package/extracted-skill/tracking-events-generator/knowledge-base.md +172 -0
- package/extracted-skill/tracking-events-generator/micro-events.js +992 -992
- package/extracted-skill/tracking-events-generator/models/lancamento-imobiliario.md +344 -0
- package/extracted-skill/tracking-events-generator/models/pinterest/conversions-api-template.js +144 -144
- package/extracted-skill/tracking-events-generator/models/pinterest/event-mappings.json +48 -48
- package/extracted-skill/tracking-events-generator/models/pinterest/tag-template.js +28 -28
- package/extracted-skill/tracking-events-generator/models/quiz-funnel.md +83 -19
- package/extracted-skill/tracking-events-generator/models/reddit/conversions-api-template.js +205 -205
- package/extracted-skill/tracking-events-generator/models/reddit/event-mappings.json +56 -56
- package/extracted-skill/tracking-events-generator/models/reddit/pixel-template.js +19 -19
- package/extracted-skill/tracking-events-generator/models/scenarios/behavior-engine.js +425 -425
- package/extracted-skill/tracking-events-generator/route-intent-capture.js +222 -0
- package/extracted-skill/tracking-events-generator/tracking.config.js +3 -3
- package/package.json +89 -75
- package/scripts/build-sdk.js +106 -0
- package/server-edge-tracker/.client.env.example +14 -0
- package/server-edge-tracker/INSTALAR.md +222 -23
- package/server-edge-tracker/SEGMENTATION-DOCS.md +513 -0
- package/server-edge-tracker/config/utm-mapping.json +64 -0
- package/server-edge-tracker/deploy-client.cjs +76 -0
- package/server-edge-tracker/index.ts +1230 -0
- package/server-edge-tracker/migrate-v7.sql +64 -0
- package/server-edge-tracker/modules/db.ts +710 -0
- package/server-edge-tracker/modules/dispatch/crm.ts +382 -0
- package/server-edge-tracker/modules/dispatch/ga4.ts +72 -0
- package/server-edge-tracker/modules/dispatch/meta.ts +143 -0
- package/server-edge-tracker/modules/dispatch/platforms.ts +255 -0
- package/server-edge-tracker/modules/dispatch/tiktok.ts +107 -0
- package/server-edge-tracker/modules/dispatch/whatsapp.ts +296 -0
- package/server-edge-tracker/modules/intelligence.ts +589 -0
- package/server-edge-tracker/modules/ml/bidding.ts +247 -0
- package/server-edge-tracker/modules/ml/fraud.ts +302 -0
- package/server-edge-tracker/modules/ml/logistic.ts +226 -0
- package/server-edge-tracker/modules/ml/ltv.ts +531 -0
- package/server-edge-tracker/modules/ml/matchquality.ts +232 -0
- package/server-edge-tracker/modules/ml/quiz.ts +343 -0
- package/server-edge-tracker/modules/ml/roas.ts +255 -0
- package/server-edge-tracker/modules/ml/segmentation.ts +407 -0
- package/server-edge-tracker/modules/nurture.ts +257 -0
- package/server-edge-tracker/modules/utils.ts +311 -0
- package/server-edge-tracker/modules/utm/utm-enricher.ts +231 -0
- package/server-edge-tracker/schema-ab-ltv.sql +97 -0
- package/server-edge-tracker/schema-bidding.sql +86 -0
- package/server-edge-tracker/schema-fraud.sql +90 -0
- package/server-edge-tracker/schema-indexes.sql +67 -0
- package/server-edge-tracker/schema-ltv-feedback.sql +11 -0
- package/server-edge-tracker/schema-quiz.sql +52 -0
- package/server-edge-tracker/schema-sales-engine.sql +113 -0
- package/server-edge-tracker/schema-segmentation.sql +219 -0
- package/server-edge-tracker/schema-utm.sql +82 -0
- package/server-edge-tracker/schema.sql +281 -265
- package/server-edge-tracker/types.ts +275 -0
- package/server-edge-tracker/wrangler.toml +140 -85
- package/templates/lancamento-imobiliario.md +344 -0
- package/templates/multi-step-checkout.md +3 -4
- package/templates/pinterest/conversions-api-template.js +144 -144
- package/templates/pinterest/event-mappings.json +48 -48
- package/templates/pinterest/tag-template.js +28 -28
- package/templates/quiz-funnel.md +83 -19
- package/templates/reddit/conversions-api-template.js +205 -205
- package/templates/reddit/event-mappings.json +56 -56
- package/templates/reddit/pixel-template.js +12 -39
- package/templates/scenarios/behavior-engine.js +45 -22
- package/docs/PixelBuilder-Documentacao-Completa (2).docx +0 -0
- package/docs/installation.md +0 -155
- package/docs/quick-start.md +0 -185
- package/extracted-skill/tracking-events-generator/agents/crm-integration-agent.md +0 -1419
- package/extracted-skill/tracking-events-generator/agents/intelligence-scheduling.md +0 -643
- package/server-edge-tracker/worker.js +0 -2574
|
@@ -12,7 +12,7 @@ Ao ser ativado, você sempre gera os seguintes arquivos:
|
|
|
12
12
|
|---|---|
|
|
13
13
|
| `wrangler.toml` | Configuração completa do Worker com todos os bindings |
|
|
14
14
|
| `schema.sql` | Schema D1 completo: eventos, identity_graph, leads, behavioral_events |
|
|
15
|
-
| `
|
|
15
|
+
| `index.ts` | O Worker principal com lógica de processamento e engagement scoring server-side |
|
|
16
16
|
| `DEPLOY.md` | Guia passo a passo de deploy do zero ao funcionando |
|
|
17
17
|
|
|
18
18
|
---
|
|
@@ -27,7 +27,7 @@ Browser (Visitante)
|
|
|
27
27
|
▼
|
|
28
28
|
Cloudflare Edge (Worker)
|
|
29
29
|
├── Route Principal: /api/* ← Same-Domain Protocol
|
|
30
|
-
├── Route Webhook: /
|
|
30
|
+
├── Route Webhook: /webhook/* ← Rota para Gateways de Pagamento
|
|
31
31
|
├── Edge Routing (A/B) ← Interceptação via A/B Testing Agent
|
|
32
32
|
├── Edge Localization ← Manipulação de Checkout/Moeda
|
|
33
33
|
├── ML LTV Prediction ← Predição de Valor via Workers AI
|
|
@@ -56,7 +56,7 @@ Cloudflare Edge (Worker)
|
|
|
56
56
|
|
|
57
57
|
```toml
|
|
58
58
|
name = "cdp-edge-worker"
|
|
59
|
-
main = "
|
|
59
|
+
main = "index.ts"
|
|
60
60
|
compatibility_date = "2025-01-01"
|
|
61
61
|
compatibility_flags = ["nodejs_compat"]
|
|
62
62
|
|
|
@@ -89,11 +89,10 @@ UMBRELLA_DOMAIN = "dominio.com"
|
|
|
89
89
|
# META_ACCESS_TOKEN ← obrigatório
|
|
90
90
|
# GA4_API_SECRET ← obrigatório
|
|
91
91
|
# TIKTOK_ACCESS_TOKEN ← opcional
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
#
|
|
96
|
-
# WA_WEBHOOK_VERIFY_TOKEN ← gerado pelo agente (crypto.randomUUID)
|
|
92
|
+
# WHATSAPP_ACCESS_TOKEN ← WhatsApp Cloud API — token de acesso permanente
|
|
93
|
+
# WHATSAPP_PHONE_NUMBER_ID ← WhatsApp Cloud API — Phone Number ID (ex: 123456789012345)
|
|
94
|
+
# WA_NOTIFY_NUMBER ← Número do dono para receber notificações (ex: 5511999998888)
|
|
95
|
+
# WA_WEBHOOK_VERIFY_TOKEN ← Token de verificação do webhook CTWA (gerado via crypto.randomUUID)
|
|
97
96
|
# PINTEREST_ACCESS_TOKEN ← ativar Pinterest CAPI v5
|
|
98
97
|
# PINTEREST_AD_ACCOUNT_ID ← ativar Pinterest CAPI v5
|
|
99
98
|
# REDDIT_ACCESS_TOKEN ← ativar Reddit CAPI v2.0
|
|
@@ -214,7 +213,7 @@ CREATE INDEX IF NOT EXISTS idx_behavioral_events_engagement ON behavioral_events
|
|
|
214
213
|
|
|
215
214
|
## 📄 WORKER.JS (TEMPLATE COMPLETO)
|
|
216
215
|
|
|
217
|
-
```
|
|
216
|
+
```typescript
|
|
218
217
|
/**
|
|
219
218
|
* CDPEDGE CLOUDFLARE WORKER - Quantum Tier
|
|
220
219
|
*/
|
|
@@ -527,7 +526,7 @@ async function syncIdentity(DB, body) {
|
|
|
527
526
|
const fp = body.fingerprint || null;
|
|
528
527
|
if (!fp || !DB) return body;
|
|
529
528
|
|
|
530
|
-
const existing = await DB.prepare(
|
|
529
|
+
const existing = await env.DB.prepare(
|
|
531
530
|
'SELECT * FROM identity_graph WHERE fingerprint = ?'
|
|
532
531
|
).bind(fp).first();
|
|
533
532
|
|
|
@@ -542,7 +541,7 @@ async function syncIdentity(DB, body) {
|
|
|
542
541
|
visit_count: (existing.visit_count || 1) + 1
|
|
543
542
|
};
|
|
544
543
|
} else {
|
|
545
|
-
await DB.prepare(`
|
|
544
|
+
await env.DB.prepare(`
|
|
546
545
|
INSERT OR IGNORE INTO identity_graph (fingerprint, fbp, fbc, ga_client_id, external_id, ttclid, first_utm)
|
|
547
546
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
548
547
|
`).bind(fp, body.fbp, body.fbc, body.ga_client_id, body.external_id, body.ttclid, JSON.stringify(body.utm || {})).run();
|
|
@@ -636,7 +635,7 @@ function buildCookieHeader(visitor, umbrellaDomain) {
|
|
|
636
635
|
async function logBehavioralEvent(DB, body, visitor, engagementScore) {
|
|
637
636
|
if (!DB) return;
|
|
638
637
|
|
|
639
|
-
await DB.prepare(`
|
|
638
|
+
await env.DB.prepare(`
|
|
640
639
|
INSERT OR REPLACE INTO behavioral_events (
|
|
641
640
|
event_id, user_id, session_id,
|
|
642
641
|
engagement_score, time_level, scroll_score, click_score, video_score, hover_score, intention_level,
|
|
@@ -691,7 +690,7 @@ O engagement scoring no servidor é mais preciso que no browser porque tem acess
|
|
|
691
690
|
|
|
692
691
|
### Cálculo por Componente
|
|
693
692
|
|
|
694
|
-
```
|
|
693
|
+
```typescript
|
|
695
694
|
// 1. Visit Score (25%)
|
|
696
695
|
function calculateVisitScore(visitorContext) {
|
|
697
696
|
const visitCount = visitorContext.visit_count || 1;
|
|
@@ -758,7 +757,7 @@ const finalScore = (
|
|
|
758
757
|
### Integração com Plataformas
|
|
759
758
|
|
|
760
759
|
**Meta CAPI v22.0:**
|
|
761
|
-
```
|
|
760
|
+
```typescript
|
|
762
761
|
custom_data: {
|
|
763
762
|
engagement_score: engagementScore.server_engagement_score,
|
|
764
763
|
intention_level: engagementScore.final_intention_level,
|
|
@@ -773,7 +772,7 @@ custom_data: {
|
|
|
773
772
|
```
|
|
774
773
|
|
|
775
774
|
**Google GA4 Measurement Protocol:**
|
|
776
|
-
```
|
|
775
|
+
```typescript
|
|
777
776
|
custom_params: {
|
|
778
777
|
engagement_score: engagementScore.server_engagement_score,
|
|
779
778
|
intention_level: engagementScore.final_intention_level,
|
|
@@ -783,7 +782,7 @@ custom_params: {
|
|
|
783
782
|
```
|
|
784
783
|
|
|
785
784
|
**TikTok Events API v1.3:**
|
|
786
|
-
```
|
|
785
|
+
```typescript
|
|
787
786
|
context: {
|
|
788
787
|
user: {
|
|
789
788
|
engagement_score: engagementScore.server_engagement_score,
|
|
@@ -796,6 +795,7 @@ context: {
|
|
|
796
795
|
|
|
797
796
|
## ✅ REGRAS CRÍTICAS
|
|
798
797
|
|
|
798
|
+
0. **CONSULTA OBRIGATÓRIA À MEMÓRIA**: Extraia os valores exatos de `Hash Salts`, domínios, `CORS` e `Rate Limits` consultando ativamente o "memory-agent.json" (Agente Memória). Solicite as variáveis antecipadamente ao Orquestrador se não as possuir. Execute a arquitetura de borda exclusivamente com dados oficiais extraídos do repositório da Memória.
|
|
799
799
|
1. **Cloudflare-Only**: Sem dependências externas.
|
|
800
800
|
2. **Same-Domain**: Worker no domínio do site (anti-adblock).
|
|
801
801
|
3. **Umbrella Protocol**: Cookies com abrangência de domínio.
|
|
@@ -812,7 +812,7 @@ context: {
|
|
|
812
812
|
### Estratégias para Maximizar Resiliência
|
|
813
813
|
|
|
814
814
|
**1. Same-Domain Endpoint:**
|
|
815
|
-
- Worker deve estar no mesmo domínio do site: `site.com/
|
|
815
|
+
- Worker deve estar no mesmo domínio do site: `site.com/track`
|
|
816
816
|
- Evita bloqueios de CORS e ad-blockers que bloqueiam requests cross-origin
|
|
817
817
|
|
|
818
818
|
**2. First-Party Cookies:**
|
|
@@ -821,7 +821,7 @@ context: {
|
|
|
821
821
|
- SameSite=Lax para balance entre segurança e funcionalidade
|
|
822
822
|
|
|
823
823
|
**3. Response Headers Anti-Blocking:**
|
|
824
|
-
```
|
|
824
|
+
```typescript
|
|
825
825
|
const corsHeaders = {
|
|
826
826
|
'Access-Control-Allow-Origin': '*',
|
|
827
827
|
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
@@ -843,9 +843,9 @@ const corsHeaders = {
|
|
|
843
843
|
- Ad-blockers podem falsificar user-agent
|
|
844
844
|
- Validação deve ser baseada em token/secret, não UA
|
|
845
845
|
|
|
846
|
-
**6.
|
|
847
|
-
-
|
|
848
|
-
-
|
|
846
|
+
**6. Same-Domain via Worker Route (anti-blocking):**
|
|
847
|
+
- Endpoint de tracking: `/track` (Worker route same-domain — ad-blockers não bloqueiam requests same-domain)
|
|
848
|
+
- A proteção real vem do same-domain, não do nome do path
|
|
849
849
|
|
|
850
850
|
---
|
|
851
851
|
|
|
@@ -883,7 +883,7 @@ Tentativa 3 (Cloudflare Queue - 15 minutos)
|
|
|
883
883
|
|
|
884
884
|
Toda função de dispatch (Meta, Google, TikTok) DEVE ter try/catch com gravação:
|
|
885
885
|
|
|
886
|
-
```
|
|
886
|
+
```typescript
|
|
887
887
|
// Exemplo para dispatchMetaCapi com escalonamento
|
|
888
888
|
async function dispatchMetaCapi(body, env, visitor, heatScore, clientIP, userAgent, cf, retryCount = 0) {
|
|
889
889
|
if (!env.META_ACCESS_TOKEN || !body.pixel_id) {
|
|
@@ -967,12 +967,12 @@ CREATE INDEX IF NOT EXISTS idx_retry_scheduled ON retry_queue(scheduled_at, stat
|
|
|
967
967
|
|
|
968
968
|
### PASSO 3 — Funções de Log de Sucesso/Falha
|
|
969
969
|
|
|
970
|
-
```
|
|
970
|
+
```typescript
|
|
971
971
|
// Log de sucesso
|
|
972
972
|
async function logEventSuccess(DB, platform, eventId) {
|
|
973
973
|
if (!DB) return;
|
|
974
974
|
|
|
975
|
-
await DB.prepare(`
|
|
975
|
+
await env.DB.prepare(`
|
|
976
976
|
UPDATE events_log
|
|
977
977
|
SET status = 'success',
|
|
978
978
|
retry_count = 0,
|
|
@@ -988,7 +988,7 @@ async function logEventFailure(DB, platform, eventId, errorMessage, retryCount)
|
|
|
988
988
|
const maxRetries = 3;
|
|
989
989
|
const isFinalFailure = retryCount >= maxRetries;
|
|
990
990
|
|
|
991
|
-
await DB.prepare(`
|
|
991
|
+
await env.DB.prepare(`
|
|
992
992
|
UPDATE events_log
|
|
993
993
|
SET status = ?,
|
|
994
994
|
retry_count = ?,
|
|
@@ -1033,7 +1033,7 @@ async function enqueueRetry(queue, retryData) {
|
|
|
1033
1033
|
|
|
1034
1034
|
Após 3 falhas consecutivas, disparar alerta para o administrador:
|
|
1035
1035
|
|
|
1036
|
-
```
|
|
1036
|
+
```typescript
|
|
1037
1037
|
// Função de alerta integrada com WhatsApp Agent
|
|
1038
1038
|
async function dispatchAlert(platform, eventId, errorMessage) {
|
|
1039
1039
|
const alertMessage = `
|
|
@@ -1049,7 +1049,7 @@ Timestamp: ${new Date().toISOString()}
|
|
|
1049
1049
|
`.trim();
|
|
1050
1050
|
|
|
1051
1051
|
// Verificar se há token do WhatsApp configurado
|
|
1052
|
-
const waPhoneId = env.
|
|
1052
|
+
const waPhoneId = env.WHATSAPP_PHONE_NUMBER_ID;
|
|
1053
1053
|
const adminNumber = env.ADMIN_PHONE_NUMBER;
|
|
1054
1054
|
|
|
1055
1055
|
if (waPhoneId && adminNumber) {
|
|
@@ -1057,7 +1057,7 @@ Timestamp: ${new Date().toISOString()}
|
|
|
1057
1057
|
method: 'POST',
|
|
1058
1058
|
headers: {
|
|
1059
1059
|
'Content-Type': 'application/json',
|
|
1060
|
-
'Authorization': `Bearer ${env.
|
|
1060
|
+
'Authorization': `Bearer ${env.WHATSAPP_ACCESS_TOKEN}`
|
|
1061
1061
|
},
|
|
1062
1062
|
body: JSON.stringify({
|
|
1063
1063
|
messaging_product: 'whatsapp',
|
|
@@ -1098,9 +1098,9 @@ max_batch_timeout = 60
|
|
|
1098
1098
|
cron = "* * * * *" # A cada minuto
|
|
1099
1099
|
```
|
|
1100
1100
|
|
|
1101
|
-
E no `
|
|
1101
|
+
E no `index.ts`, adicionar handler de queue:
|
|
1102
1102
|
|
|
1103
|
-
```
|
|
1103
|
+
```typescript
|
|
1104
1104
|
// Handler de Queue (retries)
|
|
1105
1105
|
export async function queue(batch, env) {
|
|
1106
1106
|
for (const message of batch.messages) {
|
|
@@ -1144,13 +1144,13 @@ export async function queue(batch, env) {
|
|
|
1144
1144
|
- Plataformas selecionadas na FASE 0-B (Meta, Google, TikTok, etc.)
|
|
1145
1145
|
- `UMBRELLA_DOMAIN` — domínio principal do funil (detectado automaticamente ou fornecido pelo usuário)
|
|
1146
1146
|
- Secrets de plataformas: `META_ACCESS_TOKEN`, `GA4_API_SECRET`, `TIKTOK_ACCESS_TOKEN`
|
|
1147
|
-
- Secrets opcionais: `RESEND_API_KEY`, `
|
|
1147
|
+
- Secrets opcionais: `RESEND_API_KEY`, `WHATSAPP_ACCESS_TOKEN`, `WHATSAPP_PHONE_NUMBER_ID`
|
|
1148
1148
|
|
|
1149
1149
|
## RESPONSABILIDADE
|
|
1150
1150
|
|
|
1151
1151
|
- Gerar `wrangler.toml` completo com bindings D1, KV, R2, Queues e Cron Triggers
|
|
1152
1152
|
- Gerar `schema.sql` com todas as tabelas: `events_log`, `identity_graph`, `leads`, `behavioral_events`, `webhook_events`, `user_profiles`
|
|
1153
|
-
- Gerar `
|
|
1153
|
+
- Gerar `index.ts` principal com endpoint `/track` (recebe eventos do browser)
|
|
1154
1154
|
- Implementar Identity Graph sync, Engagement Scoring server-side e First-Party Cookie (`_cdp_uid`)
|
|
1155
1155
|
- Implementar Anti-Blocking: CORS same-domain, headers limpos, sem keywords bloqueáveis
|
|
1156
1156
|
- Implementar sistema de retry com Cloudflare Queues (3-Tier: imediato → 5min → 15min → 45min)
|
|
@@ -1163,13 +1163,13 @@ export async function queue(batch, env) {
|
|
|
1163
1163
|
"arquivos_gerados": [
|
|
1164
1164
|
"wrangler.toml",
|
|
1165
1165
|
"schema.sql",
|
|
1166
|
-
"
|
|
1166
|
+
"index.ts",
|
|
1167
1167
|
"DEPLOY.md"
|
|
1168
1168
|
],
|
|
1169
1169
|
"endpoints": {
|
|
1170
|
-
"tracking": "POST /
|
|
1170
|
+
"tracking": "POST /track",
|
|
1171
1171
|
"health": "GET /api/health",
|
|
1172
|
-
"webhooks": "POST /
|
|
1172
|
+
"webhooks": "POST /webhook/{gateway}",
|
|
1173
1173
|
"ticto": "POST /webhook/ticto"
|
|
1174
1174
|
},
|
|
1175
1175
|
"bindings_cloudflare": {
|
|
@@ -4,6 +4,14 @@ Você é o especialista em **Spotify Ad Studio e Spotify Conversions API**. Sua
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## ✅ REGRAS CRÍTICAS
|
|
8
|
+
|
|
9
|
+
0. **CONSULTA OBRIGATÓRIA À MEMÓRIA**: Extraia o ID de Conta de Anúncios Spotify e Token de Acesso (`SPOTIFY_AD_ACCOUNT_ID`, `SPOTIFY_ACCESS_TOKEN`) consultando ativamente o "memory-agent.json". Solicite ao Orquestrador tudo o que faltar. Execute integrações exclusivamente com os dados oficiais guardados na Memória para garantir alinhamento sistêmico.
|
|
10
|
+
1. Cloudflare-Only: Sem dependências externas.
|
|
11
|
+
2. Same-Domain: Worker no domínio do site (anti-adblock).
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
7
15
|
## 🏗️ ARQUITETURA QUANTUM TIER
|
|
8
16
|
|
|
9
17
|
### Stack Spotify Ads
|
|
@@ -27,7 +35,7 @@ Database: Cloudflare D1 (Persistência)
|
|
|
27
35
|
- Gera `event_id` para deduplicação com server-side
|
|
28
36
|
|
|
29
37
|
### 2. Server Tracking (Spotify Conversions API)
|
|
30
|
-
- `spotify
|
|
38
|
+
- `modules/dispatch/spotify.ts` — Payloads para API de conversões Spotify
|
|
31
39
|
- Envia eventos para Conversions API com deduplicação
|
|
32
40
|
- Usa `crypto.subtle.digest('SHA-256')` para PII (email, phone)
|
|
33
41
|
|
|
@@ -40,7 +48,7 @@ Database: Cloudflare D1 (Persistência)
|
|
|
40
48
|
| Arquivo | Descrição |
|
|
41
49
|
|---------|-----------|
|
|
42
50
|
| `spotify-pixel.js` | Spotify Pixel SDK (Browser) |
|
|
43
|
-
| `spotify
|
|
51
|
+
| `modules/dispatch/spotify.ts` | Spotify Conversions API Payloads (Server — TypeScript) |
|
|
44
52
|
|
|
45
53
|
---
|
|
46
54
|
|
|
@@ -211,12 +219,12 @@ Spotify Ads suporta Advanced Matching para melhorar a qualidade do sinal:
|
|
|
211
219
|
|
|
212
220
|
## 💻 O QUE VOCÊ GERA (SERVER)
|
|
213
221
|
|
|
214
|
-
### `spotify
|
|
222
|
+
### `modules/dispatch/spotify.ts`
|
|
215
223
|
|
|
216
|
-
```
|
|
224
|
+
```typescript
|
|
217
225
|
/**
|
|
218
226
|
* Spotify Conversions API - Server-Side Tracking
|
|
219
|
-
* CDP Edge Quantum Tier - Cloudflare Worker
|
|
227
|
+
* CDP Edge Quantum Tier - Cloudflare Worker (TypeScript)
|
|
220
228
|
*/
|
|
221
229
|
|
|
222
230
|
/**
|
|
@@ -302,7 +310,7 @@ export async function hashPII(data) {
|
|
|
302
310
|
| Depende de | Input Esperado | O que faz com isso |
|
|
303
311
|
|-------------|----------------|------------------|
|
|
304
312
|
| **Page Analyzer** | Lista de elementos HTML | Mapeia `content_name` e `content_id` |
|
|
305
|
-
| **Server Tracking Agent** | Lista de plataformas | Adiciona endpoint Spotify `/
|
|
313
|
+
| **Server Tracking Agent** | Lista de plataformas | Adiciona endpoint Spotify `/webhook/spotify` |
|
|
306
314
|
| **Premium Tracking Intelligence** | Estratégia de tracking | Define eventos prioritários para Spotify |
|
|
307
315
|
| **Validator Agent** | Código gerado | Valida conformidade com Spotify API v1 |
|
|
308
316
|
|
|
@@ -341,7 +349,7 @@ Ao final, gere um relatório JSON:
|
|
|
341
349
|
"fix": "Adicionar comentário explicando integração"
|
|
342
350
|
},
|
|
343
351
|
{
|
|
344
|
-
"file": "spotify
|
|
352
|
+
"file": "modules/dispatch/spotify.ts",
|
|
345
353
|
"issue": "Descrição",
|
|
346
354
|
"fix": "Adicionar retry logic com Promise.allSettled"
|
|
347
355
|
}
|
|
@@ -4,6 +4,14 @@ Especialista exclusivo em TikTok Pixel (browser via cdpTrack) + TikTok Events AP
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## ✅ REGRAS CRÍTICAS
|
|
8
|
+
|
|
9
|
+
0. **CONSULTA OBRIGATÓRIA À MEMÓRIA**: Extraia o ID de Pixel TikTok e Token de Acesso (`TIKTOK_PIXEL_ID`, `TIKTOK_ACCESS_TOKEN`) consultando ativamente o "memory-agent.json". Solicite ao Orquestrador tudo o que faltar. Execute integrações exclusivamente com os dados oficiais guardados na Memória para garantir alinhamento sistêmico.
|
|
10
|
+
1. Cloudflare-Only: Sem dependências externas.
|
|
11
|
+
2. Same-Domain: Worker no domínio do site (anti-adblock).
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
7
15
|
## 🏗️ ARQUITETURA Quantum Tier
|
|
8
16
|
- **Browser**: Use `cdpTrack.js` para captura direta.
|
|
9
17
|
- **Server**: Cloudflare Worker enviando para `/open_api/v1.3/event/track/`.
|
|
@@ -15,7 +23,7 @@ Especialista exclusivo em TikTok Pixel (browser via cdpTrack) + TikTok Events AP
|
|
|
15
23
|
|
|
16
24
|
### PASSO 0 — Ler Versões Atuais
|
|
17
25
|
|
|
18
|
-
```
|
|
26
|
+
```typescript
|
|
19
27
|
// Ler versões do arquivo centralizado
|
|
20
28
|
const apiVersions = await readJSON('contracts/api-versions.json');
|
|
21
29
|
const tiktokVersion = apiVersions.tiktok;
|
|
@@ -65,6 +73,69 @@ Gere payloads para o Worker seguir a API oficial:
|
|
|
65
73
|
|
|
66
74
|
---
|
|
67
75
|
|
|
76
|
+
## ⏱️ RATE LIMITS — TikTok Events API v1.3
|
|
77
|
+
|
|
78
|
+
Conforme `contracts/api-versions.json`, a TikTok Events API tem limites estritos:
|
|
79
|
+
|
|
80
|
+
| Limite | Valor | Ação se excedido |
|
|
81
|
+
|--------|-------|-----------------|
|
|
82
|
+
| Requisições por minuto (por pixel) | 10 req/min | Implementar throttling |
|
|
83
|
+
| Eventos por batch | 5 events/batch | Agrupar eventos em batches |
|
|
84
|
+
| Retries máximos | 3 tentativas | Backoff exponencial |
|
|
85
|
+
|
|
86
|
+
### Implementação de Throttling no Worker
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
// Rate limit KV key: 'tiktok_rate_{pixel_id}_{minute}'
|
|
90
|
+
async function dispatchTikTokWithRateLimit(env, events, pixelId, accessToken) {
|
|
91
|
+
const now = new Date();
|
|
92
|
+
const minuteKey = `tiktok_rate_${pixelId}_${now.getUTCFullYear()}${now.getUTCMonth()}${now.getUTCDate()}${now.getUTCHours()}${now.getUTCMinutes()}`;
|
|
93
|
+
|
|
94
|
+
// Verificar rate limit no KV
|
|
95
|
+
const currentCount = parseInt(await env.GEO_CACHE.get(minuteKey) || '0');
|
|
96
|
+
|
|
97
|
+
if (currentCount >= 10) {
|
|
98
|
+
// Rate limit atingido — encaminhar para RETRY_QUEUE
|
|
99
|
+
await env.RETRY_QUEUE.send({ platform: 'tiktok', events, pixelId });
|
|
100
|
+
return { queued: true, reason: 'rate_limit' };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Agrupar eventos em batches de 5
|
|
104
|
+
const batches = [];
|
|
105
|
+
for (let i = 0; i < events.length; i += 5) {
|
|
106
|
+
batches.push(events.slice(i, i + 5));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const results = [];
|
|
110
|
+
for (const batch of batches) {
|
|
111
|
+
const result = await fetch('https://business-api.tiktok.com/open_api/v1.3/event/track/', {
|
|
112
|
+
method: 'POST',
|
|
113
|
+
headers: {
|
|
114
|
+
'Content-Type': 'application/json',
|
|
115
|
+
'Access-Token': accessToken
|
|
116
|
+
},
|
|
117
|
+
body: JSON.stringify({
|
|
118
|
+
pixel_code: pixelId,
|
|
119
|
+
event_source: 'web',
|
|
120
|
+
event_source_id: pixelId,
|
|
121
|
+
data: batch
|
|
122
|
+
})
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Incrementar contador no KV (TTL de 60s = 1 minuto)
|
|
126
|
+
await env.GEO_CACHE.put(minuteKey, String(currentCount + 1), { expirationTtl: 60 });
|
|
127
|
+
|
|
128
|
+
results.push(result);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return { sent: results.length, batches: batches.length };
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
> **Regra:** Se `HTTP 429` for recebido da TikTok API, encaminhar eventos para `RETRY_QUEUE` com backoff de 1min, 2min, 4min (máximo 3 tentativas).
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
68
139
|
## INPUTS RECEBIDOS
|
|
69
140
|
|
|
70
141
|
- JSON do Page Analyzer Agent (eventos mapeados, seletores, tipo de página)
|
|
@@ -90,7 +161,7 @@ Gere payloads para o Worker seguir a API oficial:
|
|
|
90
161
|
{
|
|
91
162
|
"arquivos_gerados": {
|
|
92
163
|
"browser": "cdpTrack.js (eventos TikTok injetados)",
|
|
93
|
-
"server": "
|
|
164
|
+
"server": "modules/dispatch/tiktok.ts"
|
|
94
165
|
},
|
|
95
166
|
"versao_api": "v1.3",
|
|
96
167
|
"endpoint": "/open_api/v1.3/event/track/",
|
|
@@ -28,7 +28,7 @@ Gerar um tracking plan **validado e verificável** que elimine:
|
|
|
28
28
|
|
|
29
29
|
### 1.1 Verificar Cobertura de Eventos
|
|
30
30
|
|
|
31
|
-
```
|
|
31
|
+
```typescript
|
|
32
32
|
// Comparar eventos do Page Analyzer com outputs dos agentes
|
|
33
33
|
function validateEventCoverage(pageAnalysis, agentOutputs) {
|
|
34
34
|
const pageEvents = new Set();
|
|
@@ -59,26 +59,37 @@ function validateEventCoverage(pageAnalysis, agentOutputs) {
|
|
|
59
59
|
});
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
-
// Encontrar eventos
|
|
63
|
-
const
|
|
62
|
+
// Encontrar eventos do Page Analyzer NÃO implementados por nenhum agente
|
|
63
|
+
const unimplementedEvents = [];
|
|
64
|
+
pageEvents.forEach(eventKey => {
|
|
65
|
+
if (!agentEvents.has(eventKey)) {
|
|
66
|
+
unimplementedEvents.push(eventKey);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Encontrar eventos implementados pelos agentes mas SEM correspondência no Page Analyzer
|
|
71
|
+
const orphanEvents = [];
|
|
64
72
|
agentEvents.forEach(eventKey => {
|
|
65
73
|
if (!pageEvents.has(eventKey)) {
|
|
66
|
-
|
|
74
|
+
orphanEvents.push(eventKey);
|
|
67
75
|
}
|
|
68
76
|
});
|
|
69
77
|
|
|
70
78
|
return {
|
|
71
79
|
total_page_events: pageEvents.size,
|
|
72
80
|
total_implemented_events: agentEvents.size,
|
|
73
|
-
|
|
74
|
-
|
|
81
|
+
unimplemented_events: unimplementedEvents, // ← Eventos do plano sem código
|
|
82
|
+
orphan_events: orphanEvents, // ← Código sem evento no plano
|
|
83
|
+
coverage_percentage: Math.round(
|
|
84
|
+
((pageEvents.size - unimplementedEvents.length) / Math.max(pageEvents.size, 1)) * 100
|
|
85
|
+
)
|
|
75
86
|
};
|
|
76
87
|
}
|
|
77
88
|
```
|
|
78
89
|
|
|
79
90
|
### 1.2 Verificar Consistência de Parâmetros
|
|
80
91
|
|
|
81
|
-
```
|
|
92
|
+
```typescript
|
|
82
93
|
// Verificar se eventos de conversão têm todos os campos críticos
|
|
83
94
|
function validateConversionParameters(events, apiVersions) {
|
|
84
95
|
const criticalFields = ['value', 'currency', 'content_ids', 'transaction_id'];
|
|
@@ -107,7 +118,7 @@ function validateConversionParameters(events, apiVersions) {
|
|
|
107
118
|
|
|
108
119
|
### 1.3 Verificar Seletores Implementados
|
|
109
120
|
|
|
110
|
-
```
|
|
121
|
+
```typescript
|
|
111
122
|
// Verificar se seletores no tracking plan existem no código
|
|
112
123
|
function validateSelectorsExist(trackingPlan, pageAnalysis) {
|
|
113
124
|
const missingSelectors = [];
|
|
@@ -147,7 +158,7 @@ function validateSelectorsExist(trackingPlan, pageAnalysis) {
|
|
|
147
158
|
|
|
148
159
|
### 1.4 Verificar Versões de API
|
|
149
160
|
|
|
150
|
-
```
|
|
161
|
+
```typescript
|
|
151
162
|
// Ler api-versions.json e verificar consistência
|
|
152
163
|
async function validateApiVersions(trackingPlan) {
|
|
153
164
|
const apiVersions = await readJSON('contracts/api-versions.json');
|
|
@@ -187,6 +198,90 @@ async function validateApiVersions(trackingPlan) {
|
|
|
187
198
|
}
|
|
188
199
|
```
|
|
189
200
|
|
|
201
|
+
### 1.5 Validação Cruzada Completa (runFullValidation)
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
/**
|
|
205
|
+
* Ponto de entrada principal — executa TODAS as validações em sequência
|
|
206
|
+
* e retorna um relatório consolidado com status PASS | WARN | BLOCK
|
|
207
|
+
*
|
|
208
|
+
* @param {Object} pageAnalysis - Output do Page Analyzer Agent
|
|
209
|
+
* @param {Object} agentOutputs - Código gerado por todos os agentes
|
|
210
|
+
* @param {Object} apiVersions - Conteúdo de contracts/api-versions.json
|
|
211
|
+
* @returns {Object} Relatório consolidado de validação
|
|
212
|
+
*/
|
|
213
|
+
async function runFullValidation(pageAnalysis, agentOutputs, apiVersions) {
|
|
214
|
+
const report = {
|
|
215
|
+
status: 'PASS', // PASS | WARN | BLOCK
|
|
216
|
+
timestamp: new Date().toISOString(),
|
|
217
|
+
checks: {}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// CHECK 1: Cobertura de eventos
|
|
221
|
+
const coverage = validateEventCoverage(pageAnalysis, agentOutputs);
|
|
222
|
+
report.checks.event_coverage = coverage;
|
|
223
|
+
if (coverage.coverage_percentage < 100) {
|
|
224
|
+
report.status = coverage.coverage_percentage < 80 ? 'BLOCK' : 'WARN';
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// CHECK 2: Parâmetros de conversão
|
|
228
|
+
const allEvents = Object.values(agentOutputs).flatMap(o => o.events || []);
|
|
229
|
+
const paramIssues = validateConversionParameters(allEvents, apiVersions);
|
|
230
|
+
report.checks.conversion_params = paramIssues;
|
|
231
|
+
if (paramIssues.filter(i => i.severity === 'HIGH').length > 0) {
|
|
232
|
+
report.status = 'BLOCK';
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// CHECK 3: Seletores existentes no código
|
|
236
|
+
const missingSelectors = validateSelectorsExist({}, pageAnalysis);
|
|
237
|
+
report.checks.selectors = { missing: missingSelectors };
|
|
238
|
+
if (missingSelectors.length > 0) {
|
|
239
|
+
if (report.status === 'PASS') report.status = 'WARN';
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// CHECK 4: Versões de API consistentes com api-versions.json
|
|
243
|
+
const trackingPlan = { events: {} };
|
|
244
|
+
Object.entries(agentOutputs).forEach(([agent, output]) => {
|
|
245
|
+
if (output.events) trackingPlan.events[agent] = output.events;
|
|
246
|
+
});
|
|
247
|
+
await validateApiVersions(trackingPlan);
|
|
248
|
+
const apiIssues = Object.values(trackingPlan.events)
|
|
249
|
+
.flatMap(events => events.filter(e => e.api_version_issue || e.api_deprecated));
|
|
250
|
+
report.checks.api_versions = apiIssues;
|
|
251
|
+
if (apiIssues.some(e => e.api_deprecated)) {
|
|
252
|
+
report.status = 'BLOCK'; // API depreciada = bloquear deploy
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// CHECK 5: Regras de ouro — deduplicação event_id
|
|
256
|
+
const missingEventId = allEvents.filter(e => !e.event_id && !e.params?.event_id);
|
|
257
|
+
report.checks.deduplication = {
|
|
258
|
+
events_missing_event_id: missingEventId.map(e => `${e.platform}:${e.name}`)
|
|
259
|
+
};
|
|
260
|
+
if (missingEventId.length > 0) report.status = 'WARN';
|
|
261
|
+
|
|
262
|
+
// CHECK 6: SHA-256 em campos PII
|
|
263
|
+
const piiFields = ['em', 'ph', 'fn', 'ln'];
|
|
264
|
+
const unhashed = allEvents.filter(e =>
|
|
265
|
+
piiFields.some(field => e.user_data?.[field] && !e.user_data[field].match(/^[a-f0-9]{64}$/))
|
|
266
|
+
);
|
|
267
|
+
report.checks.pii_hashing = {
|
|
268
|
+
events_with_unhashed_pii: unhashed.map(e => `${e.platform}:${e.name}`)
|
|
269
|
+
};
|
|
270
|
+
if (unhashed.length > 0) {
|
|
271
|
+
report.status = 'BLOCK'; // PII sem hash = bloquear imediatamente
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Determinar mensagem de status
|
|
275
|
+
report.summary = {
|
|
276
|
+
PASS: '✅ Tracking Plan validado — pode fazer deploy',
|
|
277
|
+
WARN: '⚠️ Tracking Plan com alertas — revisar antes do deploy',
|
|
278
|
+
BLOCK: '❌ BLOQUEADO — corrigir itens críticos antes do deploy'
|
|
279
|
+
}[report.status];
|
|
280
|
+
|
|
281
|
+
return report;
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
190
285
|
---
|
|
191
286
|
|
|
192
287
|
## PASSO 2 — GERAR O TRACKING PLAN COM VALIDAÇÃO
|