cdp-edge 1.17.0 β 1.18.1
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/contracts/api-versions.json +12 -8
- package/dist/commands/install.js +186 -0
- package/dist/commands/setup.js +18 -1
- package/extracted-skill/tracking-events-generator/agents/attribution-agent.md +23 -23
- package/extracted-skill/tracking-events-generator/agents/bing-agent.md +8 -0
- package/extracted-skill/tracking-events-generator/agents/browser-tracking.md +172 -72
- package/extracted-skill/tracking-events-generator/agents/compliance-agent.md +20 -0
- package/extracted-skill/tracking-events-generator/agents/crm-integration-agent.md +56 -16
- package/extracted-skill/tracking-events-generator/agents/dashboard-agent.md +7 -7
- package/extracted-skill/tracking-events-generator/agents/database-agent.md +16 -8
- package/extracted-skill/tracking-events-generator/agents/debug-agent.md +13 -13
- package/extracted-skill/tracking-events-generator/agents/devops-agent.md +32 -7
- package/extracted-skill/tracking-events-generator/agents/domain-setup-agent.md +8 -0
- package/extracted-skill/tracking-events-generator/agents/email-agent.md +27 -0
- package/extracted-skill/tracking-events-generator/agents/fingerprint-agent.md +205 -0
- package/extracted-skill/tracking-events-generator/agents/google-agent.md +126 -0
- package/extracted-skill/tracking-events-generator/agents/intelligence-agent.md +90 -4
- package/extracted-skill/tracking-events-generator/agents/intelligence-scheduling.md +8 -641
- package/extracted-skill/tracking-events-generator/agents/linkedin-agent.md +116 -0
- package/extracted-skill/tracking-events-generator/agents/ltv-predictor-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/master-feedback-loop.md +68 -8
- package/extracted-skill/tracking-events-generator/agents/master-orchestrator.md +71 -34
- package/extracted-skill/tracking-events-generator/agents/memory-agent.md +127 -2
- package/extracted-skill/tracking-events-generator/agents/meta-agent.md +8 -0
- package/extracted-skill/tracking-events-generator/agents/performance-agent.md +29 -19
- package/extracted-skill/tracking-events-generator/agents/performance-optimization-agent.md +11 -1
- package/extracted-skill/tracking-events-generator/agents/pinterest-agent.md +8 -0
- package/extracted-skill/tracking-events-generator/agents/r2-setup-agent.md +8 -0
- package/extracted-skill/tracking-events-generator/agents/reddit-agent.md +8 -0
- package/extracted-skill/tracking-events-generator/agents/security-enterprise-agent.md +137 -28
- package/extracted-skill/tracking-events-generator/agents/server-tracking.md +8 -8
- package/extracted-skill/tracking-events-generator/agents/spotify-agent.md +8 -0
- package/extracted-skill/tracking-events-generator/agents/tiktok-agent.md +71 -0
- package/extracted-skill/tracking-events-generator/agents/tracking-plan-agent.md +100 -5
- package/extracted-skill/tracking-events-generator/agents/validator-agent.md +4 -0
- package/extracted-skill/tracking-events-generator/agents/webhook-agent.md +108 -0
- package/extracted-skill/tracking-events-generator/agents/whatsapp-agent.md +58 -5
- package/extracted-skill/tracking-events-generator/agents/whatsapp-ctwa-setup-agent.md +23 -15
- package/extracted-skill/tracking-events-generator/agents/youtube-agent.md +140 -25
- package/extracted-skill/tracking-events-generator/contracts/api-versions.json +12 -8
- package/package.json +2 -2
- package/server-edge-tracker/worker.js +53 -8
|
@@ -109,99 +109,199 @@ Implementado via `anti-blocking.js`:
|
|
|
109
109
|
|
|
110
110
|
## π» EXEMPLO DE CΓDIGO GERADO
|
|
111
111
|
|
|
112
|
-
### `cdpTrack.js` (SDK Principal)
|
|
112
|
+
### `cdpTrack.js` (SDK Principal β PadrΓ£o Multi-Plataforma)
|
|
113
|
+
|
|
114
|
+
> Este Γ© o padrΓ£o canΓ΄nico do cdpTrack SDK para Meta, TikTok e GA4.
|
|
115
|
+
> Cada agente de plataforma injeta seus eventos neste SDK via Browser Tracking Agent.
|
|
113
116
|
|
|
114
117
|
```javascript
|
|
115
118
|
/**
|
|
116
119
|
* cdpTrack SDK - CDP Edge Quantum Tier
|
|
117
120
|
* Browser Tracking SDK Principal
|
|
121
|
+
* Suporta: Meta Pixel, TikTok Pixel, GA4, Pinterest Tag, Reddit Pixel, Spotify Pixel
|
|
118
122
|
*/
|
|
119
123
|
|
|
120
|
-
(function(w
|
|
121
|
-
|
|
122
|
-
w._pbq.push = w._pbq.push || [];
|
|
123
|
-
w._spotify = w._spotify || {};
|
|
124
|
-
|
|
125
|
-
// Carregar configuraΓ§Γ£o
|
|
126
|
-
const config = window.cdpTrack?.config || {};
|
|
124
|
+
(function(w) {
|
|
125
|
+
'use strict';
|
|
127
126
|
|
|
128
|
-
//
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
127
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββ
|
|
128
|
+
// CORE: GeraΓ§Γ£o de event_id ΓΊnico (deduplicaΓ§Γ£o)
|
|
129
|
+
// O mesmo event_id deve ser usado no browser E no servidor (CAPI)
|
|
130
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββ
|
|
131
|
+
function generateEventId() {
|
|
132
|
+
return 'evt_' + Date.now() + '_' + Math.random().toString(36).substring(2, 11);
|
|
132
133
|
}
|
|
133
134
|
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
135
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββ
|
|
136
|
+
// CORE: Envio para Cloudflare Worker (same-domain)
|
|
137
|
+
// Usa /track no mesmo domΓnio β imune a ad-blockers
|
|
138
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββ
|
|
139
|
+
async function sendToWorker(eventName, payload) {
|
|
140
|
+
const eventId = generateEventId();
|
|
141
|
+
|
|
142
|
+
const body = {
|
|
143
|
+
event: eventName,
|
|
144
|
+
event_id: eventId, // CRΓTICO: mesmo ID usado nas CAPIs
|
|
145
|
+
url: window.location.href,
|
|
146
|
+
referrer: document.referrer,
|
|
147
|
+
timestamp: Date.now(),
|
|
148
|
+
...payload
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
// Tentativa primΓ‘ria: fetch
|
|
153
|
+
await fetch('/track', {
|
|
154
|
+
method: 'POST',
|
|
155
|
+
headers: { 'Content-Type': 'application/json' },
|
|
156
|
+
body: JSON.stringify(body),
|
|
157
|
+
keepalive: true
|
|
152
158
|
});
|
|
159
|
+
} catch (_) {
|
|
160
|
+
// Fallback: Beacon API (funciona mesmo no unload da pΓ‘gina)
|
|
161
|
+
navigator.sendBeacon('/track', JSON.stringify(body));
|
|
153
162
|
}
|
|
154
|
-
};
|
|
155
163
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
w._spotify.trackEvent('ViewContent', {
|
|
159
|
-
content_name: contentName,
|
|
160
|
-
content_id: contentId,
|
|
161
|
-
...params
|
|
162
|
-
});
|
|
163
|
-
};
|
|
164
|
+
return eventId;
|
|
165
|
+
}
|
|
164
166
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
};
|
|
167
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββ
|
|
168
|
+
// CORE: Captura de cookies first-party
|
|
169
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββ
|
|
170
|
+
function getCookie(name) {
|
|
171
|
+
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
|
|
172
|
+
return match ? decodeURIComponent(match[2]) : null;
|
|
173
|
+
}
|
|
173
174
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
175
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββ
|
|
176
|
+
// CORE: Captura de click IDs da URL (Meta, TikTok, Google)
|
|
177
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββ
|
|
178
|
+
function getClickIds() {
|
|
179
|
+
const params = new URLSearchParams(window.location.search);
|
|
180
|
+
return {
|
|
181
|
+
fbclid: params.get('fbclid') || getCookie('fbclid') || null,
|
|
182
|
+
ttclid: params.get('ttclid') || getCookie('ttclid') || null,
|
|
183
|
+
gclid: params.get('gclid') || null,
|
|
184
|
+
gbraid: params.get('gbraid') || null,
|
|
185
|
+
wbraid: params.get('wbraid') || null,
|
|
186
|
+
fbp: getCookie('_fbp') || null,
|
|
187
|
+
fbc: getCookie('_fbc') || null,
|
|
188
|
+
ttp: getCookie('_ttp') || null,
|
|
189
|
+
uid: getCookie('_cdp_uid') || null // Identity Graph first-party cookie
|
|
190
|
+
};
|
|
191
|
+
}
|
|
183
192
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
193
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββ
|
|
194
|
+
// API PΓBLICA
|
|
195
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββ
|
|
196
|
+
const cdpTrack = {
|
|
197
|
+
generateEventId,
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Rastrear evento genΓ©rico β enviado para o Worker
|
|
201
|
+
* O Worker despacha para Meta CAPI, GA4 MP, TikTok Events API etc.
|
|
202
|
+
*
|
|
203
|
+
* @param {string} eventName - Nome do evento (ex: 'Lead', 'Purchase', 'PageView')
|
|
204
|
+
* @param {Object} params - ParΓ’metros adicionais do evento
|
|
205
|
+
*/
|
|
206
|
+
track(eventName, params = {}) {
|
|
207
|
+
const clickIds = getClickIds();
|
|
208
|
+
return sendToWorker(eventName, { ...clickIds, ...params });
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Rastrear Lead (captura de formulΓ‘rio)
|
|
213
|
+
* Enviar dados PII crus β o Worker faz SHA-256 no servidor
|
|
214
|
+
*/
|
|
215
|
+
trackLead(userData = {}) {
|
|
216
|
+
const clickIds = getClickIds();
|
|
217
|
+
return sendToWorker('Lead', {
|
|
218
|
+
...clickIds,
|
|
219
|
+
email: userData.email || null, // Worker aplica SHA-256
|
|
220
|
+
phone: userData.phone || null, // Worker aplica E.164 + SHA-256
|
|
221
|
+
first_name: userData.first_name || null,
|
|
222
|
+
last_name: userData.last_name || null,
|
|
223
|
+
city: userData.city || null,
|
|
224
|
+
state: userData.state || null,
|
|
225
|
+
zip: userData.zip || null,
|
|
226
|
+
country: userData.country || 'BR'
|
|
227
|
+
});
|
|
228
|
+
},
|
|
192
229
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
230
|
+
/**
|
|
231
|
+
* Rastrear Purchase (confirmaΓ§Γ£o de compra)
|
|
232
|
+
*/
|
|
233
|
+
trackPurchase(orderData = {}) {
|
|
234
|
+
const clickIds = getClickIds();
|
|
235
|
+
return sendToWorker('Purchase', {
|
|
236
|
+
...clickIds,
|
|
237
|
+
value: orderData.value || 0,
|
|
238
|
+
currency: orderData.currency || 'BRL',
|
|
239
|
+
order_id: orderData.order_id || null,
|
|
240
|
+
content_name: orderData.product || null
|
|
241
|
+
});
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Rastrear PageView β chamar no load da pΓ‘gina
|
|
246
|
+
*/
|
|
247
|
+
trackPageView() {
|
|
248
|
+
const clickIds = getClickIds();
|
|
249
|
+
return sendToWorker('PageView', { ...clickIds });
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Rastrear InitiateCheckout
|
|
254
|
+
*/
|
|
255
|
+
trackInitiateCheckout(checkoutData = {}) {
|
|
256
|
+
const clickIds = getClickIds();
|
|
257
|
+
return sendToWorker('InitiateCheckout', {
|
|
258
|
+
...clickIds,
|
|
259
|
+
value: checkoutData.value || 0,
|
|
260
|
+
currency: checkoutData.currency || 'BRL'
|
|
261
|
+
});
|
|
262
|
+
}
|
|
200
263
|
};
|
|
201
264
|
|
|
202
|
-
|
|
265
|
+
// Expor no window
|
|
266
|
+
w.cdpTrack = cdpTrack;
|
|
267
|
+
|
|
268
|
+
// Auto page_view no load
|
|
269
|
+
if (document.readyState === 'loading') {
|
|
270
|
+
document.addEventListener('DOMContentLoaded', () => cdpTrack.trackPageView());
|
|
271
|
+
} else {
|
|
272
|
+
cdpTrack.trackPageView();
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
})(window);
|
|
203
276
|
```
|
|
204
277
|
|
|
278
|
+
### Uso tΓpico no HTML do cliente
|
|
279
|
+
|
|
280
|
+
```html
|
|
281
|
+
<!-- 1. Carregar o SDK -->
|
|
282
|
+
<script src="/tracking/cdpTrack.js"></script>
|
|
283
|
+
|
|
284
|
+
<!-- 2. Rastrear lead ao submeter formulΓ‘rio -->
|
|
285
|
+
<script>
|
|
286
|
+
document.getElementById('lead-form').addEventListener('submit', function(e) {
|
|
287
|
+
cdpTrack.trackLead({
|
|
288
|
+
email: document.getElementById('email').value,
|
|
289
|
+
phone: document.getElementById('phone').value,
|
|
290
|
+
first_name: document.getElementById('name').value
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
</script>
|
|
294
|
+
|
|
295
|
+
<!-- 3. Rastrear checkout (botΓ£o de compra) -->
|
|
296
|
+
<script>
|
|
297
|
+
document.getElementById('buy-btn').addEventListener('click', function() {
|
|
298
|
+
cdpTrack.trackInitiateCheckout({ value: 97.00, currency: 'BRL' });
|
|
299
|
+
});
|
|
300
|
+
</script>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
> **Nota:** O Worker recebe os dados crus, aplica SHA-256, e despacha para Meta CAPI v22.0, GA4 MP, TikTok Events API v1.3 e demais plataformas configuradas β tudo em paralelo via `Promise.allSettled`.
|
|
304
|
+
|
|
205
305
|
---
|
|
206
306
|
|
|
207
307
|
## π§ INTEGRAΓΓO COM OUTROS AGENTES
|
|
@@ -2044,6 +2044,26 @@ async function handleGetCurrentPolicy(request, env) {
|
|
|
2044
2044
|
- **security-enterprise-agent.md**: Usa encryption de PII para LGPD/GDPR
|
|
2045
2045
|
- **attribution-agent.md**: Respeita consentimento para analytics e marketing
|
|
2046
2046
|
- **master-orchestrator.md**: Implementa middleware de consentimento antes de tracking
|
|
2047
|
+
- **validator-agent.md**: O Compliance Agent DEVE ser consultado pelo Validator Agent para verificar conformidade de PII. Fluxo:
|
|
2048
|
+
|
|
2049
|
+
```
|
|
2050
|
+
validator-agent (auditoria do cΓ³digo gerado)
|
|
2051
|
+
βββΊ checkComplianceCompliance(generatedCode)
|
|
2052
|
+
ββ Verificar: SHA-256 aplicado em todos os campos PII (em, ph, fn, ln)?
|
|
2053
|
+
ββ Verificar: Google Consent Mode v2 implementado (ad_storage, analytics_storage)?
|
|
2054
|
+
ββ Verificar: url_passthrough: true ativo?
|
|
2055
|
+
ββ Verificar: PII nunca logada em plaintext?
|
|
2056
|
+
ββ Verificar: opt-in explΓcito antes de tracking de marketing?
|
|
2057
|
+
|
|
2058
|
+
// No validator-agent, chamar:
|
|
2059
|
+
const complianceCheck = await validateComplianceRequirements(generatedBrowserCode, generatedWorkerCode);
|
|
2060
|
+
if (!complianceCheck.passed) {
|
|
2061
|
+
// Bloquear entrega e reportar issues ao Master Orchestrator
|
|
2062
|
+
return { status: 'BLOCKED', issues: complianceCheck.issues };
|
|
2063
|
+
}
|
|
2064
|
+
```
|
|
2065
|
+
|
|
2066
|
+
- **google-agent.md**: Consent Mode v2 gerado por este agente valida conformidade detectada pelo Compliance Agent
|
|
2047
2067
|
|
|
2048
2068
|
---
|
|
2049
2069
|
|
|
@@ -4,6 +4,46 @@ VocΓͺ Γ© o **Agente de IntegraΓ§Γ£o CRM do CDP Edge**. Sua responsabilidade: **c
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## β
REGRAS CRΓTICAS
|
|
8
|
+
|
|
9
|
+
0. **CONSULTA OBRIGATΓRIA Γ MEMΓRIA**: Extraia as Credenciais de APIs CRM e Endpoints de IntegraΓ§Γ£o (`CRM_API_KEY`, `CRM_ENDPOINT`, `CRM_WEBHOOK_SECRET`) consultando ativamente o "memory-agent.json". Solicite ao Orquestrador tudo o que faltar. Execute integraΓ§Γ΅es de CRM exclusivamente com os dados oficiais guardados na MemΓ³ria para garantir alinhamento sistΓͺmico.
|
|
10
|
+
1. Cloudflare-Only: Sem dependΓͺncias externas.
|
|
11
|
+
2. Same-Domain: Worker no domΓnio do site (anti-adblock).
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## π FLUXO DE ATIVAΓΓO (Como este agente Γ© chamado)
|
|
16
|
+
|
|
17
|
+
O CRM Integration Agent Γ© ativado pelo **Webhook Agent** apΓ³s confirmaΓ§Γ£o de compra ou captura de lead:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Webhook Agent (purchase confirmado)
|
|
21
|
+
βββΊ ctx.waitUntil(syncToCRM(env, 'purchase', payload))
|
|
22
|
+
β
|
|
23
|
+
ββ Criar/atualizar contato no CRM com status 'customer'
|
|
24
|
+
ββ Criar negΓ³cio/oportunidade com valor da compra
|
|
25
|
+
ββ Atualizar D1 com CRM_CONTACT_ID para rastreamento futuro
|
|
26
|
+
|
|
27
|
+
Webhook Agent (lead capturado via /track)
|
|
28
|
+
βββΊ ctx.waitUntil(syncToCRM(env, 'lead', payload))
|
|
29
|
+
β
|
|
30
|
+
ββ Criar contato no CRM com status 'lead'
|
|
31
|
+
ββ Registrar no D1 para cruzamento futuro
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Assinatura da funΓ§Γ£o exportada (injetada no Worker):**
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
// Injetada no worker.js pelo CRM Integration Agent
|
|
38
|
+
export async function syncToCRM(env, eventType, payload) {
|
|
39
|
+
// eventType: 'lead' | 'purchase' | 'checkout_abandoned'
|
|
40
|
+
// payload: { email, name, product, value, order_id, phone }
|
|
41
|
+
// Retorna: { success: boolean, crm_contact_id: string | null }
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
7
47
|
## π― OBJETIVO PRINCIPAL
|
|
8
48
|
|
|
9
49
|
Implementar **integraΓ§Γ£o bidirecional** entre CDP Edge D1 e CRMs externos, permitindo que dados de tracking (leads, purchases, user journeys) fluam automaticamente para sistemas de vendas, marketing e atendimento, eliminando importaΓ§Γ΅es manuais e maximizando conversΓ£o.
|
|
@@ -604,8 +644,8 @@ export const PURCHASE_FIELD_MAPPINGS = {
|
|
|
604
644
|
|
|
605
645
|
```javascript
|
|
606
646
|
// Sincronizar leads do D1 para CRM em batch
|
|
607
|
-
export async function syncLeadsToCRM(hours = 24, batchSize = 50) {
|
|
608
|
-
const leads = await DB.prepare(`
|
|
647
|
+
export async function syncLeadsToCRM(env, hours = 24, batchSize = 50) {
|
|
648
|
+
const leads = await env.DB.prepare(`
|
|
609
649
|
SELECT * FROM leads
|
|
610
650
|
WHERE created_at > datetime('now', '-${hours} hours')
|
|
611
651
|
ORDER BY created_at DESC
|
|
@@ -691,8 +731,8 @@ async function sendLeadsBatchToCRM(leadsBatch) {
|
|
|
691
731
|
};
|
|
692
732
|
}
|
|
693
733
|
|
|
694
|
-
async function markLeadAsSynced(leadId) {
|
|
695
|
-
await DB.prepare(`
|
|
734
|
+
async function markLeadAsSynced(leadId, env) {
|
|
735
|
+
await env.DB.prepare(`
|
|
696
736
|
UPDATE leads SET crm_synced = 1, crm_synced_at = datetime('now')
|
|
697
737
|
WHERE id = ?
|
|
698
738
|
`).bind(leadId).run();
|
|
@@ -703,8 +743,8 @@ async function markLeadAsSynced(leadId) {
|
|
|
703
743
|
|
|
704
744
|
```javascript
|
|
705
745
|
// Sincronizar compras do D1 para CRM em batch
|
|
706
|
-
export async function syncPurchasesToCRM(hours = 24, batchSize = 20) {
|
|
707
|
-
const purchases = await DB.prepare(`
|
|
746
|
+
export async function syncPurchasesToCRM(env, hours = 24, batchSize = 20) {
|
|
747
|
+
const purchases = await env.DB.prepare(`
|
|
708
748
|
SELECT p.*, l.email
|
|
709
749
|
FROM purchases p
|
|
710
750
|
LEFT JOIN leads l ON p.lead_id = l.id
|
|
@@ -792,8 +832,8 @@ async function sendPurchasesBatchToCRM(purchasesBatch) {
|
|
|
792
832
|
};
|
|
793
833
|
}
|
|
794
834
|
|
|
795
|
-
async function markPurchaseAsSynced(purchaseId) {
|
|
796
|
-
await DB.prepare(`
|
|
835
|
+
async function markPurchaseAsSynced(purchaseId, env) {
|
|
836
|
+
await env.DB.prepare(`
|
|
797
837
|
UPDATE purchases SET crm_synced = 1, crm_synced_at = datetime('now')
|
|
798
838
|
WHERE id = ?
|
|
799
839
|
`).bind(purchaseId).run();
|
|
@@ -845,8 +885,8 @@ export async function handleCRMWebhook(request, env) {
|
|
|
845
885
|
}
|
|
846
886
|
}
|
|
847
887
|
|
|
848
|
-
async function updateLeadStageFromCRM(payload) {
|
|
849
|
-
await DB.prepare(`
|
|
888
|
+
async function updateLeadStageFromCRM(payload, env) {
|
|
889
|
+
await env.DB.prepare(`
|
|
850
890
|
UPDATE leads SET crm_stage = ?, crm_stage_updated_at = datetime('now')
|
|
851
891
|
WHERE email = ?
|
|
852
892
|
`).bind(payload.stage, payload.email).run();
|
|
@@ -854,8 +894,8 @@ async function updateLeadStageFromCRM(payload) {
|
|
|
854
894
|
console.log(`Stage do lead ${payload.email} atualizado para: ${payload.stage}`);
|
|
855
895
|
}
|
|
856
896
|
|
|
857
|
-
async function updateDealStatusFromCRM(payload) {
|
|
858
|
-
await DB.prepare(`
|
|
897
|
+
async function updateDealStatusFromCRM(payload, env) {
|
|
898
|
+
await env.DB.prepare(`
|
|
859
899
|
UPDATE purchases SET crm_deal_status = ?, crm_deal_status_updated_at = datetime('now')
|
|
860
900
|
WHERE transaction_id = ?
|
|
861
901
|
`).bind(payload.status, payload.transaction_id).run();
|
|
@@ -863,8 +903,8 @@ async function updateDealStatusFromCRM(payload) {
|
|
|
863
903
|
console.log(`Status da compra ${payload.transaction_id} atualizado para: ${payload.status}`);
|
|
864
904
|
}
|
|
865
905
|
|
|
866
|
-
async function updateLeadScoreFromCRM(payload) {
|
|
867
|
-
await DB.prepare(`
|
|
906
|
+
async function updateLeadScoreFromCRM(payload, env) {
|
|
907
|
+
await env.DB.prepare(`
|
|
868
908
|
UPDATE leads SET lead_score = ?, lead_score_updated_at = datetime('now')
|
|
869
909
|
WHERE email = ?
|
|
870
910
|
`).bind(payload.lead_score, payload.email).run();
|
|
@@ -971,7 +1011,7 @@ export async function registerCRMWebhooks(crmType, webhookUrl) {
|
|
|
971
1011
|
};
|
|
972
1012
|
|
|
973
1013
|
// Salvar configuraΓ§Γ£o no D1
|
|
974
|
-
await DB.prepare(`
|
|
1014
|
+
await env.DB.prepare(`
|
|
975
1015
|
INSERT INTO crm_webhook_config (webhook_url, crm_type, events, signature_enabled)
|
|
976
1016
|
VALUES (?, ?, ?, ?)
|
|
977
1017
|
`).bind(
|
|
@@ -986,7 +1026,7 @@ export async function registerCRMWebhooks(crmType, webhookUrl) {
|
|
|
986
1026
|
|
|
987
1027
|
// Endpoint de saΓΊde da integraΓ§Γ£o
|
|
988
1028
|
export async function handleCRMHealthCheck(request, env) {
|
|
989
|
-
const stats = await DB.prepare(`
|
|
1029
|
+
const stats = await env.DB.prepare(`
|
|
990
1030
|
SELECT
|
|
991
1031
|
COUNT(*) as total_leads,
|
|
992
1032
|
COUNT(CASE WHEN crm_synced = 1 THEN 1 END) as synced_leads,
|
|
@@ -96,16 +96,16 @@ Definir o Dashboard como um **Centro de Comando de Dados** que equilibra:
|
|
|
96
96
|
**ImplementaΓ§Γ£o:**
|
|
97
97
|
```javascript
|
|
98
98
|
// Carregar dados do cache
|
|
99
|
-
const fetchMetrics = async (forceRefresh = false) => {
|
|
99
|
+
const fetchMetrics = async (env, forceRefresh = false) => {
|
|
100
100
|
const cacheKey = 'dashboard_metrics';
|
|
101
|
-
const cached = await
|
|
101
|
+
const cached = await env.GEO_CACHE.get(cacheKey);
|
|
102
102
|
|
|
103
103
|
if (cached && !forceRefresh) {
|
|
104
104
|
return JSON.parse(cached);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
// Cache miss ou refresh forΓ§ado β consultar D1
|
|
108
|
-
const metrics = await DB.prepare(`
|
|
108
|
+
const metrics = await env.DB.prepare(`
|
|
109
109
|
SELECT
|
|
110
110
|
AVG(heat_score) as avg_heat,
|
|
111
111
|
COUNT(DISTINCT fingerprint) as total_users,
|
|
@@ -115,7 +115,7 @@ const fetchMetrics = async (forceRefresh = false) => {
|
|
|
115
115
|
`).all();
|
|
116
116
|
|
|
117
117
|
// Salvar no KV com TTL de 1 hora
|
|
118
|
-
await
|
|
118
|
+
await env.GEO_CACHE.put(cacheKey, JSON.stringify(metrics), { expirationTtl: 3600 });
|
|
119
119
|
|
|
120
120
|
return metrics;
|
|
121
121
|
};
|
|
@@ -217,13 +217,13 @@ export const DASHBOARD_API = {
|
|
|
217
217
|
};
|
|
218
218
|
|
|
219
219
|
// HANDLER DE SINCronizaΓΓO (atualizaΓ§Γ£o de cache)
|
|
220
|
-
export async function invalidateCache(domain, pattern) {
|
|
220
|
+
export async function invalidateCache(domain, pattern, env) {
|
|
221
221
|
const deletePattern = `${domain}:${pattern}`;
|
|
222
222
|
|
|
223
223
|
// Deletar do KV
|
|
224
|
-
const keys = await
|
|
224
|
+
const keys = await env.GEO_CACHE.list({ prefix: deletePattern });
|
|
225
225
|
for (const key of keys.keys) {
|
|
226
|
-
await
|
|
226
|
+
await env.GEO_CACHE.delete(key);
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
// Retornar contagem
|
|
@@ -6,6 +6,14 @@ Enquanto o `server-tracking-agent` define **o que o Worker FAZ**, vocΓͺ define *
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## β
REGRAS CRΓTICAS
|
|
10
|
+
|
|
11
|
+
0. **CONSULTA OBRIGATΓRIA Γ MEMΓRIA**: Extraia os IDs de Recursos Cloudflare (`D1_DATABASE_ID`, `KV_ID`, `R2_BUCKET_NAME`, `ZONE_ID`) e configuraΓ§Γ΅es de bindings consultando ativamente o "memory-agent.json". Solicite ao Orquestrador tudo o que faltar. Execute configuraΓ§Γ΅es de infraestrutura exclusivamente com os dados oficiais guardados na MemΓ³ria para garantir alinhamento sistΓͺmico.
|
|
12
|
+
1. Cloudflare-Only: Sem dependΓͺncias externas.
|
|
13
|
+
2. Same-Domain: Worker no domΓnio do site (anti-adblock).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
9
17
|
## ποΈ RESPONSABILIDADES EXCLUSIVAS
|
|
10
18
|
|
|
11
19
|
| DomΓnio | VocΓͺ Γ© dono de |
|
|
@@ -70,7 +78,7 @@ crons = ["0 2 * * 7", "0 3 1 * *"]
|
|
|
70
78
|
- **ID:** `SEU_D1_DATABASE_ID`
|
|
71
79
|
- **RegiΓ£o:** ENAM (US East)
|
|
72
80
|
- **Engine:** SQLite (Cloudflare D1)
|
|
73
|
-
- **Tabelas ativas:**
|
|
81
|
+
- **Tabelas ativas:** 24 (core: 13, migrate-v6: 1, Enterprise Fases 1-4: 10)
|
|
74
82
|
|
|
75
83
|
### Schema Completo (ProduΓ§Γ£o)
|
|
76
84
|
|
|
@@ -251,7 +259,7 @@ CREATE INDEX IF NOT EXISTS idx_wa_ctwa_clid ON whatsapp_contacts(ctwa_clid);
|
|
|
251
259
|
CREATE INDEX IF NOT EXISTS idx_wa_created_at ON whatsapp_contacts(created_at);
|
|
252
260
|
```
|
|
253
261
|
> **Migration:** `migrate-v6.sql` β aplicar com `wrangler d1 execute cdp-edge-db --file=migrate-v6.sql --remote`
|
|
254
|
-
> **Tabelas ativas apΓ³s v6:**
|
|
262
|
+
> **Tabelas ativas apΓ³s v6:** 14 (core: 13 + whatsapp_contacts)
|
|
255
263
|
|
|
256
264
|
---
|
|
257
265
|
|
|
@@ -305,9 +313,9 @@ ctx.waitUntil(
|
|
|
305
313
|
|
|
306
314
|
---
|
|
307
315
|
|
|
308
|
-
## π¬ BINDING 2 β QUEUES (`env.
|
|
316
|
+
## π¬ BINDING 2 β QUEUES (`env.RETRY_QUEUE`) β β
Configurado
|
|
309
317
|
|
|
310
|
-
> **Status:**
|
|
318
|
+
> **Status:** Ativo em produΓ§Γ£o β `wrangler.toml` com `RETRY_QUEUE` binding e consumer configurados.
|
|
311
319
|
|
|
312
320
|
### ConfiguraΓ§Γ£o no `wrangler.toml`
|
|
313
321
|
```toml
|
|
@@ -379,9 +387,9 @@ Queue Consumer (assΓncrono)
|
|
|
379
387
|
|
|
380
388
|
---
|
|
381
389
|
|
|
382
|
-
## ποΈ BINDING 3 β KV NAMESPACE (`env.GEO_CACHE`) β
|
|
390
|
+
## ποΈ BINDING 3 β KV NAMESPACE (`env.GEO_CACHE`) β β
Configurado
|
|
383
391
|
|
|
384
|
-
> **Status:**
|
|
392
|
+
> **Status:** Ativo em produΓ§Γ£o β usado para geo cache, fraud blocklist, fraud velocity counters e A/B test cache.
|
|
385
393
|
|
|
386
394
|
### ConfiguraΓ§Γ£o no `wrangler.toml`
|
|
387
395
|
```toml
|
|
@@ -540,7 +548,7 @@ async function runIntelligenceAgent(cron, env) {
|
|
|
540
548
|
| `META_TEST_CODE` | β οΈ Reconfigurar | SΓ³ testes | meta-agent |
|
|
541
549
|
| `META_AD_ACCOUNT_ID` | β οΈ Reconfigurar | Customer Match | meta-agent |
|
|
542
550
|
| `META_AUDIENCE_ID` | β οΈ Reconfigurar | Customer Match | meta-agent |
|
|
543
|
-
| `
|
|
551
|
+
| `WHATSAPP_ACCESS_TOKEN` | β οΈ Reconfigurar | WhatsApp | whatsapp-agent |
|
|
544
552
|
| `WHATSAPP_PHONE_NUMBER_ID` | β οΈ Reconfigurar | WhatsApp | whatsapp-agent |
|
|
545
553
|
| `RESEND_API_KEY` | β οΈ Reconfigurar | Email | email-agent |
|
|
546
554
|
| `RESEND_FROM_EMAIL` | β οΈ Reconfigurar | Email | email-agent |
|
|
@@ -552,7 +560,7 @@ async function runIntelligenceAgent(cron, env) {
|
|
|
552
560
|
wrangler secret put META_ACCESS_TOKEN
|
|
553
561
|
wrangler secret put GA4_API_SECRET
|
|
554
562
|
wrangler secret put TIKTOK_ACCESS_TOKEN
|
|
555
|
-
wrangler secret put
|
|
563
|
+
wrangler secret put WHATSAPP_ACCESS_TOKEN
|
|
556
564
|
wrangler secret put WHATSAPP_PHONE_NUMBER_ID
|
|
557
565
|
wrangler secret put RESEND_API_KEY
|
|
558
566
|
wrangler secret put RESEND_FROM_EMAIL
|
|
@@ -56,9 +56,9 @@ export function logWorker(level, category, message, context = {}) {
|
|
|
56
56
|
console.log(`[${level}] [${category}] ${message}`, JSON.stringify(context));
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
async function persistLogEntry(logEntry) {
|
|
59
|
+
async function persistLogEntry(env, logEntry) {
|
|
60
60
|
try {
|
|
61
|
-
await DB.prepare(`
|
|
61
|
+
await env.DB.prepare(`
|
|
62
62
|
INSERT INTO worker_logs (timestamp, level, category, message, context, session_id, request_id)
|
|
63
63
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
64
64
|
`).bind(
|
|
@@ -82,7 +82,7 @@ async function dispatchEventToMeta(event, userContext) {
|
|
|
82
82
|
try {
|
|
83
83
|
const response = await fetch('https://graph.facebook.com/v22.0/events', {
|
|
84
84
|
method: 'POST',
|
|
85
|
-
headers: { 'Authorization': `Bearer ${META_ACCESS_TOKEN}` },
|
|
85
|
+
headers: { 'Authorization': `Bearer ${env.META_ACCESS_TOKEN}` },
|
|
86
86
|
body: JSON.stringify(event)
|
|
87
87
|
});
|
|
88
88
|
|
|
@@ -221,7 +221,7 @@ cdpTrack.track = function(eventName, params) {
|
|
|
221
221
|
};
|
|
222
222
|
|
|
223
223
|
// Enviar para Worker
|
|
224
|
-
fetch('/
|
|
224
|
+
fetch('/track', {
|
|
225
225
|
method: 'POST',
|
|
226
226
|
headers: { 'Content-Type': 'application/json' },
|
|
227
227
|
body: JSON.stringify(eventPayload)
|
|
@@ -331,7 +331,7 @@ export async function handleDebugRequest(request, env) {
|
|
|
331
331
|
}
|
|
332
332
|
|
|
333
333
|
async function getApiHealth(platform) {
|
|
334
|
-
const recentFailures = await DB.prepare(`
|
|
334
|
+
const recentFailures = await env.DB.prepare(`
|
|
335
335
|
SELECT
|
|
336
336
|
COUNT(*) as failure_count,
|
|
337
337
|
MAX(created_at) as last_failure_at
|
|
@@ -339,7 +339,7 @@ async function getApiHealth(platform) {
|
|
|
339
339
|
WHERE platform = ? AND created_at > datetime('now', '-1 hour')
|
|
340
340
|
`).bind(platform).get();
|
|
341
341
|
|
|
342
|
-
const recentSuccesses = await DB.prepare(`
|
|
342
|
+
const recentSuccesses = await env.DB.prepare(`
|
|
343
343
|
SELECT COUNT(*) as success_count
|
|
344
344
|
FROM events_log
|
|
345
345
|
WHERE platform = ? AND status = 'success' AND created_at > datetime('now', '-1 hour')
|
|
@@ -394,7 +394,7 @@ export async function handleHealthCheck(request, env) {
|
|
|
394
394
|
}
|
|
395
395
|
|
|
396
396
|
async function getSimpleApiHealth(platform) {
|
|
397
|
-
const lastSuccess = await DB.prepare(`
|
|
397
|
+
const lastSuccess = await env.DB.prepare(`
|
|
398
398
|
SELECT created_at
|
|
399
399
|
FROM events_log
|
|
400
400
|
WHERE platform = ? AND status = 'success'
|
|
@@ -402,7 +402,7 @@ async function getSimpleApiHealth(platform) {
|
|
|
402
402
|
LIMIT 1
|
|
403
403
|
`).bind(platform).get();
|
|
404
404
|
|
|
405
|
-
const lastFailure = await DB.prepare(`
|
|
405
|
+
const lastFailure = await env.DB.prepare(`
|
|
406
406
|
SELECT created_at
|
|
407
407
|
FROM api_failures
|
|
408
408
|
WHERE platform = ?
|
|
@@ -433,7 +433,7 @@ export async function handleEventsLogRequest(request, env) {
|
|
|
433
433
|
const limit = parseInt(url.searchParams.get('limit') || '50');
|
|
434
434
|
const hours = parseInt(url.searchParams.get('hours') || '24');
|
|
435
435
|
|
|
436
|
-
const events = await DB.prepare(`
|
|
436
|
+
const events = await env.DB.prepare(`
|
|
437
437
|
SELECT
|
|
438
438
|
event_name,
|
|
439
439
|
platform,
|
|
@@ -485,7 +485,7 @@ export async function handleEventsLogRequest(request, env) {
|
|
|
485
485
|
|
|
486
486
|
- [ ] **Envio de eventos para Worker:**
|
|
487
487
|
- [ ] Verificar Network tab em Developer Tools
|
|
488
|
-
- [ ] Confirmar requisiΓ§Γ£o para `/
|
|
488
|
+
- [ ] Confirmar requisiΓ§Γ£o para `/track`
|
|
489
489
|
- [ ] Verificar status da resposta (deve ser 200 OK)
|
|
490
490
|
- [ ] Verificar payload enviado (deve conter event_name, params, timestamp)
|
|
491
491
|
|
|
@@ -1033,7 +1033,7 @@ export async function handleEventsLogRequest(request, env) {
|
|
|
1033
1033
|
const limit = parseInt(url.searchParams.get('limit') || '50');
|
|
1034
1034
|
const hours = parseInt(url.searchParams.get('hours') || '24');
|
|
1035
1035
|
|
|
1036
|
-
const events = await DB.prepare(`
|
|
1036
|
+
const events = await env.DB.prepare(`
|
|
1037
1037
|
SELECT event_name, platform, status, error_message, created_at
|
|
1038
1038
|
FROM events_log
|
|
1039
1039
|
WHERE created_at > datetime('now', '-${hours} hours')
|
|
@@ -1057,7 +1057,7 @@ export async function handleBrowserLogs(request, env) {
|
|
|
1057
1057
|
|
|
1058
1058
|
// Persistir logs do browser no D1
|
|
1059
1059
|
for (const log of logs) {
|
|
1060
|
-
await DB.prepare(`
|
|
1060
|
+
await env.DB.prepare(`
|
|
1061
1061
|
INSERT INTO browser_logs (timestamp, level, category, message, context, session_id, page_url)
|
|
1062
1062
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
1063
1063
|
`).bind(
|
|
@@ -1182,7 +1182,7 @@ window.pbDebugLogger = logger;
|
|
|
1182
1182
|
**PossΓveis Causas:**
|
|
1183
1183
|
|
|
1184
1184
|
1. **Evento nΓ£o estΓ‘ sendo enviado para a plataforma**
|
|
1185
|
-
- Verificar se `/
|
|
1185
|
+
- Verificar se `/track` estΓ‘ recebendo o evento
|
|
1186
1186
|
- Consultar `/api/events-log` para ver se evento foi processado
|
|
1187
1187
|
- Verificar logs do Worker: `wrangler tail`
|
|
1188
1188
|
|