@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,489 @@
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 — ADD_PAYMENT_INFO segurança</title>
7
+ <style>
8
+ :root {
9
+ --bg: #f8fafc; --card: #fff; --border: #e2e8f0; --text: #0f172a;
10
+ --muted: #64748b; --accent: #0f766e; --accent-soft: #ccfbf1;
11
+ --warn: #9a3412; --warn-soft: #ffedd5;
12
+ }
13
+ * { box-sizing: border-box; }
14
+ body {
15
+ margin: 0;
16
+ font-family: "Segoe UI", system-ui, sans-serif;
17
+ background:
18
+ radial-gradient(circle at top left, #ecfeff 0%, transparent 40%),
19
+ linear-gradient(180deg, #f8fafc 0%, #eef2ff 100%);
20
+ color: var(--text); line-height: 1.45;
21
+ }
22
+ .wrap { max-width: 980px; margin: 0 auto; padding: 1.5rem; }
23
+ h1 { font-size: 1.5rem; margin: 0 0 0.35rem; letter-spacing: -0.02em; }
24
+ h2 { font-size: 1.05rem; margin: 0 0 0.75rem; }
25
+ .sub { color: var(--muted); margin: 0 0 1rem; font-size: 0.92rem; }
26
+ .nav { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 1rem; }
27
+ .nav a {
28
+ text-decoration: none; border: 1px solid var(--border); background: #fff;
29
+ color: var(--text); border-radius: 999px; padding: 0.3rem 0.7rem; font-size: 0.78rem;
30
+ }
31
+ .nav a.active { background: var(--accent); border-color: var(--accent); color: #fff; }
32
+ .grid { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: 1rem; }
33
+ @media (max-width: 860px) { .grid { grid-template-columns: 1fr; } }
34
+ .card {
35
+ background: var(--card); border: 1px solid var(--border); border-radius: 12px;
36
+ padding: 1rem; margin-bottom: 1rem; box-shadow: 0 1px 0 rgba(15,23,42,.03);
37
+ }
38
+ .hint {
39
+ background: var(--accent-soft); border: 1px solid #99f6e4; border-radius: 10px;
40
+ padding: 0.85rem 1rem; font-size: 0.9rem; margin-bottom: 1rem;
41
+ }
42
+ .hint.warn { background: var(--warn-soft); border-color: #fdba74; color: var(--warn); }
43
+ .actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
44
+ button {
45
+ appearance: none; border: 1px solid var(--border); background: #fff; color: var(--text);
46
+ border-radius: 8px; padding: 0.5rem 0.85rem; cursor: pointer; font: inherit;
47
+ }
48
+ button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
49
+ button.danger { background: #7f1d1d; border-color: #7f1d1d; color: #fff; }
50
+ button:disabled { opacity: 0.55; cursor: not-allowed; }
51
+ label { display: block; font-size: 0.8rem; color: var(--muted); margin-bottom: 0.25rem; }
52
+ input, select {
53
+ width: 100%; border: 1px solid var(--border); border-radius: 8px;
54
+ padding: 0.55rem 0.7rem; font: inherit; background: #fff;
55
+ }
56
+ .row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
57
+ .row-3 { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 0.75rem; }
58
+ @media (max-width: 560px) {
59
+ .row, .row-3 { grid-template-columns: 1fr; }
60
+ }
61
+ .status, pre {
62
+ background: #0f172a; color: #e2e8f0; border-radius: 8px; padding: 0.75rem;
63
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
64
+ font-size: 0.78rem; white-space: pre-wrap; word-break: break-word;
65
+ max-height: 260px; overflow: auto;
66
+ }
67
+ .pill {
68
+ display: inline-block; border-radius: 999px; padding: 0.15rem 0.55rem;
69
+ font-size: 0.72rem; background: #e2e8f0; color: #334155; margin-left: 0.35rem;
70
+ }
71
+ .pill.ok { background: #bbf7d0; color: #166534; }
72
+ .checklist { margin: 0; padding-left: 1.1rem; font-size: 0.88rem; color: var(--muted); }
73
+ .checklist li { margin: 0.35rem 0; }
74
+ .ctx {
75
+ border-left: 3px solid var(--accent); padding-left: 0.75rem; margin-bottom: 0.85rem;
76
+ color: var(--muted); font-size: 0.88rem;
77
+ }
78
+ code { font-size: 0.85em; }
79
+ </style>
80
+ </head>
81
+ <body>
82
+ <div class="wrap">
83
+ <h1>ADD_PAYMENT_INFO — segurança · sem PAN/CVV</h1>
84
+ <p class="sub">
85
+ Cenário isolado para validação do Pixel v2.
86
+ <span class="pill" id="init-pill">offline</span>
87
+ </p>
88
+ <div class="nav"><a href="example-add-payment-info-card-autocomplete.html" class="">1. Autocomplete</a>
89
+ <a href="example-add-payment-info-card-fields.html" class="">2. id/name/CVV</a>
90
+ <a href="example-add-payment-info-card-disabled.html" class="">3. Detection off</a>
91
+ <a href="example-add-payment-info-manual.html" class="">4. Manual API</a>
92
+ <a href="example-add-payment-info-dedupe.html" class="">5. Dedupe sessão</a>
93
+ <a href="example-add-payment-info-security.html" class="active">6. Segurança</a>
94
+ <a href="example-add-payment-info-rules-card.html" class="">7. rules.card</a>
95
+ <a href="example-add-payment-info-data-track.html" class="">8. data-track</a></div>
96
+ <div class="hint"><strong>Contexto:</strong> o CardDetector só sinaliza que o preenchimento
97
+ <em>começou</em>. Nenhum número/CVV deve aparecer no evento JSON.
98
+ Painel Security check valida vazamento.</div>
99
+
100
+ <div class="card">
101
+ <h2>Lifecycle</h2>
102
+ <div class="actions">
103
+ <button id="btn-reinit" class="primary" type="button">Reinitialize</button>
104
+ <button id="btn-destroy" class="danger" type="button">Destroy</button>
105
+ <button id="btn-clear" type="button">Clear logs</button>
106
+ </div>
107
+ <div class="status" id="runtime-status">Aguardando init...</div>
108
+ </div>
109
+
110
+ <div class="grid">
111
+ <div>
112
+ <div class="card">
113
+ <h2>Não vazar dados do cartão <span class="pill">privacy</span></h2>
114
+ <div class="hint warn">
115
+ Use números de teste. O SDK não deve serializar o valor do input.
116
+ </div>
117
+ <div>
118
+ <label for="cc-sec">Número</label>
119
+ <input
120
+ id="cc-sec"
121
+ type="text"
122
+ autocomplete="cc-number"
123
+ placeholder="4111111111111111"
124
+ />
125
+ </div>
126
+ <div class="row" style="margin-top:0.75rem">
127
+ <div>
128
+ <label for="exp-sec">Validade</label>
129
+ <input id="exp-sec" type="text" autocomplete="cc-exp" placeholder="12/30" />
130
+ </div>
131
+ <div>
132
+ <label for="cvv-sec">CVV</label>
133
+ <input id="cvv-sec" type="text" autocomplete="cc-csc" placeholder="123" />
134
+ </div>
135
+ </div>
136
+ <p class="sub">Payload esperado: só <code>{ "paymentMethod": "CREDIT_CARD" }</code>.</p>
137
+ </div>
138
+ <div class="card">
139
+ <h2>Checklist</h2>
140
+ <ul class="checklist">
141
+ <li>[ ] Evento dispara ao digitar</li>
142
+ <li>[ ] Security check = OK</li>
143
+ <li>[ ] Last event JSON sem 4111… / CVV / validade</li>
144
+ <li>[ ] data só tem paymentMethod</li>
145
+ </ul>
146
+ </div>
147
+ </div>
148
+ <div>
149
+ <div class="card">
150
+ <h2>Event counts</h2>
151
+ <div class="status" id="event-counts">Nenhum evento ainda</div>
152
+ </div>
153
+ <div class="card">
154
+ <h2>Payment payload (último)</h2>
155
+ <div class="status" id="payment-payload">null</div>
156
+ </div>
157
+ <div class="card">
158
+ <h2>Security check</h2>
159
+ <div class="status" id="security-check">Aguardando evento...</div>
160
+ </div>
161
+ <div class="card">
162
+ <h2>Active detectors</h2>
163
+ <div class="status" id="detectors">—</div>
164
+ </div>
165
+
166
+ <div class="card">
167
+ <h2>Last event JSON</h2>
168
+ <pre id="last-event">null</pre>
169
+ </div>
170
+ <div class="card">
171
+ <h2>Event log</h2>
172
+ <pre id="logs">Aguardando eventos...</pre>
173
+ </div>
174
+ </div>
175
+ </div>
176
+ </div>
177
+
178
+ <script src="../../../dist/v2/global.global.js"></script>
179
+ <script>
180
+ const { Pixel, DEFAULT_PIXEL_CONFIG } = window.PixelV2;
181
+ const API_ENDPOINT =
182
+ 'https://micro-service-pixel-production-4826.up.railway.app';
183
+ const PIXEL_ID = 'pix_7315610';
184
+
185
+ const els = {
186
+ logs: document.getElementById('logs'),
187
+ last: document.getElementById('last-event'),
188
+ counts: document.getElementById('event-counts'),
189
+ payload: document.getElementById('payment-payload'),
190
+ security: document.getElementById('security-check'),
191
+ detectors: document.getElementById('detectors'),
192
+ dedupe: document.getElementById('dedupe-keys'),
193
+ runtime: document.getElementById('runtime-status'),
194
+ pill: document.getElementById('init-pill'),
195
+ };
196
+
197
+ let pixel = null;
198
+ let unsubscribe = null;
199
+ let initCount = 0;
200
+ let destroyCount = 0;
201
+ const counts = {};
202
+
203
+ function addPaymentInfoDetectorConfig() {
204
+ return {
205
+ enabled: true,
206
+ paymentMethod: 'CREDIT_CARD',
207
+ cardDetection: true,
208
+ autoDispatch: true,
209
+ };
210
+ }
211
+
212
+ function rulesConfig() {
213
+ return {
214
+ enabled: false,
215
+ selectors: [],
216
+ texts: [],
217
+ urlPatterns: [],
218
+ checkout: { enabled: false },
219
+ card: { enabled: false },
220
+ };
221
+ }
222
+
223
+ function buildConfig() {
224
+ const base = DEFAULT_PIXEL_CONFIG;
225
+ return {
226
+ ...base,
227
+ app: {
228
+ ...base.app,
229
+ source: 'custom',
230
+ environment: 'development',
231
+ debug: true,
232
+ },
233
+ transport: {
234
+ ...DEFAULT_PIXEL_CONFIG.transport,
235
+ apiEndpoint: API_ENDPOINT,
236
+ timeoutMs: 10000,
237
+ },
238
+ identity: { ...base.identity, pixelId: PIXEL_ID },
239
+ modules: {
240
+ ...base.modules,
241
+ core: {
242
+ ...base.modules.core,
243
+ enabled: false,
244
+ pageView: {
245
+ ...base.modules.core.pageView,
246
+ enabled: false,
247
+ trackInitialPageView: false,
248
+ spa: false,
249
+ },
250
+ },
251
+ behavior: { ...base.modules.behavior, enabled: false },
252
+ privacy: { ...base.modules.privacy, enabled: false },
253
+ transport: {
254
+ enabled: true,
255
+ mockSender: { enabled: false },
256
+ sender: { mode: 'http' },
257
+ persistence: { enabled: true },
258
+ replay: { enabled: true },
259
+ ordering: { enabled: true },
260
+ coordination: { enabled: true },
261
+ circuitBreaker: {
262
+ enabled: true,
263
+ failureThreshold: 5,
264
+ resetTimeoutMs: 30000,
265
+ halfOpenMaxAttempts: 2,
266
+ },
267
+ backpressure: {
268
+ enabled: true,
269
+ maxQueueSize: 500,
270
+ policy: 'drop_oldest',
271
+ sampleRate: 0.5,
272
+ },
273
+ deadLetter: { enabled: true, maxEntries: 200 },
274
+ compression: { enabled: true, strategy: 'identity' },
275
+ retry: {
276
+ enabled: true,
277
+ maxAttempts: 4,
278
+ baseDelayMs: 500,
279
+ maxDelayMs: 4000,
280
+ multiplier: 2,
281
+ },
282
+ batch: {
283
+ enabled: true,
284
+ batchSize: 10,
285
+ flushIntervalMs: 2000,
286
+ maxWaitMs: 5000,
287
+ },
288
+ timeout: { enabled: true, timeoutMs: 10000 },
289
+ offline: { enabled: true },
290
+ flush: {
291
+ enabled: true,
292
+ flushIntervalMs: 2000,
293
+ flushOnDestroy: true,
294
+ prepareUnloadHooks: true,
295
+ },
296
+ },
297
+ integrations: { ...base.modules.integrations, enabled: false },
298
+ conversion: {
299
+ enabled: true,
300
+ commerce: {
301
+ currency: 'BRL',
302
+ catalog: { products: [] },
303
+ checkout: {
304
+ mode: 'single_product',
305
+ selectedItems: [],
306
+ calculateValueFrom: 'selected_items',
307
+ allowDynamicItems: true,
308
+ },
309
+ mappings: {
310
+ attributes: {
311
+ productId: ['data-product-id'],
312
+ productName: ['data-product-name'],
313
+ price: ['data-product-price'],
314
+ quantity: ['data-quantity'],
315
+ currency: ['data-currency'],
316
+ },
317
+ fields: {
318
+ email: ['email'],
319
+ phone: ['phone'],
320
+ productId: ['productId'],
321
+ productName: ['productName'],
322
+ price: ['price'],
323
+ quantity: ['quantity'],
324
+ currency: ['currency'],
325
+ },
326
+ },
327
+ },
328
+ manual: {
329
+ pageView: { enabled: false },
330
+ purchase: { enabled: false },
331
+ lead: { enabled: false },
332
+ addToCart: { enabled: false },
333
+ removeFromCart: { enabled: false },
334
+ initiateCheckout: { enabled: false },
335
+ addPaymentInfo: { enabled: true },
336
+ search: { enabled: false },
337
+ viewContent: { enabled: false },
338
+ },
339
+ auto: {
340
+ enabled: true,
341
+ detectors: {
342
+ lead: { enabled: false },
343
+ purchase: { enabled: false },
344
+ addToCart: { enabled: false },
345
+ removeFromCart: { enabled: false },
346
+ initiateCheckout: { enabled: false },
347
+ addPaymentInfo: addPaymentInfoDetectorConfig(),
348
+ search: { enabled: false },
349
+ viewContent: { enabled: false },
350
+ },
351
+ },
352
+ rules: rulesConfig(),
353
+ },
354
+ },
355
+ };
356
+ }
357
+
358
+ function appendLog(message) {
359
+ const line = '[' + new Date().toISOString() + '] ' + message;
360
+ const prev = els.logs.textContent;
361
+ els.logs.textContent =
362
+ prev === 'Aguardando eventos...' ? line : line + '\n' + prev;
363
+ }
364
+
365
+ function renderCounts() {
366
+ const lines = Object.keys(counts)
367
+ .sort()
368
+ .map(function (type) { return type + ': ' + counts[type]; });
369
+ els.counts.textContent =
370
+ lines.length > 0 ? lines.join('\n') : 'Nenhum evento ainda';
371
+ }
372
+
373
+ function renderPayload(event) {
374
+ if (!els.payload) return;
375
+ if (!event || event.type !== 'ADD_PAYMENT_INFO') {
376
+ els.payload.textContent = 'null';
377
+ return;
378
+ }
379
+ els.payload.textContent = JSON.stringify(event.data || {}, null, 2);
380
+ }
381
+
382
+ function renderSecurity(event) {
383
+ if (!els.security) return;
384
+ if (!event) {
385
+ els.security.textContent = 'Aguardando evento...';
386
+ return;
387
+ }
388
+ var raw = JSON.stringify(event);
389
+ var leaks = [];
390
+ if (/4111/.test(raw)) leaks.push('encontrou "4111" (PAN parcial)');
391
+ if (/111111111111/.test(raw)) leaks.push('encontrou sequência de cartão');
392
+ if (/\b123\b/.test(raw) && /cvv|cvc|csc/i.test(raw)) {
393
+ leaks.push('possível CVV no JSON');
394
+ }
395
+ // valores tipicos de demo
396
+ ['4111111111111111', '4242424242424242', '12/30', '123'].forEach(function (v) {
397
+ if (raw.indexOf(v) !== -1) leaks.push('vazou valor: ' + v);
398
+ });
399
+ els.security.textContent =
400
+ leaks.length === 0
401
+ ? 'OK — nenhum valor sensível no payload/evento'
402
+ : 'FALHA:\n- ' + leaks.join('\n- ');
403
+ }
404
+
405
+ function renderDebug() {
406
+ const detectors =
407
+ pixel && pixel.getDebugActiveDetectors
408
+ ? pixel.getDebugActiveDetectors()
409
+ : [];
410
+ els.detectors.textContent =
411
+ detectors.length > 0 ? detectors.join('\n') : 'Nenhum detector ativo';
412
+ if (els.dedupe) {
413
+ const keys =
414
+ pixel && pixel.getDebugDedupeKeys ? pixel.getDebugDedupeKeys() : [];
415
+ els.dedupe.textContent =
416
+ keys.length > 0 ? keys.join('\n') : 'Nenhuma chave';
417
+ }
418
+ els.runtime.textContent =
419
+ 'initialized: ' +
420
+ (pixel ? pixel.isInitialized() : false) +
421
+ '\ninit count: ' +
422
+ initCount +
423
+ '\ndestroy count: ' +
424
+ destroyCount +
425
+ '\npixelId: ' +
426
+ PIXEL_ID +
427
+ '\nscenario: segurança · sem PAN/CVV';
428
+ els.pill.textContent =
429
+ pixel && pixel.isInitialized() ? 'ready' : 'offline';
430
+ els.pill.className =
431
+ 'pill' + (pixel && pixel.isInitialized() ? ' ok' : '');
432
+ }
433
+
434
+ function onEvent(event) {
435
+ counts[event.type] = (counts[event.type] || 0) + 1;
436
+ renderCounts();
437
+ renderPayload(event);
438
+ renderSecurity(event);
439
+ els.last.textContent = JSON.stringify(event, null, 2);
440
+ appendLog(event.type + ' ' + JSON.stringify(event.data || {}));
441
+ renderDebug();
442
+ }
443
+
444
+ async function boot() {
445
+ if (unsubscribe) { unsubscribe(); unsubscribe = null; }
446
+ if (pixel) {
447
+ await pixel.destroy();
448
+ destroyCount += 1;
449
+ pixel = null;
450
+ }
451
+ pixel = new Pixel(buildConfig());
452
+ await pixel.init();
453
+ initCount += 1;
454
+ const services = pixel.getDebugServices();
455
+ if (services && services.dispatcher) {
456
+ unsubscribe = services.dispatcher.subscribe(onEvent);
457
+ }
458
+ appendLog('Pixel initialized — segurança · sem PAN/CVV');
459
+ renderDebug();
460
+ }
461
+
462
+ async function destroyPixel() {
463
+ if (unsubscribe) { unsubscribe(); unsubscribe = null; }
464
+ if (pixel) {
465
+ await pixel.destroy();
466
+ destroyCount += 1;
467
+ pixel = null;
468
+ }
469
+ appendLog('Pixel destroyed');
470
+ renderDebug();
471
+ }
472
+
473
+ document.getElementById('btn-reinit').onclick = function () { boot(); };
474
+ document.getElementById('btn-destroy').onclick = function () { destroyPixel(); };
475
+ document.getElementById('btn-clear').onclick = function () {
476
+ els.logs.textContent = 'Aguardando eventos...';
477
+ els.last.textContent = 'null';
478
+ if (els.payload) els.payload.textContent = 'null';
479
+ if (els.security) els.security.textContent = 'Aguardando evento...';
480
+ Object.keys(counts).forEach(function (k) { delete counts[k]; });
481
+ renderCounts();
482
+ };
483
+
484
+
485
+
486
+ boot();
487
+ </script>
488
+ </body>
489
+ </html>
@@ -0,0 +1,36 @@
1
+ # Pixel v2 — ADD_TO_CART (cenários isolados)
2
+
3
+ Cada HTML valida **um** comportamento. Abra um de cada vez.
4
+
5
+ | # | Arquivo | Como dispara | O que valida |
6
+ |---|---------|--------------|--------------|
7
+ | 1 | [`example-add-to-cart-attribute.html`](./example-add-to-cart-attribute.html) | `[data-track="add_to_cart"]` + `data-product-*` | SelectorDetector + ProductExtractor + enrich catalog |
8
+ | 2 | [`example-add-to-cart-click.html`](./example-add-to-cart-click.html) | `selectorForm` + `trigger: click` | Gate email+phone antes do CTA |
9
+ | 3 | [`example-add-to-cart-auto.html`](./example-add-to-cart-auto.html) | `selectorForm` + `trigger: auto` | Disparo ao completar contato (`fireOnce`) |
10
+ | 4 | [`example-add-to-cart-text.html`](./example-add-to-cart-text.html) | `text:Comprar agora` + form | Match por texto + condição de form |
11
+ | 5 | [`example-add-to-cart-manual.html`](./example-add-to-cart-manual.html) | `pixel.addToCart()` | Payload manual, catalog, override de preço |
12
+ | 6 | [`example-add-to-cart-dedupe.html`](./example-add-to-cart-dedupe.html) | clique / API rápida | Janela ~500ms sem bloquear ação futura |
13
+ | 7 | [`example-add-to-cart-order-bump.html`](./example-add-to-cart-order-bump.html) | multi produto | CommerceState / cart mirror |
14
+
15
+ ## Fontes de produto (merge)
16
+
17
+ ```txt
18
+ 1. Payload manual
19
+ 2. data-* do elemento
20
+ 3. campos do formulário
21
+ 4. checkout.selectedItems
22
+ 5. catálogo commerce
23
+ 6. defaults
24
+ ```
25
+
26
+ ## Como abrir
27
+
28
+ 1. Na raiz: `npm run build`
29
+ 2. Abra o HTML (live server recomendado)
30
+ 3. Script: `../../../dist/v2/global.global.js`
31
+
32
+ ## Ordem sugerida
33
+
34
+ `atributo → click+form → auto → text → manual → dedupe → order bump`
35
+
36
+ LEAD (referência): [`../lead/`](../lead/)