@beworke/pixel 0.1.0-rc.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 (123) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/README.md +163 -0
  3. package/RELEASE_CANDIDATE.md +256 -0
  4. package/dist/PixelLogger-B21lEjep.d.mts +8 -0
  5. package/dist/PixelLogger-B21lEjep.d.ts +8 -0
  6. package/dist/StorageFactory-BhpbB6Jj.d.mts +8 -0
  7. package/dist/StorageFactory-CAkJJqVD.d.ts +8 -0
  8. package/dist/config/index.cjs.js +3 -0
  9. package/dist/config/index.cjs.js.map +1 -0
  10. package/dist/config/index.d.mts +19 -0
  11. package/dist/config/index.d.ts +19 -0
  12. package/dist/config/index.esm.js +3 -0
  13. package/dist/config/index.esm.js.map +1 -0
  14. package/dist/events/index.cjs.js +3 -0
  15. package/dist/events/index.cjs.js.map +1 -0
  16. package/dist/events/index.d.mts +1 -0
  17. package/dist/events/index.d.ts +1 -0
  18. package/dist/events/index.esm.js +3 -0
  19. package/dist/events/index.esm.js.map +1 -0
  20. package/dist/examples/html-script/README.md +71 -0
  21. package/dist/examples/html-script/RELEASE_CANDIDATE.md +121 -0
  22. package/dist/examples/html-script/add-payment-info/README.md +46 -0
  23. package/dist/examples/html-script/add-payment-info/example-add-payment-info-card-autocomplete.html +494 -0
  24. package/dist/examples/html-script/add-payment-info/example-add-payment-info-card-disabled.html +478 -0
  25. package/dist/examples/html-script/add-payment-info/example-add-payment-info-card-fields.html +486 -0
  26. package/dist/examples/html-script/add-payment-info/example-add-payment-info-data-track.html +479 -0
  27. package/dist/examples/html-script/add-payment-info/example-add-payment-info-dedupe.html +492 -0
  28. package/dist/examples/html-script/add-payment-info/example-add-payment-info-manual.html +495 -0
  29. package/dist/examples/html-script/add-payment-info/example-add-payment-info-rules-card.html +469 -0
  30. package/dist/examples/html-script/add-payment-info/example-add-payment-info-security.html +489 -0
  31. package/dist/examples/html-script/add-to-cart/README.md +36 -0
  32. package/dist/examples/html-script/add-to-cart/example-add-to-cart-attribute.html +517 -0
  33. package/dist/examples/html-script/add-to-cart/example-add-to-cart-auto.html +512 -0
  34. package/dist/examples/html-script/add-to-cart/example-add-to-cart-click.html +519 -0
  35. package/dist/examples/html-script/add-to-cart/example-add-to-cart-dedupe.html +514 -0
  36. package/dist/examples/html-script/add-to-cart/example-add-to-cart-manual.html +517 -0
  37. package/dist/examples/html-script/add-to-cart/example-add-to-cart-order-bump.html +527 -0
  38. package/dist/examples/html-script/add-to-cart/example-add-to-cart-text.html +524 -0
  39. package/dist/examples/html-script/example-basic.html +350 -0
  40. package/dist/examples/html-script/example-behavior.html +435 -0
  41. package/dist/examples/html-script/example-conversion.html +479 -0
  42. package/dist/examples/html-script/example-integration.html +709 -0
  43. package/dist/examples/html-script/example-transport.html +748 -0
  44. package/dist/examples/html-script/initiate-checkout/README.md +38 -0
  45. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-attribute.html +485 -0
  46. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-auto.html +491 -0
  47. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-click.html +493 -0
  48. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-manual.html +494 -0
  49. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-snapshot.html +497 -0
  50. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-submit.html +502 -0
  51. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-text.html +496 -0
  52. package/dist/examples/html-script/lead/README.md +25 -0
  53. package/dist/examples/html-script/lead/example-lead-trigger-attribute.html +594 -0
  54. package/dist/examples/html-script/lead/example-lead-trigger-auto.html +431 -0
  55. package/dist/examples/html-script/lead/example-lead-trigger-click.html +587 -0
  56. package/dist/examples/html-script/release-candidate.html +726 -0
  57. package/dist/examples/html-script/remove-from-cart/README.md +36 -0
  58. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-attribute.html +532 -0
  59. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-css.html +524 -0
  60. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-dedupe.html +540 -0
  61. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-manual.html +533 -0
  62. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-multi.html +557 -0
  63. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-state.html +539 -0
  64. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-text.html +524 -0
  65. package/dist/examples/html-script/search/README.md +41 -0
  66. package/dist/examples/html-script/search/example-search-attribute.html +454 -0
  67. package/dist/examples/html-script/search/example-search-button-sync.html +455 -0
  68. package/dist/examples/html-script/search/example-search-dedupe.html +466 -0
  69. package/dist/examples/html-script/search/example-search-input.html +456 -0
  70. package/dist/examples/html-script/search/example-search-manual.html +473 -0
  71. package/dist/examples/html-script/search/example-search-submit.html +450 -0
  72. package/dist/examples/html-script/search/example-search-text.html +441 -0
  73. package/dist/examples/html-script/view-content/README.md +48 -0
  74. package/dist/examples/html-script/view-content/example-view-content-attribute.html +488 -0
  75. package/dist/examples/html-script/view-content/example-view-content-css.html +467 -0
  76. package/dist/examples/html-script/view-content/example-view-content-dedupe.html +485 -0
  77. package/dist/examples/html-script/view-content/example-view-content-empty.html +469 -0
  78. package/dist/examples/html-script/view-content/example-view-content-manual.html +496 -0
  79. package/dist/examples/html-script/view-content/example-view-content-product-card.html +478 -0
  80. package/dist/examples/html-script/view-content/example-view-content-text.html +473 -0
  81. package/dist/examples/release-candidate/README.md +14 -0
  82. package/dist/examples/v2/README.md +33 -0
  83. package/dist/index-DUfFzniE.d.mts +274 -0
  84. package/dist/index-DUfFzniE.d.ts +274 -0
  85. package/dist/index.cjs.js +3 -0
  86. package/dist/index.cjs.js.map +1 -0
  87. package/dist/index.d.mts +364 -0
  88. package/dist/index.d.ts +364 -0
  89. package/dist/index.esm.js +3 -0
  90. package/dist/index.esm.js.map +1 -0
  91. package/dist/logger/index.cjs.js +3 -0
  92. package/dist/logger/index.cjs.js.map +1 -0
  93. package/dist/logger/index.d.mts +12 -0
  94. package/dist/logger/index.d.ts +12 -0
  95. package/dist/logger/index.esm.js +3 -0
  96. package/dist/logger/index.esm.js.map +1 -0
  97. package/dist/pixel-CbeF25mD.d.mts +555 -0
  98. package/dist/pixel-CbeF25mD.d.ts +555 -0
  99. package/dist/pixel-default-config-1VgLFOiL.d.mts +5 -0
  100. package/dist/pixel-default-config-Bxb-Vdd8.d.ts +5 -0
  101. package/dist/runtime/index.cjs.js +3 -0
  102. package/dist/runtime/index.cjs.js.map +1 -0
  103. package/dist/runtime/index.d.mts +48 -0
  104. package/dist/runtime/index.d.ts +48 -0
  105. package/dist/runtime/index.esm.js +3 -0
  106. package/dist/runtime/index.esm.js.map +1 -0
  107. package/dist/services/index.cjs.js +3 -0
  108. package/dist/services/index.cjs.js.map +1 -0
  109. package/dist/services/index.d.mts +169 -0
  110. package/dist/services/index.d.ts +169 -0
  111. package/dist/services/index.esm.js +3 -0
  112. package/dist/services/index.esm.js.map +1 -0
  113. package/dist/types-CTpRvFKZ.d.ts +71 -0
  114. package/dist/types-DGlBdsAy.d.mts +71 -0
  115. package/dist/v2/global.global.js +3 -0
  116. package/dist/v2/global.global.js.map +1 -0
  117. package/dist/v2/index.cjs.js +3 -0
  118. package/dist/v2/index.cjs.js.map +1 -0
  119. package/dist/v2/index.d.mts +7 -0
  120. package/dist/v2/index.d.ts +7 -0
  121. package/dist/v2/index.esm.js +3 -0
  122. package/dist/v2/index.esm.js.map +1 -0
  123. package/package.json +101 -0
@@ -0,0 +1,594 @@
1
+ <!doctype html>
2
+ <html lang="pt-BR">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Pixel v2 — LEAD por atributo data-track</title>
7
+ <style>
8
+ :root {
9
+ --bg: #f8fafc;
10
+ --card: #fff;
11
+ --border: #e2e8f0;
12
+ --text: #0f172a;
13
+ --muted: #64748b;
14
+ --accent: #0f766e;
15
+ --accent-soft: #ccfbf1;
16
+ --warn: #9a3412;
17
+ --warn-soft: #ffedd5;
18
+ }
19
+ * {
20
+ box-sizing: border-box;
21
+ }
22
+ body {
23
+ margin: 0;
24
+ font-family: 'Segoe UI', system-ui, sans-serif;
25
+ background:
26
+ radial-gradient(circle at top left, #ecfeff 0%, transparent 40%),
27
+ linear-gradient(180deg, #f8fafc 0%, #eef2ff 100%);
28
+ color: var(--text);
29
+ line-height: 1.45;
30
+ }
31
+ .wrap {
32
+ max-width: 960px;
33
+ margin: 0 auto;
34
+ padding: 1.5rem;
35
+ }
36
+ h1 {
37
+ font-size: 1.55rem;
38
+ margin: 0 0 0.35rem;
39
+ letter-spacing: -0.02em;
40
+ }
41
+ h2 {
42
+ font-size: 1.05rem;
43
+ margin: 0 0 0.75rem;
44
+ }
45
+ .sub {
46
+ color: var(--muted);
47
+ margin: 0 0 1rem;
48
+ font-size: 0.92rem;
49
+ }
50
+ .nav {
51
+ display: flex;
52
+ flex-wrap: wrap;
53
+ gap: 0.4rem;
54
+ margin-bottom: 1rem;
55
+ }
56
+ .nav a {
57
+ text-decoration: none;
58
+ border: 1px solid var(--border);
59
+ background: #fff;
60
+ color: var(--text);
61
+ border-radius: 999px;
62
+ padding: 0.3rem 0.75rem;
63
+ font-size: 0.82rem;
64
+ }
65
+ .nav a.active {
66
+ background: var(--accent);
67
+ border-color: var(--accent);
68
+ color: #fff;
69
+ }
70
+ .grid {
71
+ display: grid;
72
+ grid-template-columns: 1.15fr 0.85fr;
73
+ gap: 1rem;
74
+ }
75
+ @media (max-width: 860px) {
76
+ .grid {
77
+ grid-template-columns: 1fr;
78
+ }
79
+ }
80
+ .card {
81
+ background: var(--card);
82
+ border: 1px solid var(--border);
83
+ border-radius: 12px;
84
+ padding: 1rem;
85
+ margin-bottom: 1rem;
86
+ box-shadow: 0 1px 0 rgba(15, 23, 42, 0.03);
87
+ }
88
+ .hint {
89
+ background: var(--accent-soft);
90
+ border: 1px solid #99f6e4;
91
+ border-radius: 10px;
92
+ padding: 0.85rem 1rem;
93
+ font-size: 0.9rem;
94
+ margin-bottom: 1rem;
95
+ }
96
+ .hint.warn {
97
+ background: var(--warn-soft);
98
+ border-color: #fdba74;
99
+ color: var(--warn);
100
+ }
101
+ .actions {
102
+ display: flex;
103
+ flex-wrap: wrap;
104
+ gap: 0.5rem;
105
+ margin-top: 0.75rem;
106
+ }
107
+ button {
108
+ appearance: none;
109
+ border: 1px solid var(--border);
110
+ background: #fff;
111
+ color: var(--text);
112
+ border-radius: 8px;
113
+ padding: 0.5rem 0.85rem;
114
+ cursor: pointer;
115
+ font: inherit;
116
+ }
117
+ button.primary {
118
+ background: var(--accent);
119
+ border-color: var(--accent);
120
+ color: #fff;
121
+ }
122
+ button.danger {
123
+ background: #7f1d1d;
124
+ border-color: #7f1d1d;
125
+ color: #fff;
126
+ }
127
+ label {
128
+ display: block;
129
+ font-size: 0.8rem;
130
+ color: var(--muted);
131
+ margin-bottom: 0.25rem;
132
+ }
133
+ input {
134
+ width: 100%;
135
+ border: 1px solid var(--border);
136
+ border-radius: 8px;
137
+ padding: 0.55rem 0.7rem;
138
+ font: inherit;
139
+ background: #fff;
140
+ }
141
+ .row {
142
+ display: grid;
143
+ grid-template-columns: 1fr 1fr;
144
+ gap: 0.75rem;
145
+ }
146
+ @media (max-width: 560px) {
147
+ .row {
148
+ grid-template-columns: 1fr;
149
+ }
150
+ }
151
+ .status,
152
+ pre {
153
+ background: #0f172a;
154
+ color: #e2e8f0;
155
+ border-radius: 8px;
156
+ padding: 0.75rem;
157
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
158
+ font-size: 0.78rem;
159
+ white-space: pre-wrap;
160
+ word-break: break-word;
161
+ max-height: 280px;
162
+ overflow: auto;
163
+ }
164
+ .pill {
165
+ display: inline-block;
166
+ border-radius: 999px;
167
+ padding: 0.15rem 0.55rem;
168
+ font-size: 0.72rem;
169
+ background: #e2e8f0;
170
+ color: #334155;
171
+ margin-left: 0.35rem;
172
+ }
173
+ .pill.ok {
174
+ background: #bbf7d0;
175
+ color: #166534;
176
+ }
177
+ .checklist {
178
+ margin: 0;
179
+ padding-left: 1.1rem;
180
+ font-size: 0.88rem;
181
+ color: var(--muted);
182
+ }
183
+ .checklist li {
184
+ margin: 0.35rem 0;
185
+ }
186
+ .ctx {
187
+ border-left: 3px solid var(--accent);
188
+ padding-left: 0.75rem;
189
+ margin-bottom: 0.85rem;
190
+ color: var(--muted);
191
+ font-size: 0.88rem;
192
+ }
193
+ code {
194
+ font-size: 0.85em;
195
+ }
196
+ </style>
197
+ </head>
198
+ <body>
199
+ <div class="wrap">
200
+ <h1>LEAD — selector · data-track</h1>
201
+ <p class="sub">
202
+ Cenário isolado de trigger para validação do Pixel v2.
203
+ <span class="pill" id="init-pill">offline</span>
204
+ </p>
205
+ <div class="nav">
206
+ <a href="example-lead-trigger-click.html" class=""
207
+ >1. Click · Newsletter</a
208
+ >
209
+ <a href="example-lead-trigger-auto.html" class="">2. Auto · Checkout</a>
210
+ <a href="example-lead-trigger-attribute.html" class="active"
211
+ >3. Atributo · data-track</a
212
+ >
213
+ </div>
214
+ <div class="hint">
215
+ <strong>Contexto:</strong> cenário padrão por atributo — sem
216
+ <code>selectorForm</code>. O
217
+ <code>ConfiguredSelectorDetector</code> escuta clique em
218
+ <code>[data-track="lead"]</code> e extrai email/phone do
219
+ <code>&lt;form&gt;</code> mais próximo via
220
+ <code>CustomerExtractor</code>.
221
+ </div>
222
+
223
+ <div class="card">
224
+ <h2>Lifecycle</h2>
225
+ <div class="actions">
226
+ <button id="btn-reinit" class="primary" type="button">
227
+ Reinitialize
228
+ </button>
229
+ <button id="btn-destroy" class="danger" type="button">Destroy</button>
230
+ <button id="btn-clear" type="button">Clear logs</button>
231
+ </div>
232
+ <div class="status" id="runtime-status">Aguardando init...</div>
233
+ </div>
234
+
235
+ <div class="grid">
236
+ <div>
237
+ <div class="card">
238
+ <h2>
239
+ Lead por atributo <span class="pill">data-track="lead"</span>
240
+ </h2>
241
+ <div class="ctx">
242
+ Botão marcado com atributo padrão. Sem condição de formulário no
243
+ detector — o clique no seletor dispara; o payload vem do form pai.
244
+ </div>
245
+ <form id="attr-lead-form">
246
+ <div class="row">
247
+ <div>
248
+ <label for="attr-email">Email</label>
249
+ <input
250
+ id="attr-email"
251
+ name="email"
252
+ type="email"
253
+ placeholder="lead@test.com"
254
+ />
255
+ </div>
256
+ <div>
257
+ <label for="attr-phone">Phone</label>
258
+ <input
259
+ id="attr-phone"
260
+ name="phone"
261
+ type="tel"
262
+ placeholder="11977776666"
263
+ />
264
+ </div>
265
+ </div>
266
+ <div class="actions">
267
+ <button type="button" class="primary" data-track="lead">
268
+ Enviar interesse
269
+ </button>
270
+ <button type="button" id="btn-empty-click">
271
+ Clique sem data-track
272
+ </button>
273
+ </div>
274
+ </form>
275
+ <p class="sub">
276
+ Clique em <em>Enviar interesse</em> com pelo menos email
277
+ <em>ou</em> phone (extractor). Clique no botão sem atributo → não
278
+ dispara.
279
+ </p>
280
+ </div>
281
+ <div class="card">
282
+ <h2>Checklist</h2>
283
+ <ul class="checklist">
284
+ <li>[ ] Clique sem <code>data-track</code> → não dispara</li>
285
+ <li>
286
+ [ ] Clique com form vazio → não dispara (sem email/phone/name)
287
+ </li>
288
+ <li>
289
+ [ ] Email preenchido + clique no botão → <code>LEAD</code>
290
+ </li>
291
+ <li>[ ] Detector ativo: <code>ConfiguredSelector(LEAD)</code></li>
292
+ <li>[ ] Payload traz dados extraídos do form</li>
293
+ </ul>
294
+ </div>
295
+ </div>
296
+ <div>
297
+ <div class="card">
298
+ <h2>Event counts</h2>
299
+ <div class="status" id="event-counts">Nenhum evento ainda</div>
300
+ </div>
301
+ <div class="card">
302
+ <h2>Active detectors</h2>
303
+ <div class="status" id="detectors">—</div>
304
+ </div>
305
+ <div class="card">
306
+ <h2>Last event JSON</h2>
307
+ <pre id="last-event">null</pre>
308
+ </div>
309
+ <div class="card">
310
+ <h2>Event log</h2>
311
+ <pre id="logs">Aguardando eventos...</pre>
312
+ </div>
313
+ </div>
314
+ </div>
315
+ </div>
316
+
317
+ <script src="../../dist/v2/global.global.js"></script>
318
+ <script>
319
+ const { Pixel, DEFAULT_PIXEL_CONFIG } = window.PixelV2;
320
+ const API_ENDPOINT =
321
+ 'https://micro-service-pixel-production-4826.up.railway.app';
322
+ const PIXEL_ID = 'pix_7315610';
323
+
324
+ const els = {
325
+ logs: document.getElementById('logs'),
326
+ last: document.getElementById('last-event'),
327
+ counts: document.getElementById('event-counts'),
328
+ detectors: document.getElementById('detectors'),
329
+ runtime: document.getElementById('runtime-status'),
330
+ pill: document.getElementById('init-pill'),
331
+ };
332
+
333
+ let pixel = null;
334
+ let unsubscribe = null;
335
+ let initCount = 0;
336
+ let destroyCount = 0;
337
+ const counts = {};
338
+
339
+ function leadDetectorConfig() {
340
+ return {
341
+ enabled: true,
342
+ selector: ['[data-track="lead"]'],
343
+ selectorType: 'css',
344
+ };
345
+ }
346
+
347
+ function buildConfig() {
348
+ const base = DEFAULT_PIXEL_CONFIG;
349
+ return {
350
+ ...base,
351
+ app: {
352
+ ...base.app,
353
+ source: 'custom',
354
+ environment: 'development',
355
+ debug: true,
356
+ },
357
+ transport: {
358
+ ...DEFAULT_PIXEL_CONFIG.transport,
359
+ apiEndpoint: API_ENDPOINT,
360
+ timeoutMs: 10000,
361
+ },
362
+ identity: { ...base.identity, pixelId: PIXEL_ID },
363
+ modules: {
364
+ ...base.modules,
365
+ core: {
366
+ ...base.modules.core,
367
+ enabled: false,
368
+ pageView: {
369
+ ...base.modules.core.pageView,
370
+ enabled: false,
371
+ trackInitialPageView: false,
372
+ spa: false,
373
+ },
374
+ },
375
+ behavior: { ...base.modules.behavior, enabled: false },
376
+ privacy: { ...base.modules.privacy, enabled: false },
377
+ transport: {
378
+ enabled: true,
379
+ mockSender: { enabled: false },
380
+ sender: { mode: 'http' },
381
+ persistence: { enabled: true },
382
+ replay: { enabled: true },
383
+ ordering: { enabled: true },
384
+ coordination: { enabled: true },
385
+ circuitBreaker: {
386
+ enabled: true,
387
+ failureThreshold: 5,
388
+ resetTimeoutMs: 30000,
389
+ halfOpenMaxAttempts: 2,
390
+ },
391
+ backpressure: {
392
+ enabled: true,
393
+ maxQueueSize: 500,
394
+ policy: 'drop_oldest',
395
+ sampleRate: 0.5,
396
+ },
397
+ deadLetter: { enabled: true, maxEntries: 200 },
398
+ compression: { enabled: true, strategy: 'identity' },
399
+ retry: {
400
+ enabled: true,
401
+ maxAttempts: 4,
402
+ baseDelayMs: 500,
403
+ maxDelayMs: 4000,
404
+ multiplier: 2,
405
+ },
406
+ batch: {
407
+ enabled: true,
408
+ batchSize: 10,
409
+ flushIntervalMs: 2000,
410
+ maxWaitMs: 5000,
411
+ },
412
+ timeout: { enabled: true, timeoutMs: 10000 },
413
+ offline: { enabled: true },
414
+ flush: {
415
+ enabled: true,
416
+ flushIntervalMs: 2000,
417
+ flushOnDestroy: true,
418
+ prepareUnloadHooks: true,
419
+ },
420
+ },
421
+ integrations: { ...base.modules.integrations, enabled: false },
422
+ conversion: {
423
+ enabled: true,
424
+ commerce: {
425
+ currency: 'BRL',
426
+ catalog: { products: [] },
427
+ checkout: {
428
+ mode: 'single_product',
429
+ selectedItems: [],
430
+ calculateValueFrom: 'selected_items',
431
+ allowDynamicItems: true,
432
+ },
433
+ mappings: {
434
+ attributes: {
435
+ productId: ['data-product-id'],
436
+ productName: ['data-product-name'],
437
+ price: ['data-product-price'],
438
+ quantity: ['data-quantity'],
439
+ currency: ['data-currency'],
440
+ },
441
+ fields: {
442
+ email: ['email', 'customerEmail'],
443
+ phone: ['phone', 'telefone', 'customerPhone'],
444
+ productId: ['productId'],
445
+ productName: ['productName'],
446
+ price: ['price'],
447
+ quantity: ['quantity'],
448
+ currency: ['currency'],
449
+ },
450
+ },
451
+ },
452
+ manual: {
453
+ pageView: { enabled: false },
454
+ purchase: { enabled: false },
455
+ lead: { enabled: true },
456
+ addToCart: { enabled: false },
457
+ removeFromCart: { enabled: false },
458
+ initiateCheckout: { enabled: false },
459
+ addPaymentInfo: { enabled: false },
460
+ search: { enabled: false },
461
+ viewContent: { enabled: false },
462
+ },
463
+ auto: {
464
+ enabled: true,
465
+ detectors: {
466
+ lead: leadDetectorConfig(),
467
+ purchase: { enabled: false },
468
+ addToCart: { enabled: false },
469
+ removeFromCart: { enabled: false },
470
+ initiateCheckout: { enabled: false },
471
+ addPaymentInfo: { enabled: false },
472
+ search: { enabled: false },
473
+ viewContent: { enabled: false },
474
+ },
475
+ },
476
+ rules: {
477
+ enabled: false,
478
+ selectors: [],
479
+ texts: [],
480
+ urlPatterns: [],
481
+ checkout: { enabled: false },
482
+ card: { enabled: false },
483
+ },
484
+ },
485
+ },
486
+ };
487
+ }
488
+
489
+ function appendLog(message) {
490
+ const line = '[' + new Date().toISOString() + '] ' + message;
491
+ const prev = els.logs.textContent;
492
+ els.logs.textContent =
493
+ prev === 'Aguardando eventos...' ? line : line + '\n' + prev;
494
+ }
495
+
496
+ function renderCounts() {
497
+ const lines = Object.keys(counts)
498
+ .sort()
499
+ .map(function (type) {
500
+ return type + ': ' + counts[type];
501
+ });
502
+ els.counts.textContent =
503
+ lines.length > 0 ? lines.join('\n') : 'Nenhum evento ainda';
504
+ }
505
+
506
+ function renderDebug() {
507
+ const detectors =
508
+ pixel && pixel.getDebugActiveDetectors
509
+ ? pixel.getDebugActiveDetectors()
510
+ : [];
511
+ els.detectors.textContent =
512
+ detectors.length > 0 ? detectors.join('\n') : 'Nenhum detector ativo';
513
+ els.runtime.textContent =
514
+ 'initialized: ' +
515
+ (pixel ? pixel.isInitialized() : false) +
516
+ '\ninit count: ' +
517
+ initCount +
518
+ '\ndestroy count: ' +
519
+ destroyCount +
520
+ '\npixelId: ' +
521
+ PIXEL_ID +
522
+ '\nscenario: selector · data-track';
523
+ els.pill.textContent =
524
+ pixel && pixel.isInitialized() ? 'ready' : 'offline';
525
+ els.pill.className =
526
+ 'pill' + (pixel && pixel.isInitialized() ? ' ok' : '');
527
+ }
528
+
529
+ function onEvent(event) {
530
+ counts[event.type] = (counts[event.type] || 0) + 1;
531
+ renderCounts();
532
+ els.last.textContent = JSON.stringify(event, null, 2);
533
+ appendLog(event.type + ' ' + JSON.stringify(event.data || {}));
534
+ renderDebug();
535
+ }
536
+
537
+ async function boot() {
538
+ if (unsubscribe) {
539
+ unsubscribe();
540
+ unsubscribe = null;
541
+ }
542
+ if (pixel) {
543
+ await pixel.destroy();
544
+ destroyCount += 1;
545
+ pixel = null;
546
+ }
547
+ pixel = new Pixel(buildConfig());
548
+ await pixel.init();
549
+ initCount += 1;
550
+ const services = pixel.getDebugServices();
551
+ if (services && services.dispatcher) {
552
+ unsubscribe = services.dispatcher.subscribe(onEvent);
553
+ }
554
+ appendLog('Pixel initialized — selector · data-track');
555
+ renderDebug();
556
+ }
557
+
558
+ async function destroyPixel() {
559
+ if (unsubscribe) {
560
+ unsubscribe();
561
+ unsubscribe = null;
562
+ }
563
+ if (pixel) {
564
+ await pixel.destroy();
565
+ destroyCount += 1;
566
+ pixel = null;
567
+ }
568
+ appendLog('Pixel destroyed');
569
+ renderDebug();
570
+ }
571
+
572
+ document.getElementById('btn-reinit').onclick = function () {
573
+ boot();
574
+ };
575
+ document.getElementById('btn-destroy').onclick = function () {
576
+ destroyPixel();
577
+ };
578
+ document.getElementById('btn-clear').onclick = function () {
579
+ els.logs.textContent = 'Aguardando eventos...';
580
+ els.last.textContent = 'null';
581
+ Object.keys(counts).forEach(function (k) {
582
+ delete counts[k];
583
+ });
584
+ renderCounts();
585
+ };
586
+
587
+ document.getElementById('btn-empty-click').onclick = function () {
588
+ appendLog('(playground) clique sem data-track — esperado: nenhum LEAD');
589
+ };
590
+
591
+ boot();
592
+ </script>
593
+ </body>
594
+ </html>