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.
- package/README.md +367 -0
- package/bin/cdp-edge.js +61 -0
- package/contracts/api-versions.json +368 -0
- package/dist/commands/analyze.js +52 -0
- package/dist/commands/infra.js +54 -0
- package/dist/commands/install.js +168 -0
- package/dist/commands/server.js +174 -0
- package/dist/commands/setup.js +123 -0
- package/dist/commands/validate.js +84 -0
- package/dist/index.js +12 -0
- package/docs/CI-CD-SETUP.md +217 -0
- package/docs/PixelBuilder-Documentacao-Completa (2).docx +0 -0
- package/docs/events-reference.md +359 -0
- package/docs/installation.md +155 -0
- package/docs/quick-start.md +185 -0
- package/docs/sdk-reference.md +371 -0
- package/docs/whatsapp-ctwa.md +209 -0
- package/extracted-skill/tracking-events-generator/INDEX.md +94 -0
- package/extracted-skill/tracking-events-generator/INSTALACAO-CDPEDGE.md +58 -0
- package/extracted-skill/tracking-events-generator/INTEGRACAO-COMPLETA.md +594 -0
- package/extracted-skill/tracking-events-generator/MELHORIAS-IMPLEMENTADAS.md +412 -0
- package/extracted-skill/tracking-events-generator/Premium-Tracking-Intelligence-Resumo.md +333 -0
- package/extracted-skill/tracking-events-generator/SKILL.md +257 -0
- package/extracted-skill/tracking-events-generator/advanced-matching.js +364 -0
- package/extracted-skill/tracking-events-generator/agents/ab-testing-agent.md +54 -0
- package/extracted-skill/tracking-events-generator/agents/attribution-agent.md +1304 -0
- package/extracted-skill/tracking-events-generator/agents/bing-agent.md +76 -0
- package/extracted-skill/tracking-events-generator/agents/browser-tracking.md +264 -0
- package/extracted-skill/tracking-events-generator/agents/code-guardian-agent.md +149 -0
- package/extracted-skill/tracking-events-generator/agents/compliance-agent.md +2077 -0
- package/extracted-skill/tracking-events-generator/agents/crm-integration-agent.md +1419 -0
- package/extracted-skill/tracking-events-generator/agents/dashboard-agent.md +456 -0
- package/extracted-skill/tracking-events-generator/agents/database-agent.md +667 -0
- package/extracted-skill/tracking-events-generator/agents/debug-agent.md +1455 -0
- package/extracted-skill/tracking-events-generator/agents/domain-setup-agent.md +224 -0
- package/extracted-skill/tracking-events-generator/agents/email-agent.md +61 -0
- package/extracted-skill/tracking-events-generator/agents/fingerprint-agent.md +52 -0
- package/extracted-skill/tracking-events-generator/agents/google-agent.md +109 -0
- package/extracted-skill/tracking-events-generator/agents/intelligence-agent.md +365 -0
- package/extracted-skill/tracking-events-generator/agents/intelligence-scheduling.md +643 -0
- package/extracted-skill/tracking-events-generator/agents/linkedin-agent.md +62 -0
- package/extracted-skill/tracking-events-generator/agents/localization-agent.md +55 -0
- package/extracted-skill/tracking-events-generator/agents/ltv-predictor-agent.md +59 -0
- package/extracted-skill/tracking-events-generator/agents/master-feedback-loop.md +900 -0
- package/extracted-skill/tracking-events-generator/agents/master-orchestrator.md +1922 -0
- package/extracted-skill/tracking-events-generator/agents/memory-agent.json +109 -0
- package/extracted-skill/tracking-events-generator/agents/memory-agent.md +703 -0
- package/extracted-skill/tracking-events-generator/agents/meta-agent.md +110 -0
- package/extracted-skill/tracking-events-generator/agents/page-analyzer.md +255 -0
- package/extracted-skill/tracking-events-generator/agents/performance-agent.md +1157 -0
- package/extracted-skill/tracking-events-generator/agents/performance-optimization-agent.md +1432 -0
- package/extracted-skill/tracking-events-generator/agents/pinterest-agent.md +310 -0
- package/extracted-skill/tracking-events-generator/agents/premium-tracking-intelligence-agent.md +849 -0
- package/extracted-skill/tracking-events-generator/agents/r2-setup-agent.md +250 -0
- package/extracted-skill/tracking-events-generator/agents/reddit-agent.md +313 -0
- package/extracted-skill/tracking-events-generator/agents/security-enterprise-agent.md +1752 -0
- package/extracted-skill/tracking-events-generator/agents/server-tracking.md +1188 -0
- package/extracted-skill/tracking-events-generator/agents/spotify-agent.md +383 -0
- package/extracted-skill/tracking-events-generator/agents/tiktok-agent.md +111 -0
- package/extracted-skill/tracking-events-generator/agents/tracking-plan-agent.md +364 -0
- package/extracted-skill/tracking-events-generator/agents/validator-agent.md +267 -0
- package/extracted-skill/tracking-events-generator/agents/webhook-agent.md +69 -0
- package/extracted-skill/tracking-events-generator/agents/whatsapp-agent.md +76 -0
- package/extracted-skill/tracking-events-generator/agents/whatsapp-ctwa-setup-agent.md +699 -0
- package/extracted-skill/tracking-events-generator/agents/youtube-agent.md +422 -0
- package/extracted-skill/tracking-events-generator/anti-blocking.js +285 -0
- package/extracted-skill/tracking-events-generator/cdpTrack.js +641 -0
- package/extracted-skill/tracking-events-generator/contracts/api-versions.json +368 -0
- package/extracted-skill/tracking-events-generator/docs/guia-cloudflare-iniciante.md +107 -0
- package/extracted-skill/tracking-events-generator/engagement-scoring.js +226 -0
- package/extracted-skill/tracking-events-generator/evals/evals.json +235 -0
- package/extracted-skill/tracking-events-generator/integration-test.js +497 -0
- package/extracted-skill/tracking-events-generator/knowledge-base.md +2894 -0
- package/extracted-skill/tracking-events-generator/micro-events.js +992 -0
- package/extracted-skill/tracking-events-generator/models/captura-de-lead.md +78 -0
- package/extracted-skill/tracking-events-generator/models/captura-lead-evento-externo.md +99 -0
- package/extracted-skill/tracking-events-generator/models/checkout-proprio.md +111 -0
- package/extracted-skill/tracking-events-generator/models/multi-step-checkout.md +672 -0
- package/extracted-skill/tracking-events-generator/models/pagina-obrigado.md +55 -0
- package/extracted-skill/tracking-events-generator/models/pinterest/conversions-api-template.js +144 -0
- package/extracted-skill/tracking-events-generator/models/pinterest/event-mappings.json +48 -0
- package/extracted-skill/tracking-events-generator/models/pinterest/tag-template.js +28 -0
- package/extracted-skill/tracking-events-generator/models/quiz-funnel.md +68 -0
- package/extracted-skill/tracking-events-generator/models/reddit/conversions-api-template.js +205 -0
- package/extracted-skill/tracking-events-generator/models/reddit/event-mappings.json +56 -0
- package/extracted-skill/tracking-events-generator/models/reddit/pixel-template.js +19 -0
- package/extracted-skill/tracking-events-generator/models/scenarios/behavior-engine.js +425 -0
- package/extracted-skill/tracking-events-generator/models/scenarios/real-estate-logic.md +50 -0
- package/extracted-skill/tracking-events-generator/models/scenarios/sales-page-logic.md +50 -0
- package/extracted-skill/tracking-events-generator/models/trafego-direto.md +582 -0
- package/extracted-skill/tracking-events-generator/models/webinar-registration.md +63 -0
- package/extracted-skill/tracking-events-generator/tracking.config.js +46 -0
- package/extracted-skill/tracking-events-generator/walkthrough.md +26 -0
- package/package.json +75 -0
- package/server-edge-tracker/INSTALAR.md +328 -0
- package/server-edge-tracker/migrate-new-db.sql +137 -0
- package/server-edge-tracker/migrate-v2.sql +16 -0
- package/server-edge-tracker/migrate-v3.sql +6 -0
- package/server-edge-tracker/migrate-v4.sql +18 -0
- package/server-edge-tracker/migrate-v5.sql +17 -0
- package/server-edge-tracker/migrate-v6.sql +24 -0
- package/server-edge-tracker/migrate.sql +111 -0
- package/server-edge-tracker/schema.sql +265 -0
- package/server-edge-tracker/worker.js +2574 -0
- package/server-edge-tracker/wrangler.toml +85 -0
- package/templates/afiliado-sem-landing.md +312 -0
- package/templates/captura-de-lead.md +78 -0
- package/templates/captura-lead-evento-externo.md +99 -0
- package/templates/checkout-proprio.md +111 -0
- package/templates/install/.claude/commands/cdp.md +1 -0
- package/templates/install/CLAUDE.md +65 -0
- package/templates/linkedin/tag-template.js +46 -0
- package/templates/multi-step-checkout.md +673 -0
- package/templates/pagina-obrigado.md +55 -0
- package/templates/pinterest/conversions-api-template.js +144 -0
- package/templates/pinterest/event-mappings.json +48 -0
- package/templates/pinterest/tag-template.js +28 -0
- package/templates/quiz-funnel.md +68 -0
- package/templates/reddit/conversions-api-template.js +205 -0
- package/templates/reddit/event-mappings.json +56 -0
- package/templates/reddit/pixel-template.js +46 -0
- package/templates/scenarios/behavior-engine.js +402 -0
- package/templates/scenarios/real-estate-logic.md +50 -0
- package/templates/scenarios/sales-page-logic.md +50 -0
- package/templates/spotify/pixel-template.js +46 -0
- package/templates/trafego-direto.md +582 -0
- package/templates/vsl-page.md +292 -0
- package/templates/webinar-registration.md +63 -0
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CDP Edge Human-Behavior Engine (Quantum Tier)
|
|
3
|
+
* Responsável por capturar micro-interações e intenção real.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const BehaviorEngine = {
|
|
7
|
+
config: {
|
|
8
|
+
rageClickThreshold: 3,
|
|
9
|
+
rageClickTime: 700, // ms
|
|
10
|
+
idleThreshold: 60000, // 60s
|
|
11
|
+
scoreThresholds: {
|
|
12
|
+
engaged: 40,
|
|
13
|
+
highIntent: 80
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
state: {
|
|
18
|
+
clickHistory: [],
|
|
19
|
+
startTime: Date.now(),
|
|
20
|
+
lastActivity: Date.now(),
|
|
21
|
+
lastPulse: Date.now(),
|
|
22
|
+
isIdle: false,
|
|
23
|
+
formStartTime: {},
|
|
24
|
+
userScore: 0,
|
|
25
|
+
firedScoreEvents: new Set(),
|
|
26
|
+
abVariant: null,
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
init() {
|
|
30
|
+
this.setupRageClicks();
|
|
31
|
+
this.setupVisibility();
|
|
32
|
+
this.setupHeartbeat();
|
|
33
|
+
this.setupScroll();
|
|
34
|
+
this.setupVideoTracking();
|
|
35
|
+
this.setupFormAnalytics();
|
|
36
|
+
this.setupFormAbandonment();
|
|
37
|
+
this.setupCopyPaste();
|
|
38
|
+
this.setupExitIntent();
|
|
39
|
+
this.setupOutboundLinks();
|
|
40
|
+
this.setupErrorTracking();
|
|
41
|
+
this.setupIdleDetection();
|
|
42
|
+
this.setupScoring();
|
|
43
|
+
this.setupABTesting();
|
|
44
|
+
console.log('[CDP Edge] Enterprise Behavior Engine Initialized');
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
// 0.1 A/B Testing (Mode 1 - Edge Sync)
|
|
48
|
+
setupABTesting() {
|
|
49
|
+
// Busca variante no Cookie ou URL (Modo 1)
|
|
50
|
+
const getCookie = (name) => {
|
|
51
|
+
const value = `; ${document.cookie}`;
|
|
52
|
+
const parts = value.split(`; ${name}=`);
|
|
53
|
+
if (parts.length === 2) return parts.pop().split(';').shift();
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
57
|
+
this.state.abVariant = urlParams.get('cdp_variant') || getCookie('cdp_ab_variant') || 'original';
|
|
58
|
+
|
|
59
|
+
console.log(`[CDP Edge] A/B Variant Detected: ${this.state.abVariant}`);
|
|
60
|
+
|
|
61
|
+
// Intercepta o cdpTrack.track para injetar a variante globalmente
|
|
62
|
+
const originalTrack = cdpTrack.track;
|
|
63
|
+
cdpTrack.track = (eventName, eventParams = {}) => {
|
|
64
|
+
const enrichedParams = {
|
|
65
|
+
...eventParams,
|
|
66
|
+
ab_test_variant: this.state.abVariant,
|
|
67
|
+
user_score: this.state.userScore
|
|
68
|
+
};
|
|
69
|
+
return originalTrack.apply(cdpTrack, [eventName, enrichedParams]);
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
// 0. Scoring Engine (Internal)
|
|
74
|
+
setupScoring() {
|
|
75
|
+
console.log('[CDP Edge] Scoring Engine Online');
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
addScore(points, reason) {
|
|
79
|
+
this.state.userScore = Math.min(100, Math.max(0, this.state.userScore + points));
|
|
80
|
+
console.log(`[CDP Edge] Score Update: +${points} (${reason}) | Total: ${this.state.userScore}`);
|
|
81
|
+
|
|
82
|
+
// Gatilhos de Plataforma
|
|
83
|
+
if (this.state.userScore >= this.config.scoreThresholds.highIntent && !this.state.firedScoreEvents.has('highIntent')) {
|
|
84
|
+
this.state.firedScoreEvents.add('highIntent');
|
|
85
|
+
cdpTrack.track('High_Intent_Lead', { score: this.state.userScore, meta_intensity: 'high' });
|
|
86
|
+
} else if (this.state.userScore >= this.config.scoreThresholds.engaged && !this.state.firedScoreEvents.has('engaged')) {
|
|
87
|
+
this.state.firedScoreEvents.add('engaged');
|
|
88
|
+
cdpTrack.track('Engaged_User', { score: this.state.userScore, meta_intensity: 'medium' });
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
// 1. Rage Click Detector
|
|
93
|
+
setupRageClicks() {
|
|
94
|
+
document.addEventListener('click', (e) => {
|
|
95
|
+
const now = Date.now();
|
|
96
|
+
this.state.clickHistory.push(now);
|
|
97
|
+
|
|
98
|
+
// Limpa histórico antigo
|
|
99
|
+
this.state.clickHistory = this.state.clickHistory.filter(t => now - t < this.config.rageClickTime);
|
|
100
|
+
|
|
101
|
+
if (this.state.clickHistory.length >= this.config.rageClickThreshold) {
|
|
102
|
+
cdpTrack.track('rage_click', {
|
|
103
|
+
element_id: e.target.id || '',
|
|
104
|
+
element_class: e.target.className || '',
|
|
105
|
+
x: e.pageX,
|
|
106
|
+
y: e.pageY,
|
|
107
|
+
meta_intensity: 'low' // Envia sinal leve para Meta
|
|
108
|
+
});
|
|
109
|
+
this.addScore(-10, 'rage_click');
|
|
110
|
+
this.state.clickHistory = []; // Reseta após detecção
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
// 1.2 Scroll Depth (Quantum Tier)
|
|
116
|
+
setupScroll() {
|
|
117
|
+
const markers = [25, 50, 75, 90];
|
|
118
|
+
const fired = new Set();
|
|
119
|
+
|
|
120
|
+
window.addEventListener('scroll', () => {
|
|
121
|
+
const scrollPct = Math.round((window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 100);
|
|
122
|
+
|
|
123
|
+
markers.forEach(m => {
|
|
124
|
+
if (scrollPct >= m && !fired.has(m)) {
|
|
125
|
+
fired.add(m);
|
|
126
|
+
this.addScore(m === 25 ? 5 : (m === 50 ? 5 : 10), `scroll_${m}%`);
|
|
127
|
+
cdpTrack.track('scroll_depth', {
|
|
128
|
+
percent: m,
|
|
129
|
+
meta_intensity: m >= 50 ? 'medium' : 'low' // Envia como sinal mais forte após 50%
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}, { passive: true });
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
// 2. Tab Visibility (VSL Focus)
|
|
137
|
+
setupVisibility() {
|
|
138
|
+
document.addEventListener('visibilitychange', () => {
|
|
139
|
+
const status = document.visibilityState; // 'visible' ou 'hidden'
|
|
140
|
+
cdpTrack.track('tab_visibility_change', {
|
|
141
|
+
status: status,
|
|
142
|
+
time_since_start: Math.floor((Date.now() - this.state.startTime) / 1000),
|
|
143
|
+
meta_intensity: status === 'visible' ? 'high' : 'low'
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
// 3. Click Heatmap (D1 Only)
|
|
149
|
+
setupHeatmap() {
|
|
150
|
+
document.addEventListener('click', (e) => {
|
|
151
|
+
// Enviamos apenas para o servidor/D1 para não poluir o pixel do cliente
|
|
152
|
+
// sendServerEvent é o método interno que pula o despacho para Meta/TikTok
|
|
153
|
+
if (typeof cdpTrack.sendServerEvent === 'function') {
|
|
154
|
+
cdpTrack.sendServerEvent('click_heatmap', null, {
|
|
155
|
+
x: e.pageX,
|
|
156
|
+
y: e.pageY,
|
|
157
|
+
element: e.target.tagName.toLowerCase(),
|
|
158
|
+
id: e.target.id || '',
|
|
159
|
+
classes: e.target.className || ''
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
// 4. Retention Pulse (Heartbeat)
|
|
166
|
+
setupHeartbeat() {
|
|
167
|
+
setInterval(() => {
|
|
168
|
+
const activeTime = Math.floor((Date.now() - this.state.startTime) / 1000);
|
|
169
|
+
cdpTrack.track('pulse_heartbeat', {
|
|
170
|
+
duration_seconds: activeTime,
|
|
171
|
+
is_visible: document.visibilityState === 'visible'
|
|
172
|
+
});
|
|
173
|
+
}, this.config.heartbeatInterval);
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
// 5. VSL / Video Tracking (YouTube & Vimeo)
|
|
177
|
+
setupVideoTracking() {
|
|
178
|
+
const iframes = document.querySelectorAll('iframe');
|
|
179
|
+
const fired = new Set();
|
|
180
|
+
|
|
181
|
+
iframes.forEach(iframe => {
|
|
182
|
+
const src = iframe.src || '';
|
|
183
|
+
const isYT = src.includes('youtube.com/embed');
|
|
184
|
+
const isVimeo = src.includes('vimeo.com/video');
|
|
185
|
+
|
|
186
|
+
if (isYT || isVimeo) {
|
|
187
|
+
// Observer de progresso (via postMessage para evitar dependência de SDK pesado)
|
|
188
|
+
window.addEventListener('message', (event) => {
|
|
189
|
+
try {
|
|
190
|
+
const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
|
|
191
|
+
|
|
192
|
+
// Lógica YouTube
|
|
193
|
+
if (isYT && data.event === 'infoDelivery' && data.info && data.info.currentTime) {
|
|
194
|
+
this.handleVideoProgress(iframe, data.info.currentTime, data.info.duration, fired, 'YouTube');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Lógica Vimeo
|
|
198
|
+
if (isVimeo && data.event === 'timeupdate') {
|
|
199
|
+
this.handleVideoProgress(iframe, data.data.seconds, data.data.duration, fired, 'Vimeo');
|
|
200
|
+
}
|
|
201
|
+
} catch (e) { /* ignore non-json messages */ }
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Ativa o JS API se for YouTube
|
|
205
|
+
if (isYT && !src.includes('enablejsapi=1')) {
|
|
206
|
+
const url = new URL(src);
|
|
207
|
+
url.searchParams.set('enablejsapi', '1');
|
|
208
|
+
iframe.src = url.toString();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
handleVideoProgress(iframe, current, total, firedSet, platform) {
|
|
215
|
+
if (!total) return;
|
|
216
|
+
const pct = Math.floor((current / total) * 100);
|
|
217
|
+
const milestones = [25, 50, 75, 100];
|
|
218
|
+
const videoId = iframe.id || iframe.src.split('/').pop().split('?')[0];
|
|
219
|
+
|
|
220
|
+
milestones.forEach(m => {
|
|
221
|
+
const key = `${videoId}_${m}`;
|
|
222
|
+
if (pct >= m && !firedSet.has(key)) {
|
|
223
|
+
firedSet.add(key);
|
|
224
|
+
this.addScore(m === 25 ? 10 : (m === 50 ? 15 : 25), `vsl_${m}%`);
|
|
225
|
+
cdpTrack.track('video_milestone', {
|
|
226
|
+
video_id: videoId,
|
|
227
|
+
platform: platform,
|
|
228
|
+
percent: m,
|
|
229
|
+
meta_intensity: m >= 50 ? 'high' : 'medium'
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
// 6. Form Analytics (Friction & Abandonment)
|
|
236
|
+
setupFormAnalytics() {
|
|
237
|
+
const inputs = document.querySelectorAll('input, select, textarea');
|
|
238
|
+
inputs.forEach(input => {
|
|
239
|
+
input.addEventListener('focus', () => {
|
|
240
|
+
const name = input.name || input.id;
|
|
241
|
+
if (!this.state.formStartTime[name]) {
|
|
242
|
+
this.state.formStartTime[name] = Date.now();
|
|
243
|
+
this.addScore(10, `form_interaction_${name}`);
|
|
244
|
+
cdpTrack.track('form_field_focus', { field: name });
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
input.addEventListener('blur', () => {
|
|
249
|
+
const name = input.name || input.id;
|
|
250
|
+
const duration = Math.round((Date.now() - this.state.formStartTime[name]) / 1000);
|
|
251
|
+
if (duration > 0) {
|
|
252
|
+
cdpTrack.track('form_field_blur', { field: name, duration_sec: duration });
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
// 6.1 Form Abandonment — saiu da página após interagir com formulário sem submeter
|
|
259
|
+
setupFormAbandonment() {
|
|
260
|
+
const formInteracted = new Set(); // campos que receberam foco
|
|
261
|
+
let formSubmitted = false;
|
|
262
|
+
|
|
263
|
+
// Marcar campo como interagido no focus
|
|
264
|
+
document.addEventListener('focusin', (e) => {
|
|
265
|
+
const el = e.target;
|
|
266
|
+
if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.tagName === 'SELECT') {
|
|
267
|
+
const name = el.name || el.id || el.type;
|
|
268
|
+
if (name) formInteracted.add(name);
|
|
269
|
+
}
|
|
270
|
+
}, true);
|
|
271
|
+
|
|
272
|
+
// Marcar submit realizado (qualquer formulário)
|
|
273
|
+
document.addEventListener('submit', () => {
|
|
274
|
+
formSubmitted = true;
|
|
275
|
+
}, true);
|
|
276
|
+
|
|
277
|
+
// Detectar abandono via visibilitychange (tab hidden / fechando)
|
|
278
|
+
document.addEventListener('visibilitychange', () => {
|
|
279
|
+
if (document.visibilityState === 'hidden' && formInteracted.size > 0 && !formSubmitted) {
|
|
280
|
+
this.addScore(-5, 'form_abandonment');
|
|
281
|
+
cdpTrack.track('form_abandonment', {
|
|
282
|
+
fields_interacted: Array.from(formInteracted),
|
|
283
|
+
fields_count: formInteracted.size,
|
|
284
|
+
meta_intensity: 'medium',
|
|
285
|
+
time_on_page: Math.floor((Date.now() - this.state.startTime) / 1000),
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Fallback: beforeunload
|
|
291
|
+
window.addEventListener('beforeunload', () => {
|
|
292
|
+
if (formInteracted.size > 0 && !formSubmitted) {
|
|
293
|
+
// Usar sendBeacon para garantir entrega mesmo na saída
|
|
294
|
+
if (navigator.sendBeacon && typeof cdpTrack !== 'undefined') {
|
|
295
|
+
const data = JSON.stringify({
|
|
296
|
+
eventName: 'form_abandonment',
|
|
297
|
+
behavioral_data: { user_score: this.state.userScore },
|
|
298
|
+
fields_interacted: Array.from(formInteracted),
|
|
299
|
+
fields_count: formInteracted.size,
|
|
300
|
+
meta_intensity: 'medium',
|
|
301
|
+
});
|
|
302
|
+
navigator.sendBeacon('/api/tracking', new Blob([data], { type: 'application/json' }));
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
},
|
|
307
|
+
|
|
308
|
+
// 6.2 Exit Intent — mouse saindo pelo topo da viewport
|
|
309
|
+
setupExitIntent() {
|
|
310
|
+
let exitFired = false; // disparar apenas uma vez por sessão
|
|
311
|
+
|
|
312
|
+
document.addEventListener('mousemove', (e) => {
|
|
313
|
+
// Threshold: mouse a menos de 20px do topo da viewport
|
|
314
|
+
if (e.clientY < 20 && !exitFired) {
|
|
315
|
+
exitFired = true;
|
|
316
|
+
this.addScore(15, 'exit_intent'); // sinal positivo: ainda está aqui
|
|
317
|
+
cdpTrack.track('exit_intent', {
|
|
318
|
+
mouse_y: e.clientY,
|
|
319
|
+
time_on_page: Math.floor((Date.now() - this.state.startTime) / 1000),
|
|
320
|
+
user_score: this.state.userScore,
|
|
321
|
+
meta_intensity: 'high', // Alta intenção — usuário está prestes a sair
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// Resetar após 30s para redetectar se usuário continuar
|
|
325
|
+
setTimeout(() => { exitFired = false; }, 30000);
|
|
326
|
+
}
|
|
327
|
+
}, { passive: true });
|
|
328
|
+
|
|
329
|
+
// Mobile: detectar via visibilitychange (sem mouse)
|
|
330
|
+
let mobileExitFired = false;
|
|
331
|
+
document.addEventListener('visibilitychange', () => {
|
|
332
|
+
if (document.visibilityState === 'hidden' && !mobileExitFired) {
|
|
333
|
+
const timeOnPage = Math.floor((Date.now() - this.state.startTime) / 1000);
|
|
334
|
+
// Só dispara se usuário ficou tempo suficiente (não é bounce imediato)
|
|
335
|
+
if (timeOnPage > 5) {
|
|
336
|
+
mobileExitFired = true;
|
|
337
|
+
cdpTrack.track('exit_intent_mobile', {
|
|
338
|
+
time_on_page: timeOnPage,
|
|
339
|
+
user_score: this.state.userScore,
|
|
340
|
+
meta_intensity: 'medium',
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
},
|
|
346
|
+
|
|
347
|
+
// 7. Copy-Paste Intent (High Conv.)
|
|
348
|
+
setupCopyPaste() {
|
|
349
|
+
document.addEventListener('copy', () => {
|
|
350
|
+
const selectedText = window.getSelection().toString();
|
|
351
|
+
if (selectedText.length > 0) {
|
|
352
|
+
this.addScore(20, 'text_copy');
|
|
353
|
+
cdpTrack.track('content_copy', {
|
|
354
|
+
text_length: selectedText.length,
|
|
355
|
+
meta_intensity: 'medium'
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
},
|
|
360
|
+
|
|
361
|
+
// 8. Outbound Link Tracking (Whitelist: WhatsApp/Checkouts)
|
|
362
|
+
setupOutboundLinks() {
|
|
363
|
+
document.addEventListener('click', (e) => {
|
|
364
|
+
const link = e.target.closest('a');
|
|
365
|
+
if (link && link.href) {
|
|
366
|
+
const url = link.href;
|
|
367
|
+
const isExternal = !url.includes(window.location.hostname);
|
|
368
|
+
const isWhitelisted = url.includes('wa.me') ||
|
|
369
|
+
url.includes('hotmart.com') ||
|
|
370
|
+
url.includes('kiwify.com') ||
|
|
371
|
+
url.includes('checkout');
|
|
372
|
+
|
|
373
|
+
if (isExternal && isWhitelisted) {
|
|
374
|
+
this.addScore(100, 'outbound_conversion_intent');
|
|
375
|
+
cdpTrack.track('outbound_click', {
|
|
376
|
+
destination: url,
|
|
377
|
+
meta_intensity: 'high'
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
},
|
|
383
|
+
|
|
384
|
+
// 9. JS Error Tracking (D1 Only)
|
|
385
|
+
setupErrorTracking() {
|
|
386
|
+
window.addEventListener('error', (event) => {
|
|
387
|
+
if (typeof cdpTrack.sendServerEvent === 'function') {
|
|
388
|
+
cdpTrack.sendServerEvent('js_error', null, {
|
|
389
|
+
message: event.message,
|
|
390
|
+
source: event.filename,
|
|
391
|
+
lineno: event.lineno,
|
|
392
|
+
colno: event.colno
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
},
|
|
397
|
+
|
|
398
|
+
// 10. Idle Detection (Active Time)
|
|
399
|
+
setupIdleDetection() {
|
|
400
|
+
const activityEvents = ['mousedown', 'mousemove', 'keydown', 'scroll', 'touchstart'];
|
|
401
|
+
activityEvents.forEach(evt => {
|
|
402
|
+
document.addEventListener(evt, () => {
|
|
403
|
+
this.state.lastActivity = Date.now();
|
|
404
|
+
if (this.state.isIdle) {
|
|
405
|
+
this.state.isIdle = false;
|
|
406
|
+
cdpTrack.track('user_active', { status: 'back_online' });
|
|
407
|
+
}
|
|
408
|
+
}, { passive: true });
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
setInterval(() => {
|
|
412
|
+
if (Date.now() - this.state.lastActivity > this.config.idleThreshold && !this.state.isIdle) {
|
|
413
|
+
this.state.isIdle = true;
|
|
414
|
+
cdpTrack.track('user_idle', { idle_duration: this.config.idleThreshold / 1000 });
|
|
415
|
+
}
|
|
416
|
+
}, 10000);
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
// Auto-inicialização se o cdpTrack estiver presente
|
|
421
|
+
if (typeof cdpTrack !== 'undefined') {
|
|
422
|
+
BehaviorEngine.init();
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export default BehaviorEngine;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Blueprint: Real Estate (Lançamento Imobiliário) - Quantum Tier
|
|
2
|
+
|
|
3
|
+
Este blueprint define a inteligência técnica para capturar e atribuir leads do mercado imobiliário com alta fidelidade.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🏗️ ARQUITETURA TÉCNICA
|
|
8
|
+
|
|
9
|
+
### 1. Geolocalização Nativa (Edge Sync)
|
|
10
|
+
Para negócios locais, a geolocalização é o sinal mais rico para a Meta encontrar compradores próximos ao empreendimento.
|
|
11
|
+
* **Captura**: Ativar via `getCidade()` no browser.
|
|
12
|
+
* **Envio**: Incluir campos `ct` (city) e `st` (state) no Advanced Matching da Meta (CAPI).
|
|
13
|
+
|
|
14
|
+
### 2. WhatsApp Lead Lock (D1 Persistence)
|
|
15
|
+
O maior vazamento de dados no mercado imobiliário é o clique no botão de WhatsApp sem que o lead seja salvo no CRM.
|
|
16
|
+
* **Ação**: No momento do clique (`Contact`), o CDP Edge salva o `fbclid`, `gclid` e `ttclid` no D1 vinculado ao contexto da página.
|
|
17
|
+
* **Offline Match**: Quando a venda ocorre (offline), os IDs de rastro são recuperados do D1 para disparo do evento `Purchase`.
|
|
18
|
+
|
|
19
|
+
### 3. CTWA Support (Click-to-WhatsApp)
|
|
20
|
+
Anúncios de mensagem são o padrão. O parâmetro `ctwa_clid` é monitorado e persistido para o Worker.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🛠️ MAPEAMENTO DO PAGE ANALYZER
|
|
25
|
+
|
|
26
|
+
O Page Analyzer deve buscar os seguintes sinais:
|
|
27
|
+
* **Seletores**: `a[href*='wa.me']`, `a[href*='api.whatsapp.com']`, `#form-visita`.
|
|
28
|
+
* **Sinais Gráficos**: Palavras-chave como "Plantão", "Decorado", "Financiamento", "Quartos", "Suítes".
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 📜 EXEMPLO DE INJEÇÃO (cdpTrack)
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
// Exemplo de captura de visita a imóvel com geolocalização ativa
|
|
36
|
+
cdpTrack.track('ViewContent', {
|
|
37
|
+
content_category: 'imovel',
|
|
38
|
+
content_name: 'Residencial Aurora', // Capturado do H1
|
|
39
|
+
city: await cdpTrack.getCidade(), // Capturado nativamente
|
|
40
|
+
meta_intensity: 'high'
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Lead Lock no clique do WhatsApp
|
|
44
|
+
document.querySelector('.btn-whatsapp').addEventListener('click', () => {
|
|
45
|
+
cdpTrack.track('Contact', {
|
|
46
|
+
method: 'whatsapp',
|
|
47
|
+
lead_lock: true // Sinaliza para o D1 persistir os IDs de clique e a geolocalização
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Blueprint: Sales Page & Checkout (Páginas de Vendas) - Quantum Tier
|
|
2
|
+
|
|
3
|
+
Este blueprint define a inteligência técnica para rastrear e atribuir vendas em infoprodutos com alta precisão e 100% de dedução de ROI.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🏗️ ARQUITETURA TÉCNICA
|
|
8
|
+
|
|
9
|
+
### 1. Checkout Passthrough (UTM & UID Injection)
|
|
10
|
+
Indispensável para Hotmart, Kiwify, Eduzz, CartPanda.
|
|
11
|
+
* **Captura**: O CDP Edge captura as UTMs no carregamento da página.
|
|
12
|
+
* **Injeção**: Ao clicar no botão de compra, o CDP Edge injeta automaticamente os parâmetros `xcod`, `sck` (Hotmart), `src` (Kiwify) ou parâmetros customizados no URL do checkout.
|
|
13
|
+
* **D1 Lock**: Salva o `_cdp_uid` persistente para atribuição server-side posterior (no recebimento do Webhook de venda).
|
|
14
|
+
|
|
15
|
+
### 2. VSL Retention Engine (Video Milestone)
|
|
16
|
+
Mede a eficácia do vídeo de vendas antes do botão de compra aparecer.
|
|
17
|
+
* **Milestones**: 25%, 50%, 75%, 100%.
|
|
18
|
+
* **Visibility Sync**: Pausa a contagem de retenção se a aba for escondida, mas registra o status do áudio separadamente.
|
|
19
|
+
* **Ação**: Disparar `ViewContent` (25/50/75) e `AddToCart` (100% ou clique no botão).
|
|
20
|
+
|
|
21
|
+
### 3. Adblock Immunity (Stealth Tracking)
|
|
22
|
+
Utiliza rotas no mesmo domínio (ex: `/api/tracking`) para garantir que o script de rastreamento não seja bloqueado por uBlock ou Ghostery.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 🛠️ MAPEAMENTO DO PAGE ANALYZER
|
|
27
|
+
|
|
28
|
+
O Page Analyzer deve buscar os seguintes sinais:
|
|
29
|
+
* **Checkouts**: Qualquer `<a>` com links contendo `pay.hotmart.com`, `kiwify.com.br`, `eduzz.com`, `monetizze.com.br`.
|
|
30
|
+
* **Vídeos**: Tags `<iframe>` de YouTube ou Vimeo, ou players customizados.
|
|
31
|
+
* **Sinais Gráficos**: Headlines de promessa, Garantia de X dias, Botão de "Quero Garantir Minha Vaga".
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 📜 EXEMPLO DE INJEÇÃO (cdpTrack)
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
// Exemplo de injeção automática de Checkout
|
|
39
|
+
cdpTrack.passCheckoutParams({
|
|
40
|
+
platforms: ['hotmart', 'kiwify'],
|
|
41
|
+
extra: { source: 'facebook_ads' }
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Exemplo de retenção de VSL
|
|
45
|
+
cdpTrack.track('ViewContent', {
|
|
46
|
+
vsl_name: 'VSL_Lote_1',
|
|
47
|
+
watch_time: 120, // segundos
|
|
48
|
+
meta_intensity: 'high'
|
|
49
|
+
});
|
|
50
|
+
```
|