cdp-edge 2.5.9 → 2.6.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.
Files changed (47) hide show
  1. package/README.md +247 -211
  2. package/bin/cdp-edge.js +1 -0
  3. package/contracts/agent-versions.json +2 -2
  4. package/dist/commands/infra.js +1 -1
  5. package/dist/commands/server.js +38 -33
  6. package/dist/commands/setup.js +3 -0
  7. package/dist/commands/validate.js +251 -236
  8. package/dist/sdk/cdpTrack.js +6 -4
  9. package/dist/sdk/cdpTrack.min.js +4 -4
  10. package/dist/sdk/install-snippet.html +1 -1
  11. package/extracted-skill/tracking-events-generator/INTEGRACAO-COMPLETA.md +4 -4
  12. package/extracted-skill/tracking-events-generator/Premium-Tracking-Intelligence-Resumo.md +3 -3
  13. package/extracted-skill/tracking-events-generator/agents/master-orchestrator.md +78 -33
  14. package/extracted-skill/tracking-events-generator/agents/whatsapp-agent.md +562 -93
  15. package/extracted-skill/tracking-events-generator/integration-test.js +3 -3
  16. package/extracted-skill/tracking-events-generator/knowledge-base.md +12 -12
  17. package/extracted-skill/tracking-events-generator/models/checkout-proprio.md +1 -1
  18. package/extracted-skill/tracking-events-generator/models/multi-step-checkout.md +4 -4
  19. package/extracted-skill/tracking-events-generator/models/reddit/conversions-api-template.js +1 -1
  20. package/extracted-skill/tracking-events-generator/models/scenarios/behavior-engine.js +1 -1
  21. package/extracted-skill/tracking-events-generator/models/scenarios/sales-page-logic.md +1 -1
  22. package/extracted-skill/tracking-events-generator/models/trafego-direto.md +7 -7
  23. package/package.json +2 -2
  24. package/server-edge-tracker/.client.env.example +5 -0
  25. package/server-edge-tracker/deploy-client.cjs +47 -31
  26. package/server-edge-tracker/index.ts +1267 -1204
  27. package/server-edge-tracker/modules/db.ts +2 -2
  28. package/server-edge-tracker/modules/dispatch/meta.ts +3 -0
  29. package/server-edge-tracker/modules/dispatch/tiktok.ts +1 -0
  30. package/server-edge-tracker/modules/dispatch/whatsapp.ts +5 -2
  31. package/server-edge-tracker/modules/utils.ts +1 -1
  32. package/server-edge-tracker/types.ts +3 -0
  33. package/server-edge-tracker/wrangler.toml +2 -0
  34. package/templates/checkout-proprio.md +1 -1
  35. package/templates/install/CLAUDE.md +1 -1
  36. package/templates/multi-step-checkout.md +4 -4
  37. package/templates/reddit/conversions-api-template.js +1 -1
  38. package/templates/scenarios/behavior-engine.js +1 -1
  39. package/templates/scenarios/sales-page-logic.md +1 -1
  40. package/templates/trafego-direto.md +7 -7
  41. package/templates/vsl-page.md +2 -2
  42. package/extracted-skill/tracking-events-generator/agents/whatsapp-ctwa-setup-agent.md +0 -707
  43. package/extracted-skill/tracking-events-generator/agents/zapman-agent.md +0 -189
  44. package/server-edge-tracker/.client.env +0 -5
  45. package/server-edge-tracker/dist-check/README.md +0 -1
  46. package/server-edge-tracker/dist-check/index.js +0 -5164
  47. package/server-edge-tracker/dist-check/index.js.map +0 -8
@@ -1,4 +1,4 @@
1
- /**
1
+ /**
2
2
  * INTEGRATION TEST - CDP Edge (Quantum Tier)
3
3
  *
4
4
  * Sistema de validação end-to-end do Premium Tracking Intelligence
@@ -13,8 +13,8 @@ const isBrowser = typeof window !== 'undefined';
13
13
  // ── Configurações de Teste ─────────────────────────────
14
14
 
15
15
  const TEST_CONFIG = {
16
- endpoint: '/api/tracking',
17
- healthEndpoint: '/api/health',
16
+ endpoint: '/track',
17
+ healthEndpoint: '/health',
18
18
  timeout: 10000, // 10 segundos
19
19
  testEvents: [
20
20
  'PageView',
@@ -1523,7 +1523,7 @@ Obrigado → PageView (+ Lead apenas se não foi disparado no formulário
1523
1523
 
1524
1524
  ## PASSO 6 — MODO SERVER-SIDE (quando solicitado)
1525
1525
 
1526
- > **Quando usar:** o usuário pede tracking server-side, CAPI, Measurement Protocol, "evitar bloqueio de adblocker", ou quer o endpoint `/api/tracking`.
1526
+ > **Quando usar:** o usuário pede tracking server-side, CAPI, Measurement Protocol, "evitar bloqueio de adblocker", ou quer o endpoint `/track`.
1527
1527
 
1528
1528
  ### Por que server-side existe
1529
1529
 
@@ -1537,9 +1537,9 @@ Browser (tracking.js)
1537
1537
  ├── gera event_id único
1538
1538
  ├── lê cookies: _fbp, _fbc, _ttp, _ga
1539
1539
  ├── captura UTMs da URL (utm_source, utm_medium, utm_campaign, utm_content, utm_term)
1540
- └── POST /api/tracking → { event_name, event_id, cookies, utms, user_data, page_url }
1540
+ └── POST /track → { event_name, event_id, cookies, utms, user_data, page_url }
1541
1541
 
1542
- Servidor Node.js (/api/tracking)
1542
+ Servidor Node.js (/track)
1543
1543
  ├── recebe payload do browser
1544
1544
  ├── adiciona: IP real, User-Agent do header
1545
1545
  ├── SHA256 hash: email, phone, nome, cidade, estado, CEP, país
@@ -1615,7 +1615,7 @@ const getCookies = () => ({
1615
1615
  const sendServerEvent = (eventName, eventId, payload = {}) => {
1616
1616
  if (!isBrowser) return;
1617
1617
  // Não usar await — deixar rodar em paralelo com o event client-side
1618
- fetch('/api/tracking', {
1618
+ fetch('/track', {
1619
1619
  method: 'POST',
1620
1620
  headers: { 'Content-Type': 'application/json' },
1621
1621
  body: JSON.stringify({
@@ -1662,12 +1662,12 @@ export const trackLead = async (params = {}) => {
1662
1662
 
1663
1663
  ---
1664
1664
 
1665
- ### PASSO 6.3 — Endpoint `/api/tracking` (Node.js / Next.js API Route)
1665
+ ### PASSO 6.3 — Endpoint `/track` (Node.js / Next.js API Route)
1666
1666
 
1667
1667
  ```js
1668
- // Node.js Express: src/api/tracking.js
1669
- // Next.js App Router: app/api/tracking/route.js
1670
- // Next.js Pages Router: pages/api/tracking.js
1668
+ // Node.js Express: src/track.js
1669
+ // Next.js App Router: app/track/route.js
1670
+ // Next.js Pages Router: pages/track.js
1671
1671
 
1672
1672
  import crypto from 'crypto';
1673
1673
  import CONFIG from '../tracking/tracking.config.js'; // ajustar path
@@ -1984,7 +1984,7 @@ O CDP Edge recomenda o uso de **Cloudflare Workers (Quantum Tier)** como endpoin
1984
1984
 
1985
1985
  ## PASSO 6.6 — Cloudflare Workers + D1 (Full Core Tracking)
1986
1986
 
1987
- > **Quando usar:** O padrão ouro do CDP Edge. Roda o endpoint `/api/tracking` no Cloudflare Workers e salva todos os eventos e perfis no banco D1 para atribuição precisa.
1987
+ > **Quando usar:** O padrão ouro do CDP Edge. Roda o endpoint `/track` no Cloudflare Workers e salva todos os eventos e perfis no banco D1 para atribuição precisa.
1988
1988
 
1989
1989
  ### Vantagens da Infraestrutura Cloudflare Native
1990
1990
 
@@ -2465,7 +2465,7 @@ wrangler deploy
2465
2465
  # URL gerada: https://cdp-edge-tracking.SEU_USUARIO.workers.dev
2466
2466
  ```
2467
2467
 
2468
- > Após o deploy, o Worker fica disponível em `https://cdp-edge-tracking.SEU_USUARIO.workers.dev`. Para usar `/api/tracking` no site, criar um **Custom Domain** nas configurações do Worker ou usar a URL completa.
2468
+ > Após o deploy, o Worker fica disponível em `https://cdp-edge-tracking.SEU_USUARIO.workers.dev`. Para usar `/track` no site, criar um **Custom Domain** nas configurações do Worker ou usar a URL completa.
2469
2469
 
2470
2470
  ---
2471
2471
 
@@ -2474,7 +2474,7 @@ wrangler deploy
2474
2474
  Se o site e o Worker estão em domínios diferentes, mudar a URL no `tracking.js`:
2475
2475
 
2476
2476
  ```js
2477
- // Em vez de '/api/tracking' (mesmo domínio — Next.js / Vite server)
2477
+ // Em vez de '/track' (mesmo domínio — Next.js / Vite server)
2478
2478
  // usar a URL do Worker:
2479
2479
  const TRACKING_ENDPOINT = 'https://cdp-edge-tracking.SEU_USUARIO.workers.dev';
2480
2480
 
@@ -2496,7 +2496,7 @@ const sendServerEvent = (eventName, eventId, payload = {}) => {
2496
2496
  };
2497
2497
  ```
2498
2498
 
2499
- > Se o site rodar em **Cloudflare Pages**, usar `functions/api/tracking.js` — o código do Worker é idêntico, só muda o handler para `export async function onRequestPost({ request, env, waitUntil })`.
2499
+ > Se o site rodar em **Cloudflare Pages**, usar `functions/track.js` — o código do Worker é idêntico, só muda o handler para `export async function onRequestPost({ request, env, waitUntil })`.
2500
2500
 
2501
2501
  ---
2502
2502
 
@@ -31,7 +31,7 @@ Este script captura dados à medida que o usuário preenche o formulário.
31
31
  ```javascript
32
32
  <script>
33
33
  (function() {
34
- const WORKER_URL = 'https://api.seusite.com/api/tracking';
34
+ const WORKER_URL = 'https://api.seusite.com/track';
35
35
 
36
36
  // Atualização de identidade ao sair do campo (Blur Event)
37
37
  const inputs = document.querySelectorAll('input[type="email"], input[type="tel"]');
@@ -50,7 +50,7 @@ Step 4: Confirmação / Obrigado
50
50
  <script src="/js/cdpTrack.js" async></script>
51
51
  <script>
52
52
  window.cdpConfig = {
53
- workerUrl: '/api/tracking', // Same-Domain (furtivo)
53
+ workerUrl: '/track', // Same-Domain (furtivo)
54
54
  metaId: 'SEU_PIXEL_ID',
55
55
  ga4Id: 'G-XXXXXXXX',
56
56
  tiktokId: 'C4XXXXXXXXXXXXXXX',
@@ -204,7 +204,7 @@ document.addEventListener('visibilitychange', async () => {
204
204
  const cdp_uid = document.cookie.match(/cdp_uid=([^;]+)/)?.[1] || '';
205
205
 
206
206
  // Usa navigator.sendBeacon para garantir envio mesmo se browser encerrar
207
- navigator.sendBeacon('/api/tracking', JSON.stringify({
207
+ navigator.sendBeacon('/track', JSON.stringify({
208
208
  event_name: 'CheckoutAbandonment',
209
209
  cdp_uid,
210
210
  step: checkoutState.step,
@@ -236,7 +236,7 @@ export default {
236
236
  return new Response(null, { headers: cors });
237
237
  }
238
238
 
239
- if (url.pathname === '/api/tracking') {
239
+ if (url.pathname === '/track') {
240
240
  return handleTracking(request, env, ctx);
241
241
  }
242
242
 
@@ -589,7 +589,7 @@ CREATE INDEX IF NOT EXISTS idx_events_created ON events_log(created_at);
589
589
  - [ ] CheckoutAbandonment usa `navigator.sendBeacon` para garantir envio
590
590
 
591
591
  ### Cloudflare Worker
592
- - [ ] Endpoint `/api/tracking` configurado como Route no Cloudflare
592
+ - [ ] Endpoint `/track` configurado como Route no Cloudflare
593
593
  - [ ] Identity Graph atualizado progressivamente conforme usuário preenche campos
594
594
  - [ ] Meta CAPI v25.0 endpoint correto
595
595
  - [ ] TikTok Events API v1.3 endpoint correto
@@ -183,7 +183,7 @@ function generateEventId() {
183
183
  * @param {Object} data - Dados completos do evento
184
184
  */
185
185
  async function sendToServer(eventName, data) {
186
- const serverUrl = '/api/track'; // ou URL configurada
186
+ const serverUrl = '/track'; // ou URL configurada
187
187
 
188
188
  await fetch(serverUrl, {
189
189
  method: 'POST',
@@ -299,7 +299,7 @@ const BehaviorEngine = {
299
299
  fields_count: formInteracted.size,
300
300
  meta_intensity: 'medium',
301
301
  });
302
- navigator.sendBeacon('/api/tracking', new Blob([data], { type: 'application/json' }));
302
+ navigator.sendBeacon('/track', new Blob([data], { type: 'application/json' }));
303
303
  }
304
304
  }
305
305
  });
@@ -19,7 +19,7 @@ Mede a eficácia do vídeo de vendas antes do botão de compra aparecer.
19
19
  * **Ação**: Disparar `ViewContent` (25/50/75) e `AddToCart` (100% ou clique no botão).
20
20
 
21
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.
22
+ Utiliza rotas no mesmo domínio (ex: `/track`) para garantir que o script de rastreamento não seja bloqueado por uBlock ou Ghostery.
23
23
 
24
24
  ---
25
25
 
@@ -34,7 +34,7 @@
34
34
  ┌─────────────────────────────────────────────────────────────┐
35
35
  │ Cloudflare Worker (Quantum Tier) │
36
36
 
37
- │ Endpoint: /api/tracking (Same-Domain) │
37
+ │ Endpoint: /track (Same-Domain) │
38
38
  │ - Recebe eventos do browser │
39
39
  │ - Salva sessão no D1 (fbp, fbc, ttp, UTMs) │
40
40
  │ - Despacha para APIs: Meta, GA4, TikTok │
@@ -78,7 +78,7 @@
78
78
  <script src="/js/cdpTrack.js" async></script>
79
79
  <script>
80
80
  window.cdpConfig = {
81
- workerUrl: '/api/tracking', // Same-Domain (furtivo)
81
+ workerUrl: '/track', // Same-Domain (furtivo)
82
82
  metaId: 'SEU_PIXEL_ID',
83
83
  ga4Id: 'G-XXXXXXXX',
84
84
  tiktokId: 'C4XXXXXXXXXXXXXXX',
@@ -182,7 +182,7 @@ export default {
182
182
  }
183
183
 
184
184
  // Endpoint principal de tracking
185
- if (url.pathname === '/api/tracking') {
185
+ if (url.pathname === '/track') {
186
186
  return handleTracking(request, env, ctx);
187
187
  }
188
188
 
@@ -500,13 +500,13 @@ CREATE INDEX IF NOT EXISTS idx_fbc ON identity_graph(fbc);
500
500
 
501
501
  ### Browser
502
502
  - [ ] cdp_uid gerado no primeiro acesso e persistido por 1 ano
503
- - [ ] PageView disparado via Fetch para `/api/tracking`
503
+ - [ ] PageView disparado via Fetch para `/track`
504
504
  - [ ] InitiateCheckout disparado antes do redirecionamento
505
505
  - [ ] cdp_uid injetado na URL do checkout (xcod/sck/src)
506
506
  - [ ] UTMs capturados e salvos no D1
507
507
 
508
508
  ### Cloudflare Worker
509
- - [ ] Endpoint `/api/tracking` configurado como Route no Cloudflare
509
+ - [ ] Endpoint `/track` configurado como Route no Cloudflare
510
510
  - [ ] Endpoint `/api/wh/{plataforma}` para webhooks
511
511
  - [ ] Salvar sessão no D1 com todos os cookies
512
512
  - [ ] D1 lookup pelo cdp_uid ao receber webhook
@@ -527,13 +527,13 @@ CREATE INDEX IF NOT EXISTS idx_fbc ON identity_graph(fbc);
527
527
  ```
528
528
  1. Visitante acessa a página de vendas
529
529
  └── JS: gera cdp_uid → salva cookie (1 ano)
530
- └── JS: dispara PageView → /api/tracking
530
+ └── JS: dispara PageView → /track
531
531
  └── Worker: salva sessão no D1 (fbp, fbc, ttp, UTMs, IP)
532
532
  └── Worker: dispatch → Meta, GA4, TikTok (PageView)
533
533
 
534
534
  2. Visitante clica no botão de compra
535
535
  └── JS: intercepta clique → previne redirecionamento
536
- └── JS: dispara InitiateCheckout → /api/tracking
536
+ └── JS: dispara InitiateCheckout → /track
537
537
  └── Worker: atualiza sessão no D1
538
538
  └── Worker: dispatch → Meta, GA4, TikTok (InitiateCheckout)
539
539
  └── JS: injeta cdp_uid na URL (xcod/sck/src)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cdp-edge",
3
- "version": "2.5.9",
3
+ "version": "2.6.1",
4
4
  "description": "CDP Edge - Quantum Tracking - Sistema multi-agente para tracking digital Cloudflare Native (Workers + D1)",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -24,7 +24,7 @@
24
24
  "build": "node build.js",
25
25
  "dev": "node build.js --watch",
26
26
  "test": "node test.js",
27
- "test:unit": "node tests/unit/normalization.test.js && node tests/unit/hashing.test.js && node tests/unit/deduplication.test.js && node tests/unit/payload-validation.test.js && node tests/unit/new-features.test.js && node tests/unit/utils.test.js",
27
+ "test:unit": "node tests/unit/normalization.test.js && node tests/unit/hashing.test.js && node tests/unit/deduplication.test.js && node tests/unit/payload-validation.test.js && node tests/unit/new-features.test.js && node tests/unit/utils.test.js && node tests/unit/contracts.test.js",
28
28
  "test:unit:normalize": "node tests/unit/normalization.test.js",
29
29
  "test:unit:hash": "node tests/unit/hashing.test.js",
30
30
  "test:unit:dedup": "node tests/unit/deduplication.test.js",
@@ -12,3 +12,8 @@ SITE_DOMAIN=seudominio.com.br
12
12
  META_PIXEL_ID=
13
13
  GA4_MEASUREMENT_ID=
14
14
  TIKTOK_PIXEL_ID=
15
+
16
+ # ZapMan SDR (opcional)
17
+ ZAPMAN_API_URL=
18
+ ZAPMAN_CRM_INSTANCE=
19
+ ZAPMAN_WEBHOOK_URL=
@@ -1,39 +1,39 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * CDP Edge deploy-client.js
3
+ * CDP Edge - deploy-client.js
4
4
  *
5
- * Deploy do Worker com variáveis reais do cliente, sem commitar credenciais no repo.
6
- * de .client.env (gitignored) e gera um wrangler.deploy.toml temporário.
5
+ * Deploy the Worker with client-specific values without committing credentials.
6
+ * Reads .client.env (gitignored) and writes a temporary wrangler.deploy.toml.
7
7
  *
8
- * Uso:
9
- * node deploy-client.js deploy completo
10
- * node deploy-client.js --dry-run valida sem subir ao Cloudflare
8
+ * Usage:
9
+ * node deploy-client.cjs -> full deploy
10
+ * node deploy-client.cjs --dry-run -> validate without deploying
11
11
  *
12
12
  * Setup:
13
13
  * cp .client.env.example .client.env
14
- * # edite .client.env com os valores do cliente
15
- * node deploy-client.js
14
+ * # edit .client.env with the client values
15
+ * node deploy-client.cjs --dry-run
16
16
  */
17
17
 
18
- const fs = require('fs');
18
+ const fs = require('fs');
19
19
  const path = require('path');
20
20
  const { execSync } = require('child_process');
21
21
 
22
- const ROOT = __dirname;
23
- const TOML = path.join(ROOT, 'wrangler.toml');
24
- const DEPLOY = path.join(ROOT, 'wrangler.deploy.toml');
25
- const ENV = path.join(ROOT, '.client.env');
22
+ const ROOT = __dirname;
23
+ const TOML = path.join(ROOT, 'wrangler.toml');
24
+ const DEPLOY = path.join(ROOT, 'wrangler.deploy.toml');
25
+ const ENV = path.join(ROOT, '.client.env');
26
26
  const DRY_RUN = process.argv.includes('--dry-run');
27
27
 
28
- // ── Carregar .client.env ──────────────────────────────────────────────────────
29
28
  if (!fs.existsSync(ENV)) {
30
- console.error('\n❌ .client.env não encontrado.');
31
- console.error(' cp .client.env.example .client.env e preencha os valores do cliente.\n');
29
+ console.error('\nERROR: .client.env not found.');
30
+ console.error('Run: cp .client.env.example .client.env');
31
+ console.error('Then fill in the client values.\n');
32
32
  process.exit(1);
33
33
  }
34
34
 
35
35
  const env = {};
36
- fs.readFileSync(ENV, 'utf8').split('\n').forEach(line => {
36
+ fs.readFileSync(ENV, 'utf8').split('\n').forEach((line) => {
37
37
  const trimmed = line.trim();
38
38
  if (!trimmed || trimmed.startsWith('#')) return;
39
39
  const [key, ...rest] = trimmed.split('=');
@@ -41,36 +41,52 @@ fs.readFileSync(ENV, 'utf8').split('\n').forEach(line => {
41
41
  });
42
42
 
43
43
  const required = ['DATABASE_ID', 'SITE_DOMAIN'];
44
- const missing = required.filter(k => !env[k]);
44
+ const missing = required.filter((key) => !env[key]);
45
45
  if (missing.length > 0) {
46
- console.error(`\n❌ Variáveis obrigatórias faltando no .client.env: ${missing.join(', ')}\n`);
46
+ console.error(`\nERROR: missing required .client.env values: ${missing.join(', ')}\n`);
47
47
  process.exit(1);
48
48
  }
49
49
 
50
- // ── Substituir placeholders no wrangler.toml → wrangler.deploy.toml ───────────
50
+ const invalid = [];
51
+ if (env.DATABASE_ID === 'SEU_DATABASE_ID') invalid.push('DATABASE_ID');
52
+ if (env.SITE_DOMAIN === 'SEU_DOMINIO' || env.SITE_DOMAIN === 'seudominio.com.br') {
53
+ invalid.push('SITE_DOMAIN');
54
+ }
55
+
56
+ if (invalid.length > 0) {
57
+ console.error(`\nERROR: placeholder values remain in .client.env: ${invalid.join(', ')}\n`);
58
+ process.exit(1);
59
+ }
60
+
61
+ function tomlString(value) {
62
+ return String(value || '').replace(/\\/g, '\\\\').replace(/"/g, '\\"');
63
+ }
64
+
51
65
  let toml = fs.readFileSync(TOML, 'utf8');
52
66
 
53
67
  toml = toml
54
- .replace(/SEU_DATABASE_ID/g, env.DATABASE_ID)
55
- .replace(/SEU_DOMINIO/g, env.SITE_DOMAIN)
56
- .replace(/META_PIXEL_ID\s*=\s*""/, `META_PIXEL_ID = "${env.META_PIXEL_ID || ''}"`)
57
- .replace(/GA4_MEASUREMENT_ID\s*=\s*""/, `GA4_MEASUREMENT_ID = "${env.GA4_MEASUREMENT_ID || ''}"`)
58
- .replace(/TIKTOK_PIXEL_ID\s*=\s*""/, `TIKTOK_PIXEL_ID = "${env.TIKTOK_PIXEL_ID || ''}"`);
68
+ .replace(/database_id\s*=\s*"[^"]*"/, `database_id = "${tomlString(env.DATABASE_ID)}"`)
69
+ .replace(/SEU_DATABASE_ID/g, tomlString(env.DATABASE_ID))
70
+ .replace(/SEU_DOMINIO/g, tomlString(env.SITE_DOMAIN))
71
+ .replace(/META_PIXEL_ID\s*=\s*"[^"]*"/, `META_PIXEL_ID = "${tomlString(env.META_PIXEL_ID)}"`)
72
+ .replace(/GA4_MEASUREMENT_ID\s*=\s*"[^"]*"/, `GA4_MEASUREMENT_ID = "${tomlString(env.GA4_MEASUREMENT_ID)}"`)
73
+ .replace(/TIKTOK_PIXEL_ID\s*=\s*"[^"]*"/, `TIKTOK_PIXEL_ID = "${tomlString(env.TIKTOK_PIXEL_ID)}"`)
74
+ .replace(/ZAPMAN_API_URL\s*=\s*"[^"]*"/, `ZAPMAN_API_URL = "${tomlString(env.ZAPMAN_API_URL)}"`)
75
+ .replace(/ZAPMAN_CRM_INSTANCE\s*=\s*"[^"]*"/, `ZAPMAN_CRM_INSTANCE = "${tomlString(env.ZAPMAN_CRM_INSTANCE)}"`)
76
+ .replace(/ZAPMAN_WEBHOOK_URL\s*=\s*"[^"]*"/, `ZAPMAN_WEBHOOK_URL = "${tomlString(env.ZAPMAN_WEBHOOK_URL)}"`);
59
77
 
60
78
  fs.writeFileSync(DEPLOY, toml);
61
79
 
62
- // ── Executar wrangler deploy ──────────────────────────────────────────────────
63
80
  const cmd = `wrangler deploy --config wrangler.deploy.toml${DRY_RUN ? ' --dry-run' : ''}`;
64
- console.log(`\n🚀 ${DRY_RUN ? '[DRY-RUN] ' : ''}Deploying com config do cliente...\n`);
81
+ console.log(`\n${DRY_RUN ? '[DRY-RUN] ' : ''}Deploying with client config...\n`);
65
82
 
66
83
  try {
67
84
  execSync(cmd, { stdio: 'inherit', cwd: ROOT });
68
- console.log(`\n✅ Deploy ${DRY_RUN ? '(dry-run) ' : ''}concluído.\n`);
85
+ console.log(`\nDeploy ${DRY_RUN ? '(dry-run) ' : ''}completed.\n`);
69
86
  } catch (err) {
70
- console.error('\n❌ Deploy falhou.\n');
87
+ console.error('\nDeploy failed.\n');
71
88
  process.exit(1);
72
89
  } finally {
73
- // sempre remove o arquivo temporário
74
90
  if (fs.existsSync(DEPLOY)) fs.unlinkSync(DEPLOY);
75
- console.log('🧹 wrangler.deploy.toml removido.\n');
91
+ console.log('Removed temporary wrangler.deploy.toml.\n');
76
92
  }