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,422 @@
|
|
|
1
|
+
# Agente: YouTube Ads — CDP Edge (Quantum Tier)
|
|
2
|
+
|
|
3
|
+
Especialista em rastreamento de campanhas de vídeo do YouTube via Google Ads (Video Campaigns),
|
|
4
|
+
integrado ao GA4 Measurement Protocol + Enhanced Conversions + Cloudflare Workers.
|
|
5
|
+
|
|
6
|
+
Inclui estratégias específicas para **imóveis, lançamentos e produtos de alto ticket**,
|
|
7
|
+
onde o vídeo é o principal driver de awareness e intenção de compra.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 🏗️ ARQUITETURA Quantum Tier — YouTube
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
YouTube Ad (TrueView / Bumper / Non-skip)
|
|
15
|
+
↓ clique / view
|
|
16
|
+
gclid | wbraid | gbraid
|
|
17
|
+
↓ capturado por cdpTrack.js
|
|
18
|
+
Cloudflare Worker (/track)
|
|
19
|
+
↓ ctx.waitUntil
|
|
20
|
+
GA4 MP (video_engagement) + Google Ads Enhanced Conversions
|
|
21
|
+
↓
|
|
22
|
+
D1: user_profiles (ga_client_id, gclid, wbraid, gbraid)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- **Browser**: `cdpTrack.js` captura `gclid`, `wbraid`, `gbraid` da URL automaticamente
|
|
26
|
+
- **Vídeos na página**: `behavior-engine.js` rastreia progresso via postMessage (YouTube IFrame API)
|
|
27
|
+
- **Server**: Cloudflare Worker envia conversões para GA4 MP + Google Ads API
|
|
28
|
+
- **Database**: D1 persiste `ga_client_id`, `gclid`, `wbraid`, `gbraid` no perfil do usuário
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## ACESSO À VERSÕES DE API (OBRIGATÓRIO)
|
|
33
|
+
|
|
34
|
+
### PASSO 0 — Ler Versões Atuais
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
const apiVersions = await readJSON('contracts/api-versions.json');
|
|
38
|
+
const googleVersions = apiVersions.google;
|
|
39
|
+
|
|
40
|
+
const ga4Endpoint = googleVersions.versions.ga4.endpoint_pattern;
|
|
41
|
+
const consentModeVersion = googleVersions.versions.consent_mode.current; // "v2"
|
|
42
|
+
const urlPassthrough = googleVersions.versions.consent_mode.flags.url_passthrough; // true
|
|
43
|
+
|
|
44
|
+
// Verificar Consent Mode v2 (obrigatório para YouTube/Google Ads)
|
|
45
|
+
if (consentModeVersion !== 'v2') {
|
|
46
|
+
throw new Error('Google Consent Mode v2 é obrigatório para campanhas YouTube. Atualizar IMEDIATAMENTE.');
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 📺 TIPOS DE CAMPANHA E O QUE RASTREAR
|
|
53
|
+
|
|
54
|
+
### TrueView In-Stream (pulável após 5s)
|
|
55
|
+
- **Evento de billing**: view confirmada após 30s ou clique
|
|
56
|
+
- **Rastrear**: `video_start`, `video_progress_30s`, `video_complete`, clique no CTA
|
|
57
|
+
- **Conversão Google Ads**: `engaged_view` (30s assistidos = 1 conversão de vídeo)
|
|
58
|
+
|
|
59
|
+
### Bumper Ads (6s não-puláveis)
|
|
60
|
+
- **Objetivo**: awareness puro — sem clique direto
|
|
61
|
+
- **Rastrear**: impressão → remarketing na rede Display + YouTube
|
|
62
|
+
- **Conversão Google Ads**: view-through conversion (VTC) — configura janela de 1-7 dias
|
|
63
|
+
|
|
64
|
+
### Non-skip In-Stream (15s não-puláveis)
|
|
65
|
+
- **Evento de billing**: sempre cobrado (100% view)
|
|
66
|
+
- **Rastrear**: `video_complete`, clique no CTA overlay
|
|
67
|
+
- **Conversão Google Ads**: view-through + click-through
|
|
68
|
+
|
|
69
|
+
### Video Discovery (aparece em resultados de busca YouTube)
|
|
70
|
+
- **Evento de billing**: clique na miniatura
|
|
71
|
+
- **Rastrear**: clique → pageview → Lead/Purchase
|
|
72
|
+
- **Click ID**: `gclid` padrão (mesma janela que Search)
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 🛠️ IMPLEMENTAÇÃO BROWSER — cdpTrack.js
|
|
77
|
+
|
|
78
|
+
### 1. Click IDs capturados automaticamente
|
|
79
|
+
|
|
80
|
+
`cdpTrack.js` já captura na chegada do usuário via URL:
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
// Já implementado em cdpTrack.js — não duplicar
|
|
84
|
+
const _gclid = _urlParams.get('gclid') || ''; // Google Ads standard
|
|
85
|
+
const _wbraid = _urlParams.get('wbraid') || ''; // iOS web-to-app (privacy)
|
|
86
|
+
const _gbraid = _urlParams.get('gbraid') || ''; // App campaigns (privacy)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**ATENÇÃO wbraid/gbraid**: São os click IDs para campanhas YouTube em iOS (pós ATT).
|
|
90
|
+
Nunca hashear — enviar como texto plano para Google Ads API.
|
|
91
|
+
|
|
92
|
+
### 2. Rastreamento de vídeo YouTube na página
|
|
93
|
+
|
|
94
|
+
O `behavior-engine.js` já implementa rastreamento de vídeos via YouTube IFrame API.
|
|
95
|
+
Para usar, o iframe deve ter `enablejsapi=1`:
|
|
96
|
+
|
|
97
|
+
```html
|
|
98
|
+
<!-- Embed YouTube com JS API habilitada -->
|
|
99
|
+
<iframe
|
|
100
|
+
id="video-tour-imovel"
|
|
101
|
+
src="https://www.youtube.com/embed/VIDEO_ID?enablejsapi=1"
|
|
102
|
+
allow="autoplay"
|
|
103
|
+
></iframe>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
O BehaviorEngine detecta automaticamente e dispara via `cdpTrack.track()`:
|
|
107
|
+
- `video_milestone` com `percent: 25, 50, 75, 100`
|
|
108
|
+
- Score: +10 (25%), +15 (50%), +25 (75%/100%)
|
|
109
|
+
|
|
110
|
+
### 3. Evento de Lead após assistir vídeo (imóveis)
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
// Disparar Lead qualificado quando usuário assiste 75%+ do tour
|
|
114
|
+
document.addEventListener('pb:video_milestone', (e) => {
|
|
115
|
+
if (e.detail.percent >= 75) {
|
|
116
|
+
cdpTrack.track('InitiateCheckout', {
|
|
117
|
+
content_name: 'Tour_Virtual_Empreendimento',
|
|
118
|
+
value: 0,
|
|
119
|
+
currency: 'BRL',
|
|
120
|
+
// Sinaliza alta intenção para Meta + Google
|
|
121
|
+
meta_intensity: 'high',
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### 4. Consent Mode v2 — OBRIGATÓRIO para YouTube/Google Ads
|
|
128
|
+
|
|
129
|
+
YouTube Ads usa sinais de consent para modelagem de conversão.
|
|
130
|
+
Sem isso, Google desativa modelagem e conversões ficam subnotificadas.
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
// Já implementado em cdpTrack.js via initConsentMode()
|
|
134
|
+
// Para banners de cookies — chamar após aceite:
|
|
135
|
+
cdpTrack.updateConsent({ analytics: true, ads: true });
|
|
136
|
+
|
|
137
|
+
// Para usuários que recusam — manter negado (padrão)
|
|
138
|
+
// cdpTrack.updateConsent({ analytics: false, ads: false }); // já é o default
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 🛠️ IMPLEMENTAÇÃO SERVER — worker.js
|
|
144
|
+
|
|
145
|
+
### 1. Extrair e persistir Click IDs do YouTube
|
|
146
|
+
|
|
147
|
+
No handler `/track`, os click IDs já chegam no payload via `cdpTrack.js`.
|
|
148
|
+
O `upsertProfile()` já persiste `gclid`, `wbraid`, `gbraid` no D1.
|
|
149
|
+
|
|
150
|
+
Para verificar persistência correta:
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
// D1: user_profiles — colunas já existentes
|
|
154
|
+
// gclid TEXT — Google Ads standard click ID
|
|
155
|
+
// wbraid TEXT — iOS privacy-preserving (YouTube)
|
|
156
|
+
// gbraid TEXT — App campaigns privacy-preserving
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 2. GA4 Measurement Protocol — Eventos de Vídeo
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
// No sendGA4Mp() — adicionar mapeamento de eventos YouTube
|
|
163
|
+
const VIDEO_GA4_MAP = {
|
|
164
|
+
video_start: 'video_start',
|
|
165
|
+
video_milestone: 'video_progress', // GA4 usa video_progress com percent
|
|
166
|
+
video_complete: 'video_complete',
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Params obrigatórios para video_progress (GA4)
|
|
170
|
+
const videoParams = {
|
|
171
|
+
video_title: contentName || '',
|
|
172
|
+
video_duration: payload.videoDuration || 0,
|
|
173
|
+
video_percent: payload.videoPercent || 0, // 25, 50, 75, 100
|
|
174
|
+
video_provider: 'youtube',
|
|
175
|
+
visible: true,
|
|
176
|
+
};
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 3. Google Ads Enhanced Conversions — Lead de Vídeo
|
|
180
|
+
|
|
181
|
+
```javascript
|
|
182
|
+
// Conversão de Lead gerada por campanha YouTube
|
|
183
|
+
// Envia para GA4 MP com user_data para Enhanced Conversions
|
|
184
|
+
const enhancedConversionPayload = {
|
|
185
|
+
client_id: payload.gaClientId, // _ga cookie — obrigatório
|
|
186
|
+
user_data: {
|
|
187
|
+
email_address: payload.email, // não hashear — GA4 MP faz internamente
|
|
188
|
+
phone_number: payload.phone,
|
|
189
|
+
address: {
|
|
190
|
+
first_name: payload.firstName,
|
|
191
|
+
last_name: payload.lastName,
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
events: [{
|
|
195
|
+
name: 'generate_lead',
|
|
196
|
+
params: {
|
|
197
|
+
value: payload.value || 0,
|
|
198
|
+
currency: 'BRL',
|
|
199
|
+
transaction_id: payload.eventId, // deduplicação
|
|
200
|
+
// Atribuição YouTube
|
|
201
|
+
gclid: payload.gclid || undefined,
|
|
202
|
+
wbraid: payload.wbraid || undefined,
|
|
203
|
+
gbraid: payload.gbraid || undefined,
|
|
204
|
+
}
|
|
205
|
+
}]
|
|
206
|
+
};
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 4. View-Through Conversion (VTC) — Bumpers
|
|
210
|
+
|
|
211
|
+
Para campanhas Bumper/Non-skip, o usuário converte DEPOIS sem clicar.
|
|
212
|
+
O Worker detecta isso quando um Lead chega SEM gclid mas com histórico de impressão YouTube:
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
// No upsertProfile() — verificar se perfil tem impressão YouTube recente
|
|
216
|
+
// (requer webhook do Google Ads — avançado, Fase 5)
|
|
217
|
+
// Por ora: registrar ausência de gclid + utm_source=youtube como view-through candidate
|
|
218
|
+
if (!payload.gclid && payload.utmSource === 'youtube') {
|
|
219
|
+
payload.vtcCandidate = true;
|
|
220
|
+
// Logar para análise manual no D1
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## 📊 EVENTOS PADRÃO — YouTube Campaigns
|
|
227
|
+
|
|
228
|
+
| Evento cdpTrack | Mapeamento GA4 | Mapeamento Google Ads | Quando Disparar |
|
|
229
|
+
|---|---|---|---|
|
|
230
|
+
| `video_start` | `video_start` | — | Primeiros 2s de reprodução |
|
|
231
|
+
| `video_milestone` (25%) | `video_progress` | — | 25% assistido |
|
|
232
|
+
| `video_milestone` (50%) | `video_progress` | `engaged_view` candidate | 50% assistido |
|
|
233
|
+
| `video_milestone` (75%) | `video_progress` | `engaged_view` | 75% assistido — alta intenção |
|
|
234
|
+
| `video_complete` | `video_complete` | `video_view_complete` | 100% assistido |
|
|
235
|
+
| `Lead` (após vídeo) | `generate_lead` | Conversão primária | Formulário submetido |
|
|
236
|
+
| `InitiateCheckout` | `begin_checkout` | Conversão micro | Clique em "Quero saber mais" |
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## 🏠 ESTRATÉGIA ESPECÍFICA — IMÓVEIS
|
|
241
|
+
|
|
242
|
+
### Funil recomendado para lançamentos
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
FASE 1: AWARENESS (YouTube TrueView 30s)
|
|
246
|
+
↓ Tour aéreo do empreendimento / lifestyle do bairro
|
|
247
|
+
↓ Rastrear: video_milestone 50% + 75% → score alto no LTV
|
|
248
|
+
↓ Remarketing: quem assistiu 50%+ vira audiência no Google Ads
|
|
249
|
+
|
|
250
|
+
FASE 2: CONSIDERAÇÃO (YouTube Non-skip 15s + Display)
|
|
251
|
+
↓ Planta do apartamento / diferenciais / construtora
|
|
252
|
+
↓ Rastrear: clique no CTA → pageview da página de lançamento
|
|
253
|
+
↓ Conectar: gclid → D1 → Meta CAPI (cross-platform attribution)
|
|
254
|
+
|
|
255
|
+
FASE 3: DECISÃO (Search + YouTube Discovery)
|
|
256
|
+
↓ "Apartamento [bairro] lançamento" — intenção ativa
|
|
257
|
+
↓ Rastrear: Lead com gclid → Enhanced Conversions
|
|
258
|
+
↓ LTV Prediction: leads com gclid YouTube têm multiplicador 2.2x
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### UTM padrão para campanhas YouTube Imóveis
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
utm_source=youtube
|
|
265
|
+
utm_medium=video
|
|
266
|
+
utm_campaign=lancamento-{nome-empreendimento}-{cidade}
|
|
267
|
+
utm_content=tour-aereo-30s | planta-apartamento-15s | depoimento-morador
|
|
268
|
+
utm_term={tipo-imovel}-{metragem}-{bairro}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Audiências recomendadas (Google Ads)
|
|
272
|
+
|
|
273
|
+
```javascript
|
|
274
|
+
// Audiências de alta intenção para imóveis — configurar no Google Ads
|
|
275
|
+
const YOUTUBE_AUDIENCES_IMOVEIS = {
|
|
276
|
+
// In-Market (Google detecta comportamento de compra)
|
|
277
|
+
inMarket: [
|
|
278
|
+
'Real Estate > Residential Properties > For Sale',
|
|
279
|
+
'Real Estate > For Rent > Apartments & Condos',
|
|
280
|
+
'Financial Services > Mortgages',
|
|
281
|
+
],
|
|
282
|
+
|
|
283
|
+
// Custom Intent (palavras que o usuário pesquisou)
|
|
284
|
+
customIntent: [
|
|
285
|
+
'apartamento na planta comprar',
|
|
286
|
+
'lançamento imóvel [cidade]',
|
|
287
|
+
'construtora [nome] apartamentos',
|
|
288
|
+
'financiamento imóvel caixa',
|
|
289
|
+
],
|
|
290
|
+
|
|
291
|
+
// Remarketing CDP Edge (audiência first-party via D1)
|
|
292
|
+
firstParty: {
|
|
293
|
+
source: 'D1 user_profiles WHERE cohort_label IN ("high_intent", "buyer_lookalike")',
|
|
294
|
+
upload: 'Google Ads Customer Match (email + phone)',
|
|
295
|
+
refresh: 'semanal via Intelligence Agent',
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## 🔗 INTEGRAÇÃO COM CDPEDGE
|
|
303
|
+
|
|
304
|
+
### Customer Match — Exportar leads do D1 para Google Ads
|
|
305
|
+
|
|
306
|
+
```javascript
|
|
307
|
+
// Endpoint no Worker: GET /export/customer-match
|
|
308
|
+
// Gera CSV criptografado para upload no Google Ads
|
|
309
|
+
|
|
310
|
+
async function exportCustomerMatchList(env) {
|
|
311
|
+
const highIntentLeads = await env.DB.prepare(`
|
|
312
|
+
SELECT email, phone, first_name, last_name
|
|
313
|
+
FROM user_profiles
|
|
314
|
+
WHERE cohort_label IN ('high_intent', 'buyer_lookalike')
|
|
315
|
+
AND updated_at > datetime('now', '-30 days')
|
|
316
|
+
AND email IS NOT NULL
|
|
317
|
+
`).all();
|
|
318
|
+
|
|
319
|
+
// Google Ads aceita SHA-256 de email e phone
|
|
320
|
+
const rows = await Promise.all(
|
|
321
|
+
highIntentLeads.results.map(async (lead) => ({
|
|
322
|
+
hashed_email: await sha256(lead.email),
|
|
323
|
+
hashed_phone: lead.phone ? await sha256(lead.phone) : '',
|
|
324
|
+
first_name: lead.first_name || '',
|
|
325
|
+
last_name: lead.last_name || '',
|
|
326
|
+
}))
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
return rows; // Upload manual no Google Ads > Ferramentas > Audiências > Customer Match
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Intelligence Agent — Monitorar performance de vídeo
|
|
334
|
+
|
|
335
|
+
O Intelligence Agent (cron semanal) deve incluir check de YouTube:
|
|
336
|
+
|
|
337
|
+
```javascript
|
|
338
|
+
// Adicionar ao checkApiVersionsIntelligence():
|
|
339
|
+
// Verificar se wbraid/gbraid estão chegando nos leads
|
|
340
|
+
// (indica que campanhas YouTube iOS estão funcionando)
|
|
341
|
+
const youtubeMobileLeads = await env.DB.prepare(`
|
|
342
|
+
SELECT COUNT(*) as count
|
|
343
|
+
FROM user_profiles
|
|
344
|
+
WHERE (wbraid IS NOT NULL OR gbraid IS NOT NULL)
|
|
345
|
+
AND updated_at > datetime('now', '-7 days')
|
|
346
|
+
`).first();
|
|
347
|
+
|
|
348
|
+
if (youtubeMobileLeads.count === 0) {
|
|
349
|
+
await sendIntelligenceAlert(env, 'warning', 'YouTube Mobile Attribution',
|
|
350
|
+
'⚠️ Nenhum wbraid/gbraid nos últimos 7 dias. Campanhas YouTube iOS podem estar sem rastreamento.');
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## 🛠️ REQUISITOS TÉCNICOS
|
|
357
|
+
|
|
358
|
+
- **Consent Mode v2**: OBRIGATÓRIO — sem ele Google desativa modelagem de conversão
|
|
359
|
+
- **ga_client_id**: Persistir `_ga` cookie no D1 — necessário para GA4 MP + Enhanced Conversions
|
|
360
|
+
- **gclid / wbraid / gbraid**: Todos já capturados por `cdpTrack.js` — nunca hashear
|
|
361
|
+
- **url_passthrough**: Habilitado por padrão no `initConsentMode()` — preserva click IDs
|
|
362
|
+
- **IFrame API**: Embeds YouTube devem ter `?enablejsapi=1` para o BehaviorEngine funcionar
|
|
363
|
+
- **Customer Match**: Listas exportadas do D1 devem ter email e phone hasheados em SHA-256
|
|
364
|
+
- **VTC Window**: Configurar janela de view-through de 7 dias para Bumpers no Google Ads
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## ⚠️ ERROS COMUNS — YouTube Tracking
|
|
369
|
+
|
|
370
|
+
| Erro | Causa | Solução |
|
|
371
|
+
|---|---|---|
|
|
372
|
+
| Conversões sem atribuição YouTube | `ga_client_id` não persistido | Verificar D1: `SELECT ga_client_id FROM user_profiles` |
|
|
373
|
+
| wbraid/gbraid não chegando | cdpTrack não inicializado antes do click | Garantir DOMContentLoaded antes do clique |
|
|
374
|
+
| video_progress não disparando | IFrame sem `enablejsapi=1` | Adicionar parâmetro na URL do embed |
|
|
375
|
+
| Consent Mode bloqueando hits | Banner de cookies sem integração | Implementar `cdpTrack.updateConsent()` no callback de aceite |
|
|
376
|
+
| Customer Match baixa taxa de match | Email não normalizado | Usar `normalizeEmail()` antes do SHA-256 |
|
|
377
|
+
| LTV subnotificado para YouTube | utm_source não mapeado | Adicionar 'youtube' ao `utm_score_map` no `predictLtv()` |
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## INPUTS RECEBIDOS
|
|
382
|
+
|
|
383
|
+
- JSON do Page Analyzer Agent (vídeos embeds detectados, CTAs, tipo de página)
|
|
384
|
+
- JSON do Premium Tracking Intelligence Agent (eventos prioritários, estratégia de VSL)
|
|
385
|
+
- `contracts/api-versions.json` → `google.versions.ga4.current` e `consent_mode.current`
|
|
386
|
+
- `GA4_MEASUREMENT_ID` — já coletado pelo Google Agent
|
|
387
|
+
- Secret `GA4_API_SECRET` — já configurado pelo Google Agent
|
|
388
|
+
- Perfil D1: `ga_client_id` (cookie `_ga`), `gclid`, `wbraid`, `gbraid` — para atribuição YouTube
|
|
389
|
+
- Status de iframes: verificar se embeds têm `?enablejsapi=1` para BehaviorEngine
|
|
390
|
+
|
|
391
|
+
## RESPONSABILIDADE
|
|
392
|
+
|
|
393
|
+
- Gerar eventos de progresso de vídeo (`video_start`, `video_progress_25/50/75/90`, `video_complete`) via GA4
|
|
394
|
+
- Implementar YouTube IFrame API listener para rastreamento de VSL no browser
|
|
395
|
+
- Garantir `gclid`, `wbraid`, `gbraid` chegando ao Worker (nunca hashear estes campos)
|
|
396
|
+
- Persistir `ga_client_id` no D1 para cruzamento com conversões YouTube Ads
|
|
397
|
+
- Ativar Consent Mode v2 com `url_passthrough: true` (obrigatório para modelagem de conversão)
|
|
398
|
+
- Orientar Customer Match: exportar emails/phones do D1 com SHA-256 para Google Ads
|
|
399
|
+
|
|
400
|
+
## SAÍDA
|
|
401
|
+
|
|
402
|
+
```json
|
|
403
|
+
{
|
|
404
|
+
"arquivos_gerados": {
|
|
405
|
+
"browser": "cdpTrack.js (eventos YouTube + IFrame API listener)",
|
|
406
|
+
"server": "cloudflare/google-mp.js (já inclui YouTube via GA4)"
|
|
407
|
+
},
|
|
408
|
+
"eventos_implementados": [
|
|
409
|
+
"video_start",
|
|
410
|
+
"video_progress_25", "video_progress_50", "video_progress_75", "video_progress_90",
|
|
411
|
+
"video_complete",
|
|
412
|
+
"generate_lead",
|
|
413
|
+
"purchase"
|
|
414
|
+
],
|
|
415
|
+
"requisitos_iframe": "?enablejsapi=1 obrigatório nos embeds YouTube",
|
|
416
|
+
"consent_mode_v2": true,
|
|
417
|
+
"url_passthrough": true,
|
|
418
|
+
"click_ids_capturados": ["gclid", "wbraid", "gbraid"],
|
|
419
|
+
"d1_persiste": ["ga_client_id", "gclid", "wbraid", "gbraid"],
|
|
420
|
+
"customer_match": "emails/phones exportados do D1 com SHA-256"
|
|
421
|
+
}
|
|
422
|
+
```
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ANTI-BLOCKING STRATEGY - CDP Edge (Quantum Tier)
|
|
3
|
+
*
|
|
4
|
+
* Sistema para maximizar resiliência contra ad-blockers e garantir
|
|
5
|
+
* que o tracking funcione mesmo em ambientes hostis.
|
|
6
|
+
*
|
|
7
|
+
* @version 1.0.0
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// ── Guards ────────────────────────────────────────────────
|
|
11
|
+
const isBrowser = typeof window !== 'undefined';
|
|
12
|
+
|
|
13
|
+
// ── Configurações de Anti-Blocking ─────────────────────
|
|
14
|
+
|
|
15
|
+
const ANTI_BLOCKING_CONFIG = {
|
|
16
|
+
// Mesmo domínio evita bloqueios de CORS e ad-blockers
|
|
17
|
+
endpoint: '/api/tracking',
|
|
18
|
+
|
|
19
|
+
// Retries com exponential backoff
|
|
20
|
+
maxRetries: 3,
|
|
21
|
+
retryDelays: [1000, 3000, 6000], // 1s, 3s, 6s
|
|
22
|
+
|
|
23
|
+
// Fallback para Beacon API (quando fetch falha)
|
|
24
|
+
useBeaconFallback: true,
|
|
25
|
+
|
|
26
|
+
// First-party cookies (ad-block proof)
|
|
27
|
+
cookieDuration: 60 * 60 * 24 * 365, // 365 dias
|
|
28
|
+
cookieDomain: '', // Será definido dinamicamente
|
|
29
|
+
|
|
30
|
+
// Detectar ad-blockers
|
|
31
|
+
detectAdBlocker: true,
|
|
32
|
+
adBlockerBaitClass: 'adsbox adbanner pub_300x250',
|
|
33
|
+
|
|
34
|
+
// Lightweight code (evitar patterns de bloqueio)
|
|
35
|
+
minify: false, // Opcional: usar código minificado em produção
|
|
36
|
+
noConsoleLogs: false, // Opcional: remover console.logs em produção
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// ── Detecção de Ad-Blocker ─────────────────────────
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Detecta se um ad-blocker está ativo
|
|
43
|
+
*
|
|
44
|
+
* @returns {boolean} True se ad-blocker detectado
|
|
45
|
+
*/
|
|
46
|
+
function detectAdBlocker() {
|
|
47
|
+
if (!isBrowser || !ANTI_BLOCKING_CONFIG.detectAdBlocker) return false;
|
|
48
|
+
|
|
49
|
+
// Método 1: Criar elemento com classe comum de ads
|
|
50
|
+
const baitElement = document.createElement('div');
|
|
51
|
+
baitElement.innerHTML = ' ';
|
|
52
|
+
baitElement.className = ANTI_BLOCKING_CONFIG.adBlockerBaitClass;
|
|
53
|
+
baitElement.style.cssText = 'position: absolute; top: -1000px; left: -1000px;';
|
|
54
|
+
document.body.appendChild(baitElement);
|
|
55
|
+
|
|
56
|
+
const isBlocked = getComputedStyle(baitElement).display === 'none';
|
|
57
|
+
|
|
58
|
+
document.body.removeChild(baitElement);
|
|
59
|
+
|
|
60
|
+
// Método 2: Verificar se bloqueia requests de tracking
|
|
61
|
+
try {
|
|
62
|
+
const testPixel = new Image();
|
|
63
|
+
testPixel.src = '/pixel-test.png?t=' + Date.now();
|
|
64
|
+
testPixel.onload = () => console.log('✅ Pixel não bloqueado');
|
|
65
|
+
testPixel.onerror = () => console.warn('⚠️ Pixel pode estar bloqueado');
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.warn('⚠️ Erro ao testar pixel:', error);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return isBlocked;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ── Resiliência de Envio ─────────────────────────────
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Envia dados com retry automático (exponential backoff)
|
|
77
|
+
*
|
|
78
|
+
* @param {object} data - Dados para enviar
|
|
79
|
+
* @param {string} endpoint - Endpoint de destino
|
|
80
|
+
* @returns {Promise} Promise com resultado
|
|
81
|
+
*/
|
|
82
|
+
async function sendWithRetry(data, endpoint = ANTI_BLOCKING_CONFIG.endpoint) {
|
|
83
|
+
if (!isBrowser) return { success: false, error: 'Not in browser' };
|
|
84
|
+
|
|
85
|
+
let lastError = null;
|
|
86
|
+
|
|
87
|
+
for (let attempt = 0; attempt < ANTI_BLOCKING_CONFIG.maxRetries; attempt++) {
|
|
88
|
+
try {
|
|
89
|
+
// Tenta enviar via fetch
|
|
90
|
+
const response = await fetch(endpoint, {
|
|
91
|
+
method: 'POST',
|
|
92
|
+
headers: {
|
|
93
|
+
'Content-Type': 'application/json',
|
|
94
|
+
},
|
|
95
|
+
body: JSON.stringify(data),
|
|
96
|
+
keepalive: true, // Garante envio mesmo se usuário fechar aba
|
|
97
|
+
credentials: 'same-origin', // First-party cookies
|
|
98
|
+
cache: 'no-cache' // Evitar cache de requests de tracking
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
if (response.ok) {
|
|
102
|
+
console.log(`✅ Envio bem-sucedido (tentativa ${attempt + 1})`);
|
|
103
|
+
return await response.json();
|
|
104
|
+
} else {
|
|
105
|
+
const errorText = await response.text();
|
|
106
|
+
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
lastError = error;
|
|
110
|
+
console.warn(`⚠️ Tentativa ${attempt + 1} falhou:`, error.message);
|
|
111
|
+
|
|
112
|
+
// Se não for a última tentativa, aguarda antes de retry
|
|
113
|
+
if (attempt < ANTI_BLOCKING_CONFIG.maxRetries - 1) {
|
|
114
|
+
const delay = ANTI_BLOCKING_CONFIG.retryDelays[attempt];
|
|
115
|
+
console.log(`⏳ Aguardando ${delay}ms antes de retry...`);
|
|
116
|
+
await sleep(delay);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Todas as tentativas falharam
|
|
122
|
+
console.error('❌ Todas as tentativas de envio falharam:', lastError);
|
|
123
|
+
|
|
124
|
+
// Fallback: Beacon API
|
|
125
|
+
if (ANTI_BLOCKING_CONFIG.useBeaconFallback && navigator.sendBeacon) {
|
|
126
|
+
console.log('🔄 Tentando Beacon API como fallback...');
|
|
127
|
+
const beaconSuccess = navigator.sendBeacon(endpoint, JSON.stringify(data));
|
|
128
|
+
|
|
129
|
+
if (beaconSuccess) {
|
|
130
|
+
console.log('✅ Beacon API bem-sucedido');
|
|
131
|
+
return { success: true, method: 'beacon' };
|
|
132
|
+
} else {
|
|
133
|
+
console.error('❌ Beacon API também falhou');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return { success: false, error: lastError?.message, attempts: ANTI_BLOCKING_CONFIG.maxRetries };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Função utilitária de delay
|
|
142
|
+
*/
|
|
143
|
+
function sleep(ms) {
|
|
144
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ── First-Party Cookies (Ad-Block Proof) ───────────────
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Define cookie first-party (não bloqueado por ad-blockers)
|
|
151
|
+
*
|
|
152
|
+
* @param {string} name - Nome do cookie
|
|
153
|
+
* @param {string} value - Valor do cookie
|
|
154
|
+
* @param {number} maxAge - Tempo de vida em segundos
|
|
155
|
+
*/
|
|
156
|
+
function setFirstPartyCookie(name, value, maxAge = ANTI_BLOCKING_CONFIG.cookieDuration) {
|
|
157
|
+
if (!isBrowser) return;
|
|
158
|
+
|
|
159
|
+
// Extrair domínio atual (para umbrella domain)
|
|
160
|
+
const currentDomain = window.location.hostname;
|
|
161
|
+
const rootDomain = currentDomain.split('.').slice(-2).join('.'); // ex: example.com
|
|
162
|
+
|
|
163
|
+
const cookieOptions = [
|
|
164
|
+
`${name}=${value}`,
|
|
165
|
+
`max-age=${maxAge}`,
|
|
166
|
+
'path=/',
|
|
167
|
+
`domain=.${rootDomain}`, // Umbrella domain para subdomínios
|
|
168
|
+
'SameSite=Lax',
|
|
169
|
+
'Secure'
|
|
170
|
+
].join('; ');
|
|
171
|
+
|
|
172
|
+
document.cookie = cookieOptions;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Obtém cookie first-party
|
|
177
|
+
*
|
|
178
|
+
* @param {string} name - Nome do cookie
|
|
179
|
+
* @returns {string|null} Valor do cookie ou null
|
|
180
|
+
*/
|
|
181
|
+
function getFirstPartyCookie(name) {
|
|
182
|
+
if (!isBrowser) return null;
|
|
183
|
+
|
|
184
|
+
const value = `; ${document.cookie}`;
|
|
185
|
+
const parts = value.split(`; ${name}=`);
|
|
186
|
+
|
|
187
|
+
if (parts.length === 2) {
|
|
188
|
+
return parts.pop().split(';').shift();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ── Lightweight Code (Evitar Patterns de Bloqueio) ─────────
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Verifica se código deve ser minificado (evitar palavras-chave de ad-blockers)
|
|
198
|
+
*
|
|
199
|
+
* @returns {boolean} True se deve minificar
|
|
200
|
+
*/
|
|
201
|
+
function shouldMinifyCode() {
|
|
202
|
+
return ANTI_BLOCKING_CONFIG.minify && isBrowser;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Remove console.logs se configurado (evitar detecção)
|
|
207
|
+
*
|
|
208
|
+
* @param {boolean} remove - Remove console.logs?
|
|
209
|
+
*/
|
|
210
|
+
function configureConsoleLogs(remove = ANTI_BLOCKING_CONFIG.noConsoleLogs) {
|
|
211
|
+
if (!isBrowser || !remove) return;
|
|
212
|
+
|
|
213
|
+
// Sobrescrever console com funções vazias
|
|
214
|
+
const noop = () => {};
|
|
215
|
+
console.log = noop;
|
|
216
|
+
console.warn = noop;
|
|
217
|
+
console.error = noop;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ── Same-Domain Protocol (Anti-Adblock) ─────────────
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Verifica se endpoint está no mesmo domínio
|
|
224
|
+
*
|
|
225
|
+
* @param {string} endpoint - Endpoint para verificar
|
|
226
|
+
* @returns {boolean} True se mesmo domínio
|
|
227
|
+
*/
|
|
228
|
+
function isSameDomain(endpoint) {
|
|
229
|
+
if (!isBrowser) return true;
|
|
230
|
+
|
|
231
|
+
const endpointUrl = new URL(endpoint, window.location.href);
|
|
232
|
+
return endpointUrl.hostname === window.location.hostname;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ── Inicialização ────────────────────────────────────────────
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Inicializa sistema de anti-blocking
|
|
239
|
+
*/
|
|
240
|
+
function initAntiBlocking() {
|
|
241
|
+
if (!isBrowser) return;
|
|
242
|
+
|
|
243
|
+
console.log('🛡️ Inicializando Anti-Blocking System...');
|
|
244
|
+
|
|
245
|
+
// 1. Detectar ad-blocker
|
|
246
|
+
const adBlockerActive = detectAdBlocker();
|
|
247
|
+
if (adBlockerActive) {
|
|
248
|
+
console.warn('⚠️ Ad-Blocker detectado - usando estratégias de resiliência');
|
|
249
|
+
// Enviar evento de ad-blocker detectado
|
|
250
|
+
if (typeof cdpTrack !== 'undefined' && cdpTrack.track) {
|
|
251
|
+
cdpTrack.track('adblocker_detected', {
|
|
252
|
+
user_agent: navigator.userAgent,
|
|
253
|
+
timestamp: Date.now()
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// 2. Configurar first-party cookies
|
|
259
|
+
const userId = getFirstPartyCookie('_cdp_uid');
|
|
260
|
+
if (!userId) {
|
|
261
|
+
const newUserId = `${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
|
262
|
+
setFirstPartyCookie('_cdp_uid', newUserId);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// 3. Configurar console logs (se necessário)
|
|
266
|
+
if (ANTI_BLOCKING_CONFIG.noConsoleLogs) {
|
|
267
|
+
configureConsoleLogs(true);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
console.log('✅ Anti-Blocking System inicializado');
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// ── Exportações ────────────────────────────────────────────────
|
|
274
|
+
|
|
275
|
+
export {
|
|
276
|
+
sendWithRetry,
|
|
277
|
+
detectAdBlocker,
|
|
278
|
+
setFirstPartyCookie,
|
|
279
|
+
getFirstPartyCookie,
|
|
280
|
+
isSameDomain,
|
|
281
|
+
configureConsoleLogs,
|
|
282
|
+
shouldMinifyCode,
|
|
283
|
+
ANTI_BLOCKING_CONFIG,
|
|
284
|
+
initAntiBlocking
|
|
285
|
+
};
|