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
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# Modelo: Lançamento Imobiliário (Cloudflare Native)
|
|
2
|
+
|
|
3
|
+
Template para páginas de lançamento imobiliário com formulário de interesse, galeria, mapa/localização, simulador de financiamento, vídeo de tour, calendário de agendamento e botão WhatsApp.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🏗️ ARQUITETURA TÉCNICA (Quantum Tier)
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Browser (cdpTrack.js)
|
|
11
|
+
├─ PageView → ao carregar
|
|
12
|
+
├─ ViewContent → ao entrar na galeria
|
|
13
|
+
├─ FindLocation → ao interagir com mapa/localização
|
|
14
|
+
├─ video_25/50/75/complete → ao assistir tour virtual
|
|
15
|
+
├─ CustomizeProduct → ao usar simulador de financiamento
|
|
16
|
+
├─ AddToWishlist → ao favoritar imóvel
|
|
17
|
+
├─ Contact → ao clicar em WhatsApp/telefone
|
|
18
|
+
├─ Schedule → ao confirmar agendamento de visita
|
|
19
|
+
└─ Lead → ao enviar formulário (PII completo)
|
|
20
|
+
│
|
|
21
|
+
▼
|
|
22
|
+
Cloudflare Worker (same-domain /track)
|
|
23
|
+
├─ Fraud Gate
|
|
24
|
+
├─ LTV Prediction (Granite 4.0 Micro) + score por eventType
|
|
25
|
+
├─ D1: upsertProfile, identity graph, distanceKm
|
|
26
|
+
└─ CAPI dispatch: Meta v22.0 + GA4 + TikTok v1.3
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 📘 MAPA DE EVENTOS
|
|
32
|
+
|
|
33
|
+
| Evento | Gatilho | Sinal para as plataformas |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| `PageView` | Carregamento | Topo do funil |
|
|
36
|
+
| `ViewContent` | Entra na galeria de fotos | Interesse no produto |
|
|
37
|
+
| `FindLocation` | Clica em mapa / "Como chegar" / abre localização | Intenção de visita física — +10 LTV |
|
|
38
|
+
| `video_25` / `video_50` / `video_75` / `video_complete` | Tour virtual / VSL em % assistido | Engajamento profundo |
|
|
39
|
+
| `CustomizeProduct` | Usa simulador de financiamento/parcelas/FGTS | Intenção de compra máxima — +15 LTV |
|
|
40
|
+
| `AddToWishlist` | Clica em "Favoritar" / coração | Interesse persistente — +8 LTV |
|
|
41
|
+
| `Contact` | Clica em WhatsApp ou telefone | Alta intenção de contato |
|
|
42
|
+
| `Schedule` | Confirma agendamento de visita | Conversão de visita |
|
|
43
|
+
| `Lead` | Envia formulário (nome/email/telefone) | Conversão principal com PII |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 🛠️ PASSO 1: CONFIGURAÇÃO DO SDK
|
|
48
|
+
|
|
49
|
+
### 1.1 Header
|
|
50
|
+
```html
|
|
51
|
+
<script src="/js/cdpTrack.js" async></script>
|
|
52
|
+
<script>
|
|
53
|
+
window.cdpConfig = {
|
|
54
|
+
metaId: 'SEU_PIXEL_ID',
|
|
55
|
+
ttId: 'SEU_TIKTOK_ID',
|
|
56
|
+
trackEndpoint: '/track'
|
|
57
|
+
};
|
|
58
|
+
</script>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 🛠️ PASSO 2: EVENTOS DE COMPORTAMENTO
|
|
64
|
+
|
|
65
|
+
### 2.1 PageView (automático via SDK)
|
|
66
|
+
O SDK dispara automaticamente. Não precisa de código adicional.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
### 2.2 ViewContent — Galeria de fotos
|
|
71
|
+
```javascript
|
|
72
|
+
// Dispara quando usuário abre/rola a galeria de imagens
|
|
73
|
+
document.querySelector('.galeria-imovel, [data-section="gallery"]')?.addEventListener('click', () => {
|
|
74
|
+
cdpTrack.track('ViewContent', {
|
|
75
|
+
contentName: 'Galeria — [NOME DO EMPREENDIMENTO]',
|
|
76
|
+
contentCategory: 'imovel',
|
|
77
|
+
funnel_stage: 'gallery_view',
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
### 2.3 FindLocation — Mapa / Localização
|
|
85
|
+
```javascript
|
|
86
|
+
// Dispara quando usuário clica no mapa, "Como chegar" ou "Ver localização"
|
|
87
|
+
document.querySelectorAll(
|
|
88
|
+
'a[href*="maps"], a[href*="waze"], [data-section="localizacao"], #mapa, .btn-localizacao, .btn-como-chegar'
|
|
89
|
+
).forEach(el => {
|
|
90
|
+
el.addEventListener('click', () => {
|
|
91
|
+
cdpTrack.track('FindLocation', {
|
|
92
|
+
contentName: 'Localização — [NOME DO EMPREENDIMENTO]',
|
|
93
|
+
contentCategory: 'imovel',
|
|
94
|
+
funnel_stage: 'map_view',
|
|
95
|
+
// Coordenadas do empreendimento (preencher):
|
|
96
|
+
property_lat: -23.5505, // latitude
|
|
97
|
+
property_lng: -46.6333, // longitude
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### 2.4 Vídeo / Tour Virtual
|
|
106
|
+
```javascript
|
|
107
|
+
// Para vídeo HTML5 nativo:
|
|
108
|
+
const video = document.querySelector('video#tour-virtual, video.tour-360');
|
|
109
|
+
if (video) {
|
|
110
|
+
const fired = new Set();
|
|
111
|
+
video.addEventListener('timeupdate', () => {
|
|
112
|
+
const pct = Math.floor((video.currentTime / video.duration) * 100);
|
|
113
|
+
if (pct >= 25 && !fired.has(25)) {
|
|
114
|
+
fired.add(25);
|
|
115
|
+
cdpTrack.track('video_25', { contentName: 'Tour Virtual — [NOME DO EMPREENDIMENTO]' });
|
|
116
|
+
}
|
|
117
|
+
if (pct >= 50 && !fired.has(50)) {
|
|
118
|
+
fired.add(50);
|
|
119
|
+
cdpTrack.track('video_50', { contentName: 'Tour Virtual — [NOME DO EMPREENDIMENTO]' });
|
|
120
|
+
}
|
|
121
|
+
if (pct >= 75 && !fired.has(75)) {
|
|
122
|
+
fired.add(75);
|
|
123
|
+
cdpTrack.track('video_75', { contentName: 'Tour Virtual — [NOME DO EMPREENDIMENTO]' });
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
video.addEventListener('ended', () => {
|
|
127
|
+
cdpTrack.track('video_complete', { contentName: 'Tour Virtual — [NOME DO EMPREENDIMENTO]' });
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Para YouTube embed (via YouTube API):
|
|
132
|
+
// Adicionar ?enablejsapi=1 na URL do iframe e usar onStateChange
|
|
133
|
+
// Ver: https://developers.google.com/youtube/iframe_api_reference
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
### 2.5 CustomizeProduct — Simulador de Financiamento
|
|
139
|
+
```javascript
|
|
140
|
+
// Dispara quando usuário interage com o simulador de parcelas/FGTS/Caixa
|
|
141
|
+
const simulador = document.querySelector(
|
|
142
|
+
'#simulador, .simulador-financiamento, [data-section="simulacao"], form.simulador'
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
if (simulador) {
|
|
146
|
+
// Dispara ao 1º interact (foco em qualquer campo do simulador)
|
|
147
|
+
let simuladorFired = false;
|
|
148
|
+
simulador.addEventListener('focusin', () => {
|
|
149
|
+
if (simuladorFired) return;
|
|
150
|
+
simuladorFired = true;
|
|
151
|
+
cdpTrack.track('CustomizeProduct', {
|
|
152
|
+
contentName: 'Simulador de Financiamento — [NOME DO EMPREENDIMENTO]',
|
|
153
|
+
contentCategory: 'imovel',
|
|
154
|
+
funnel_stage: 'financing_simulation',
|
|
155
|
+
intentionLevel: 'comprador',
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Dispara também ao clicar em "Simular" / "Calcular"
|
|
160
|
+
simulador.querySelector('button[type="submit"], .btn-simular, .btn-calcular')?.addEventListener('click', () => {
|
|
161
|
+
const valorImovel = simulador.querySelector('input[name="valor"], #valor-imovel')?.value;
|
|
162
|
+
cdpTrack.track('CustomizeProduct', {
|
|
163
|
+
contentName: 'Simulação Concluída — [NOME DO EMPREENDIMENTO]',
|
|
164
|
+
contentCategory: 'imovel',
|
|
165
|
+
funnel_stage: 'financing_simulation',
|
|
166
|
+
intentionLevel: 'comprador',
|
|
167
|
+
value: valorImovel ? parseFloat(valorImovel.replace(/\D/g, '')) : undefined,
|
|
168
|
+
currency: 'BRL',
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### 2.6 AddToWishlist — Favoritar Imóvel
|
|
177
|
+
```javascript
|
|
178
|
+
// Dispara quando usuário clica em favoritar / ícone de coração
|
|
179
|
+
document.querySelectorAll('.btn-favoritar, .icon-heart, [data-action="favoritar"], .favorito').forEach(el => {
|
|
180
|
+
el.addEventListener('click', () => {
|
|
181
|
+
cdpTrack.track('AddToWishlist', {
|
|
182
|
+
contentName: '[NOME DO EMPREENDIMENTO]',
|
|
183
|
+
contentCategory: 'imovel',
|
|
184
|
+
funnel_stage: 'wishlist',
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
### 2.7 Contact — WhatsApp / Telefone
|
|
193
|
+
```javascript
|
|
194
|
+
// WhatsApp
|
|
195
|
+
document.querySelectorAll('a[href*="wa.me"], a[href*="whatsapp.com"], .btn-whatsapp').forEach(el => {
|
|
196
|
+
el.addEventListener('click', () => {
|
|
197
|
+
cdpTrack.track('Contact', {
|
|
198
|
+
contentName: 'WhatsApp — [NOME DO EMPREENDIMENTO]',
|
|
199
|
+
contentCategory: 'imovel_whatsapp',
|
|
200
|
+
funnel_stage: 'whatsapp_click',
|
|
201
|
+
intentionLevel: 'comprador',
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Telefone
|
|
207
|
+
document.querySelectorAll('a[href^="tel:"], .btn-ligar, .btn-telefone').forEach(el => {
|
|
208
|
+
el.addEventListener('click', () => {
|
|
209
|
+
cdpTrack.track('Contact', {
|
|
210
|
+
contentName: 'Telefone — [NOME DO EMPREENDIMENTO]',
|
|
211
|
+
contentCategory: 'imovel_telefone',
|
|
212
|
+
funnel_stage: 'phone_click',
|
|
213
|
+
intentionLevel: 'comprador',
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
### 2.8 Schedule — Calendário de Agendamento de Visita
|
|
222
|
+
```javascript
|
|
223
|
+
// Dispara quando usuário CONFIRMA o agendamento (não ao abrir o calendário)
|
|
224
|
+
// Adaptar ao provider: Calendly, Google Calendar, formulário próprio
|
|
225
|
+
|
|
226
|
+
// Exemplo com Calendly:
|
|
227
|
+
window.addEventListener('message', (e) => {
|
|
228
|
+
if (e.data?.event === 'calendly.event_scheduled') {
|
|
229
|
+
cdpTrack.track('Schedule', {
|
|
230
|
+
contentName: 'Visita Agendada — [NOME DO EMPREENDIMENTO]',
|
|
231
|
+
contentCategory: 'imovel',
|
|
232
|
+
funnel_stage: 'schedule_confirmed',
|
|
233
|
+
intentionLevel: 'comprador',
|
|
234
|
+
// Dados do lead do Calendly (se disponíveis via payload):
|
|
235
|
+
email: e.data?.payload?.invitee?.email,
|
|
236
|
+
firstName: e.data?.payload?.invitee?.first_name,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// Exemplo com formulário próprio de agendamento:
|
|
242
|
+
document.querySelector('#form-agendamento')?.addEventListener('submit', async (e) => {
|
|
243
|
+
e.preventDefault();
|
|
244
|
+
const data = new FormData(e.target);
|
|
245
|
+
await cdpTrack.track('Schedule', {
|
|
246
|
+
contentName: 'Visita Agendada — [NOME DO EMPREENDIMENTO]',
|
|
247
|
+
contentCategory: 'imovel',
|
|
248
|
+
funnel_stage: 'schedule_confirmed',
|
|
249
|
+
intentionLevel: 'comprador',
|
|
250
|
+
email: data.get('email'),
|
|
251
|
+
phone: data.get('phone'),
|
|
252
|
+
firstName: data.get('nome')?.split(' ')[0],
|
|
253
|
+
});
|
|
254
|
+
e.target.submit();
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
### 2.9 Lead — Formulário Principal de Interesse
|
|
261
|
+
```javascript
|
|
262
|
+
document.querySelector('#form-interesse, #form-lead, form.form-contato')?.addEventListener('submit', async (e) => {
|
|
263
|
+
e.preventDefault();
|
|
264
|
+
|
|
265
|
+
await cdpTrack.track('Lead', {
|
|
266
|
+
// PII — enviados hasheados pelo Worker
|
|
267
|
+
email: e.target.email?.value?.trim(),
|
|
268
|
+
phone: e.target.phone?.value?.trim() || e.target.telefone?.value?.trim(),
|
|
269
|
+
firstName: e.target.nome?.value?.split(' ')[0]?.trim(),
|
|
270
|
+
lastName: e.target.nome?.value?.split(' ').slice(1).join(' ')?.trim(),
|
|
271
|
+
|
|
272
|
+
// Contexto
|
|
273
|
+
contentName: '[NOME DO EMPREENDIMENTO]',
|
|
274
|
+
contentCategory: 'imovel',
|
|
275
|
+
intentionLevel: 'comprador',
|
|
276
|
+
funnel_stage: 'lead_form',
|
|
277
|
+
|
|
278
|
+
// UTMs capturados pelo SDK automaticamente
|
|
279
|
+
// Coordenadas do imóvel para distância geoespacial no Worker:
|
|
280
|
+
property_lat: -23.5505,
|
|
281
|
+
property_lng: -46.6333,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// Redirecionar para obrigado
|
|
285
|
+
window.location.href = '/obrigado';
|
|
286
|
+
});
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 📊 LTV por Evento — O que o Worker calcula
|
|
292
|
+
|
|
293
|
+
| Evento | Bonus LTV Score | Multiplicador Valor |
|
|
294
|
+
|---|---|---|
|
|
295
|
+
| `Lead` (utm_source=facebook, intention=comprador) | ~65–80 pts | 3.5× → **High** |
|
|
296
|
+
| `CustomizeProduct` | +15 pts automático | Score sobe para High |
|
|
297
|
+
| `FindLocation` | +10 pts automático | Puxa Medium → High |
|
|
298
|
+
| `AddToWishlist` | +8 pts automático | Sinal de retargeting |
|
|
299
|
+
| `Schedule` (visita confirmada) | intention=comprador → +20 pts | Máximo High |
|
|
300
|
+
| `Contact` (WhatsApp) | Sem LTV (evento de sinal) | — |
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## 🔄 FLUXO COMPLETO DO LEAD IMOBILIÁRIO
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
Usuário chega na landing
|
|
308
|
+
│
|
|
309
|
+
├─ PageView → sinal de alcance
|
|
310
|
+
├─ ViewContent (galeria) → interesse qualificado
|
|
311
|
+
├─ video_50 (tour) → engajamento profundo
|
|
312
|
+
├─ FindLocation (mapa) → intenção de visita física (+10 LTV)
|
|
313
|
+
├─ CustomizeProduct (simulador) → intenção máxima (+15 LTV)
|
|
314
|
+
├─ Contact (WhatsApp) → ação de contato
|
|
315
|
+
├─ Schedule (agendamento) → visita confirmada
|
|
316
|
+
└─ Lead (formulário) → conversão principal
|
|
317
|
+
│
|
|
318
|
+
▼
|
|
319
|
+
Worker: LTV score ~75-90 → High → valor 3.5× injetado
|
|
320
|
+
│
|
|
321
|
+
▼
|
|
322
|
+
Meta CAPI + GA4 + TikTok recebem Lead com value=R$689
|
|
323
|
+
│
|
|
324
|
+
▼
|
|
325
|
+
Algoritmo de Meta aprende a buscar mais leads de alto valor
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## 📋 CHECKLIST DE IMPLEMENTAÇÃO
|
|
331
|
+
|
|
332
|
+
- [ ] SDK `cdpTrack.js` carregando no `<head>`
|
|
333
|
+
- [ ] `PageView` disparando (automático)
|
|
334
|
+
- [ ] `ViewContent` na galeria
|
|
335
|
+
- [ ] `FindLocation` no mapa e botão "Como chegar"
|
|
336
|
+
- [ ] Vídeo/tour instrumentado (`video_25`, `video_75`, `video_complete`)
|
|
337
|
+
- [ ] `CustomizeProduct` no simulador de financiamento
|
|
338
|
+
- [ ] `AddToWishlist` no botão de favoritar
|
|
339
|
+
- [ ] `Contact` nos botões de WhatsApp e telefone
|
|
340
|
+
- [ ] `Schedule` no calendário (Calendly ou formulário próprio)
|
|
341
|
+
- [ ] `Lead` no formulário principal com PII e `property_lat/lng`
|
|
342
|
+
- [ ] Verificar `/health` retornando `d1: ok, kv: ok, ai: ok`
|
|
343
|
+
- [ ] Testar evento `Lead` no Meta Events Manager → Test Events
|
|
344
|
+
- [ ] Confirmar LTV na resposta JSON do `/track` (`class: "High"`)
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# Modelo: Multi-Step Checkout
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> ✅ **STATUS: Quantum Tier (Server-Side Completo)**
|
|
4
4
|
>
|
|
5
|
-
>
|
|
6
|
-
>
|
|
7
|
-
> Até a migração ser concluída, use `checkout-proprio.md` como referência de arquitetura Quantum Tier e adapte as etapas manualmente.
|
|
5
|
+
> Checkout multi-etapa com rastreamento 100% Cloudflare Native (Workers + D1).
|
|
6
|
+
> Inclui enriquecimento progressivo de identidade, deduplicação e dispatch server-side para Meta CAPI v22.0, GA4 MP e TikTok API v1.3.
|
|
8
7
|
|
|
9
8
|
Checkout próprio dividido em múltiplas etapas: dados pessoais → endereço → pagamento → confirmação.
|
|
10
9
|
|
|
@@ -1,144 +1,144 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pinterest Conversions API Server Template — CDP Edge Quantum Tier
|
|
3
|
-
*
|
|
4
|
-
* Este template contém a função de envio para a Conversions API do Pinterest
|
|
5
|
-
* Uso: Incluir no worker.js gerado pelo Server Tracking Agent
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Função principal de envio para Pinterest Conversions API
|
|
10
|
-
* @param {Object} env - Variáveis de ambiente do Cloudflare Worker
|
|
11
|
-
* @param {Object} eventData - Dados do evento a ser enviado
|
|
12
|
-
* @returns {Promise<Object>} - Resposta da API
|
|
13
|
-
*/
|
|
14
|
-
export async function sendPinterestApi(env, eventData) {
|
|
15
|
-
const {
|
|
16
|
-
email, phone, userId, clientIp, userAgent, pageUrl,
|
|
17
|
-
eventId, value, currency, orderId, productName, productId
|
|
18
|
-
} = eventData;
|
|
19
|
-
|
|
20
|
-
// Verificar se as credenciais estão configuradas
|
|
21
|
-
if (!env.PINTEREST_ACCESS_TOKEN || !env.PINTEREST_AD_ACCOUNT_ID) {
|
|
22
|
-
console.warn('Pinterest Conversions API: Credenciais não configuradas');
|
|
23
|
-
return { success: false, error: 'MISSING_CREDENTIALS' };
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Função de hash SHA-256
|
|
27
|
-
async function sha256(str) {
|
|
28
|
-
if (!str) return undefined;
|
|
29
|
-
const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(str.toLowerCase().trim()));
|
|
30
|
-
return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Normalizar evento — Pinterest usa nomes específicos
|
|
34
|
-
const pinterestEventMap = {
|
|
35
|
-
'PageView': 'pagevisit',
|
|
36
|
-
'Lead': 'lead',
|
|
37
|
-
'Purchase': 'checkout',
|
|
38
|
-
'AddToCart': 'addtocart',
|
|
39
|
-
'InitiateCheckout': 'checkout',
|
|
40
|
-
'ViewContent': 'pagevisit',
|
|
41
|
-
'CompleteRegistration': 'signup',
|
|
42
|
-
'Search': 'search',
|
|
43
|
-
};
|
|
44
|
-
const pinterestEvent = pinterestEventMap[eventName] || 'custom';
|
|
45
|
-
|
|
46
|
-
// User data com hashing
|
|
47
|
-
const userData = {};
|
|
48
|
-
if (email) userData.em = [await sha256(email)];
|
|
49
|
-
if (phone) userData.ph = [await sha256(phone.replace(/\D/g, ''))];
|
|
50
|
-
if (userId) userData.external_id = [await sha256(userId)];
|
|
51
|
-
if (clientIp) userData.client_ip_address = clientIp; // sem hash
|
|
52
|
-
if (userAgent) userData.client_user_agent = userAgent; // sem hash
|
|
53
|
-
|
|
54
|
-
// Payload da Conversions API
|
|
55
|
-
const payload = {
|
|
56
|
-
data: [{
|
|
57
|
-
event_name: pinterestEvent,
|
|
58
|
-
action_source: 'web',
|
|
59
|
-
event_time: Math.floor(Date.now() / 1000),
|
|
60
|
-
event_id: eventId, // deduplicação com browser tag
|
|
61
|
-
event_source_url: pageUrl || '',
|
|
62
|
-
user_data: userData,
|
|
63
|
-
custom_data: {
|
|
64
|
-
currency: currency || 'BRL',
|
|
65
|
-
value: value ? String(value) : '0',
|
|
66
|
-
order_id: orderId || undefined,
|
|
67
|
-
content_ids: productId ? [productId] : undefined,
|
|
68
|
-
content_name: productName || undefined,
|
|
69
|
-
content_type: 'product',
|
|
70
|
-
},
|
|
71
|
-
// Para lead: adicionar lead_type
|
|
72
|
-
...(eventName === 'Lead' ? { custom_data: { ...{}, lead_type: 'Newsletter' } } : {}),
|
|
73
|
-
}],
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
const resp = await fetch(
|
|
78
|
-
`https://api.pinterest.com/v5/ad_accounts/${env.PINTEREST_AD_ACCOUNT_ID}/events`,
|
|
79
|
-
{
|
|
80
|
-
method: 'POST',
|
|
81
|
-
headers: {
|
|
82
|
-
'Content-Type': 'application/json',
|
|
83
|
-
'Authorization': `Bearer ${env.PINTEREST_ACCESS_TOKEN}`,
|
|
84
|
-
},
|
|
85
|
-
body: JSON.stringify(payload),
|
|
86
|
-
}
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
const result = await resp.json();
|
|
90
|
-
|
|
91
|
-
// Resposta de sucesso: { num_events_received: 1, num_events_processed: 1 }
|
|
92
|
-
if (result.num_events_received === 1 && result.num_events_processed === 1) {
|
|
93
|
-
return { success: true, result };
|
|
94
|
-
} else {
|
|
95
|
-
return { success: false, error: 'API_ERROR', result };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
} catch (error) {
|
|
99
|
-
console.error('Pinterest Conversions API Error:', error);
|
|
100
|
-
return { success: false, error: error.message };
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Função de Enhanced Match — re-inicializa o pixel com dados hasheados
|
|
106
|
-
* @param {string} email - Email do usuário (opcional)
|
|
107
|
-
* @param {string} phone - Telefone do usuário (opcional)
|
|
108
|
-
*/
|
|
109
|
-
export async function reinitPinterestWithEnhancedMatch(email, phone) {
|
|
110
|
-
if (!email && !phone) return;
|
|
111
|
-
|
|
112
|
-
const hashedEmail = email ? await sha256Email(email) : '';
|
|
113
|
-
const hashedPhone = phone ? await sha256Phone(phone.replace(/\D/g, '')) : '';
|
|
114
|
-
|
|
115
|
-
// Re-load com dados hasheados para Enhanced Match
|
|
116
|
-
if (typeof pintrk !== 'undefined') {
|
|
117
|
-
pintrk('load', '{PINTEREST_TAG_ID}', {
|
|
118
|
-
em: hashedEmail,
|
|
119
|
-
ph: hashedPhone
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Funções de hash para Enhanced Match no browser
|
|
126
|
-
*/
|
|
127
|
-
export async function sha256Email(str) {
|
|
128
|
-
if (!str) return '';
|
|
129
|
-
const normalized = str.toLowerCase().trim();
|
|
130
|
-
const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(normalized));
|
|
131
|
-
return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export async function sha256Phone(str) {
|
|
135
|
-
if (!str) return '';
|
|
136
|
-
const normalized = str.replace(/\D/g, '').toLowerCase().trim();
|
|
137
|
-
const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(normalized));
|
|
138
|
-
return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export default {
|
|
142
|
-
sendPinterestApi,
|
|
143
|
-
reinitPinterestWithEnhancedMatch
|
|
144
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Pinterest Conversions API Server Template — CDP Edge Quantum Tier
|
|
3
|
+
*
|
|
4
|
+
* Este template contém a função de envio para a Conversions API do Pinterest
|
|
5
|
+
* Uso: Incluir no worker.js gerado pelo Server Tracking Agent
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Função principal de envio para Pinterest Conversions API
|
|
10
|
+
* @param {Object} env - Variáveis de ambiente do Cloudflare Worker
|
|
11
|
+
* @param {Object} eventData - Dados do evento a ser enviado
|
|
12
|
+
* @returns {Promise<Object>} - Resposta da API
|
|
13
|
+
*/
|
|
14
|
+
export async function sendPinterestApi(env, eventData) {
|
|
15
|
+
const {
|
|
16
|
+
email, phone, userId, clientIp, userAgent, pageUrl,
|
|
17
|
+
eventId, value, currency, orderId, productName, productId
|
|
18
|
+
} = eventData;
|
|
19
|
+
|
|
20
|
+
// Verificar se as credenciais estão configuradas
|
|
21
|
+
if (!env.PINTEREST_ACCESS_TOKEN || !env.PINTEREST_AD_ACCOUNT_ID) {
|
|
22
|
+
console.warn('Pinterest Conversions API: Credenciais não configuradas');
|
|
23
|
+
return { success: false, error: 'MISSING_CREDENTIALS' };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Função de hash SHA-256
|
|
27
|
+
async function sha256(str) {
|
|
28
|
+
if (!str) return undefined;
|
|
29
|
+
const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(str.toLowerCase().trim()));
|
|
30
|
+
return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Normalizar evento — Pinterest usa nomes específicos
|
|
34
|
+
const pinterestEventMap = {
|
|
35
|
+
'PageView': 'pagevisit',
|
|
36
|
+
'Lead': 'lead',
|
|
37
|
+
'Purchase': 'checkout',
|
|
38
|
+
'AddToCart': 'addtocart',
|
|
39
|
+
'InitiateCheckout': 'checkout',
|
|
40
|
+
'ViewContent': 'pagevisit',
|
|
41
|
+
'CompleteRegistration': 'signup',
|
|
42
|
+
'Search': 'search',
|
|
43
|
+
};
|
|
44
|
+
const pinterestEvent = pinterestEventMap[eventName] || 'custom';
|
|
45
|
+
|
|
46
|
+
// User data com hashing
|
|
47
|
+
const userData = {};
|
|
48
|
+
if (email) userData.em = [await sha256(email)];
|
|
49
|
+
if (phone) userData.ph = [await sha256(phone.replace(/\D/g, ''))];
|
|
50
|
+
if (userId) userData.external_id = [await sha256(userId)];
|
|
51
|
+
if (clientIp) userData.client_ip_address = clientIp; // sem hash
|
|
52
|
+
if (userAgent) userData.client_user_agent = userAgent; // sem hash
|
|
53
|
+
|
|
54
|
+
// Payload da Conversions API
|
|
55
|
+
const payload = {
|
|
56
|
+
data: [{
|
|
57
|
+
event_name: pinterestEvent,
|
|
58
|
+
action_source: 'web',
|
|
59
|
+
event_time: Math.floor(Date.now() / 1000),
|
|
60
|
+
event_id: eventId, // deduplicação com browser tag
|
|
61
|
+
event_source_url: pageUrl || '',
|
|
62
|
+
user_data: userData,
|
|
63
|
+
custom_data: {
|
|
64
|
+
currency: currency || 'BRL',
|
|
65
|
+
value: value ? String(value) : '0',
|
|
66
|
+
order_id: orderId || undefined,
|
|
67
|
+
content_ids: productId ? [productId] : undefined,
|
|
68
|
+
content_name: productName || undefined,
|
|
69
|
+
content_type: 'product',
|
|
70
|
+
},
|
|
71
|
+
// Para lead: adicionar lead_type
|
|
72
|
+
...(eventName === 'Lead' ? { custom_data: { ...{}, lead_type: 'Newsletter' } } : {}),
|
|
73
|
+
}],
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const resp = await fetch(
|
|
78
|
+
`https://api.pinterest.com/v5/ad_accounts/${env.PINTEREST_AD_ACCOUNT_ID}/events`,
|
|
79
|
+
{
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: {
|
|
82
|
+
'Content-Type': 'application/json',
|
|
83
|
+
'Authorization': `Bearer ${env.PINTEREST_ACCESS_TOKEN}`,
|
|
84
|
+
},
|
|
85
|
+
body: JSON.stringify(payload),
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const result = await resp.json();
|
|
90
|
+
|
|
91
|
+
// Resposta de sucesso: { num_events_received: 1, num_events_processed: 1 }
|
|
92
|
+
if (result.num_events_received === 1 && result.num_events_processed === 1) {
|
|
93
|
+
return { success: true, result };
|
|
94
|
+
} else {
|
|
95
|
+
return { success: false, error: 'API_ERROR', result };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.error('Pinterest Conversions API Error:', error);
|
|
100
|
+
return { success: false, error: error.message };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Função de Enhanced Match — re-inicializa o pixel com dados hasheados
|
|
106
|
+
* @param {string} email - Email do usuário (opcional)
|
|
107
|
+
* @param {string} phone - Telefone do usuário (opcional)
|
|
108
|
+
*/
|
|
109
|
+
export async function reinitPinterestWithEnhancedMatch(email, phone) {
|
|
110
|
+
if (!email && !phone) return;
|
|
111
|
+
|
|
112
|
+
const hashedEmail = email ? await sha256Email(email) : '';
|
|
113
|
+
const hashedPhone = phone ? await sha256Phone(phone.replace(/\D/g, '')) : '';
|
|
114
|
+
|
|
115
|
+
// Re-load com dados hasheados para Enhanced Match
|
|
116
|
+
if (typeof pintrk !== 'undefined') {
|
|
117
|
+
pintrk('load', '{PINTEREST_TAG_ID}', {
|
|
118
|
+
em: hashedEmail,
|
|
119
|
+
ph: hashedPhone
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Funções de hash para Enhanced Match no browser
|
|
126
|
+
*/
|
|
127
|
+
export async function sha256Email(str) {
|
|
128
|
+
if (!str) return '';
|
|
129
|
+
const normalized = str.toLowerCase().trim();
|
|
130
|
+
const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(normalized));
|
|
131
|
+
return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export async function sha256Phone(str) {
|
|
135
|
+
if (!str) return '';
|
|
136
|
+
const normalized = str.replace(/\D/g, '').toLowerCase().trim();
|
|
137
|
+
const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(normalized));
|
|
138
|
+
return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export default {
|
|
142
|
+
sendPinterestApi,
|
|
143
|
+
reinitPinterestWithEnhancedMatch
|
|
144
|
+
};
|