@beworke/pixel 0.1.0-rc.13 → 0.1.0-rc.15

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 (41) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/browser/index.cjs.js +1 -1
  3. package/dist/browser/index.cjs.js.map +1 -1
  4. package/dist/browser/index.esm.js +1 -1
  5. package/dist/browser/index.esm.js.map +1 -1
  6. package/dist/browser/pixel.buygoods-checkout.global.js +1 -1
  7. package/dist/browser/pixel.buygoods-checkout.global.js.map +1 -1
  8. package/dist/browser/pixel.buygoods-landing.global.js +1 -1
  9. package/dist/browser/pixel.buygoods-landing.global.js.map +1 -1
  10. package/dist/browser/pixel.global.js +1 -1
  11. package/dist/browser/pixel.global.js.map +1 -1
  12. package/dist/browser/pixel.internal-checkout.global.js +1 -1
  13. package/dist/browser/pixel.internal-checkout.global.js.map +1 -1
  14. package/dist/events/index.cjs.js +1 -1
  15. package/dist/events/index.esm.js +1 -1
  16. package/dist/examples/html-script/README.md +11 -0
  17. package/dist/examples/html-script/customer/README.md +29 -0
  18. package/dist/examples/html-script/customer/example-customer-css.html +383 -0
  19. package/dist/examples/html-script/customer/example-customer-defaults.html +408 -0
  20. package/dist/examples/html-script/customer/example-customer-events.html +428 -0
  21. package/dist/examples/html-script/customer/example-customer-extra-fields.html +385 -0
  22. package/dist/index.cjs.js +1 -1
  23. package/dist/index.cjs.js.map +1 -1
  24. package/dist/index.esm.js +1 -1
  25. package/dist/index.esm.js.map +1 -1
  26. package/dist/runtime/index.cjs.js +1 -1
  27. package/dist/runtime/index.cjs.js.map +1 -1
  28. package/dist/runtime/index.esm.js +1 -1
  29. package/dist/runtime/index.esm.js.map +1 -1
  30. package/dist/services/index.cjs.js +1 -1
  31. package/dist/services/index.cjs.js.map +1 -1
  32. package/dist/services/index.esm.js +1 -1
  33. package/dist/services/index.esm.js.map +1 -1
  34. package/dist/v2/global.global.js +1 -1
  35. package/dist/v2/global.global.js.map +1 -1
  36. package/dist/v2/index.cjs.js +1 -1
  37. package/dist/v2/index.cjs.js.map +1 -1
  38. package/dist/v2/index.esm.js +1 -1
  39. package/dist/v2/index.esm.js.map +1 -1
  40. package/docs/public/configuration/commerce.md +3 -1
  41. package/package.json +1 -1
@@ -0,0 +1,428 @@
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 — Customer em todos os eventos</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
+ label { display: block; font-size: 0.8rem; color: var(--muted); margin-bottom: 0.25rem; }
51
+ input {
52
+ width: 100%; border: 1px solid var(--border); border-radius: 8px;
53
+ padding: 0.55rem 0.7rem; font: inherit; background: #fff;
54
+ }
55
+ .row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
56
+ @media (max-width: 560px) { .row { grid-template-columns: 1fr; } }
57
+ .status, pre {
58
+ background: #0f172a; color: #e2e8f0; border-radius: 8px; padding: 0.75rem;
59
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
60
+ font-size: 0.78rem; white-space: pre-wrap; word-break: break-word;
61
+ max-height: 260px; overflow: auto;
62
+ }
63
+ .pill {
64
+ display: inline-block; border-radius: 999px; padding: 0.15rem 0.55rem;
65
+ font-size: 0.72rem; background: #e2e8f0; color: #334155; margin-left: 0.35rem;
66
+ }
67
+ .pill.ok { background: #bbf7d0; color: #166534; }
68
+ .checklist { margin: 0; padding-left: 1.1rem; font-size: 0.88rem; color: var(--muted); }
69
+ .checklist li { margin: 0.35rem 0; }
70
+ .ctx {
71
+ border-left: 3px solid var(--accent); padding-left: 0.75rem; margin-bottom: 0.85rem;
72
+ color: var(--muted); font-size: 0.88rem;
73
+ }
74
+ code { font-size: 0.85em; }
75
+ </style>
76
+ </head>
77
+ <body>
78
+ <div class="wrap">
79
+ <h1>Customer — em todos os eventos <span class="pill" id="init-pill">offline</span></h1>
80
+ <p class="sub">
81
+ PAGE_VIEW no init (form vazio). Depois do preenchimento, ATC, pay e HEARTBEAT levam customer.
82
+ </p>
83
+ <div class="nav">
84
+ <a href="example-customer-defaults.html">1. Defaults</a>
85
+ <a href="example-customer-extra-fields.html">2. Extra name/id</a>
86
+ <a href="example-customer-css.html">3. CSS</a>
87
+ <a href="example-customer-events.html" class="active">4. Eventos</a>
88
+ </div>
89
+ <div class="hint warn">
90
+ O <code>PAGE_VIEW</code> do init sai <strong>sem</strong> customer
91
+ (form vazio). Preencha e veja ATC, pay e o HEARTBEAT seguinte (8s).
92
+ </div>
93
+
94
+ <div class="card">
95
+ <h2>Lifecycle</h2>
96
+ <div class="actions">
97
+ <button id="btn-reinit" class="primary" type="button">Reinitialize</button>
98
+ <button id="btn-destroy" class="danger" type="button">Destroy</button>
99
+ <button id="btn-fill" type="button">Preencher demo</button>
100
+ <button id="btn-clear" type="button">Clear logs</button>
101
+ </div>
102
+ <div class="status" id="runtime-status">Aguardando init...</div>
103
+ </div>
104
+
105
+ <div class="grid">
106
+ <div>
107
+ <div class="card">
108
+ <h2>Form + pay</h2>
109
+ <div class="ctx">
110
+ Email + phone → ATC. Clique em Pagar →
111
+ <code>ADD_PAYMENT_INFO</code>.
112
+ </div>
113
+ <form id="customer-form">
114
+ <div class="row">
115
+ <div>
116
+ <label for="email">email</label>
117
+ <input id="email" name="email" type="email" />
118
+ </div>
119
+ <div>
120
+ <label for="phone">phone</label>
121
+ <input id="phone" name="phone" type="tel" />
122
+ </div>
123
+ </div>
124
+ <div class="row">
125
+ <div>
126
+ <label for="first_name">first_name</label>
127
+ <input id="first_name" name="first_name" />
128
+ </div>
129
+ <div>
130
+ <label for="last_name">last_name</label>
131
+ <input id="last_name" name="last_name" />
132
+ </div>
133
+ </div>
134
+ <div class="row">
135
+ <div>
136
+ <label for="address">address</label>
137
+ <input id="address" name="address" />
138
+ </div>
139
+ <div>
140
+ <label for="cep">cep</label>
141
+ <input id="cep" name="cep" />
142
+ </div>
143
+ </div>
144
+ <div class="actions">
145
+ <button type="button" class="primary" data-track="add_payment_info" data-checkout="true">
146
+ Pagar
147
+ </button>
148
+ </div>
149
+ </form>
150
+ </div>
151
+ <div class="card">
152
+ <h2>Checklist</h2>
153
+ <ul class="checklist">
154
+ <li>[ ] Init → PAGE_VIEW sem customer</li>
155
+ <li>[ ] Preencher → snapshot preenchido</li>
156
+ <li>[ ] ATC com <code>customer</code></li>
157
+ <li>[ ] Pagar → ADD_PAYMENT_INFO com o mesmo customer</li>
158
+ <li>[ ] Próximo HEARTBEAT (≤8s) também com customer</li>
159
+ </ul>
160
+ </div>
161
+ </div>
162
+ <div>
163
+ <div class="card">
164
+ <h2>Customer snapshot</h2>
165
+ <pre id="customer-snap">null</pre>
166
+ </div>
167
+ <div class="card">
168
+ <h2>Event counts</h2>
169
+ <div class="status" id="event-counts">Nenhum evento ainda</div>
170
+ </div>
171
+ <div class="card">
172
+ <h2>Last event.customer</h2>
173
+ <pre id="last-customer">null</pre>
174
+ </div>
175
+ <div class="card">
176
+ <h2>Last event JSON</h2>
177
+ <pre id="last-event">null</pre>
178
+ </div>
179
+ <div class="card">
180
+ <h2>Event log</h2>
181
+ <pre id="logs">Aguardando eventos...</pre>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </div>
186
+
187
+ <script src="../../../browser/pixel.global.js"></script>
188
+ <script>
189
+ const PIXEL_ID = 'pix_7315610';
190
+ const API_ENDPOINT =
191
+ 'https://micro-service-pixel-production-4826.up.railway.app';
192
+
193
+ const els = {
194
+ logs: document.getElementById('logs'),
195
+ last: document.getElementById('last-event'),
196
+ lastCustomer: document.getElementById('last-customer'),
197
+ customer: document.getElementById('customer-snap'),
198
+ counts: document.getElementById('event-counts'),
199
+ runtime: document.getElementById('runtime-status'),
200
+ pill: document.getElementById('init-pill'),
201
+ };
202
+
203
+ let pixel = null;
204
+ let unsubscribe = null;
205
+ let initCount = 0;
206
+ let destroyCount = 0;
207
+ const counts = {};
208
+
209
+ function disabledDetector() {
210
+ return { enabled: false, sources: [] };
211
+ }
212
+
213
+ function buildSettings() {
214
+ return {
215
+ identity: { pixelId: PIXEL_ID },
216
+ app: { source: 'custom', environment: 'development', debug: true },
217
+ transport: {
218
+ enabled: true,
219
+ sender: { mode: 'internal', baseUrl: API_ENDPOINT },
220
+ },
221
+ commerce: {
222
+ enabled: true,
223
+ currency: 'BRL',
224
+ catalog: {
225
+ products: [
226
+ { id: 'main_offer', name: 'Oferta Principal', type: 'main', price: 197, currency: 'BRL', quantity: 1 },
227
+ ],
228
+ },
229
+ cart: {
230
+ mode: 'single_product',
231
+ initialItems: [{ productId: 'main_offer', quantity: 1 }],
232
+ },
233
+ },
234
+ modules: {
235
+ core: {
236
+ enabled: true,
237
+ pageView: { enabled: true, trackInitialPageView: true, spa: false },
238
+ },
239
+ behavior: {
240
+ enabled: true,
241
+ heartbeat: {
242
+ enabled: true,
243
+ intervalMs: 8000,
244
+ hiddenIntervalMs: 60000,
245
+ emitWhenHidden: true,
246
+ emitWhenIdle: true,
247
+ includeSnapshot: true,
248
+ fireImmediately: false,
249
+ },
250
+ trackers: {
251
+ idle: { enabled: false },
252
+ visibility: { enabled: false },
253
+ scroll: { enabled: false },
254
+ click: { enabled: false },
255
+ exitIntent: { enabled: false },
256
+ },
257
+ },
258
+ conversion: {
259
+ enabled: true,
260
+ auto: {
261
+ enabled: true,
262
+ detectors: {
263
+ lead: disabledDetector(),
264
+ purchase: disabledDetector(),
265
+ removeFromCart: disabledDetector(),
266
+ initiateCheckout: disabledDetector(),
267
+ search: disabledDetector(),
268
+ viewContent: disabledDetector(),
269
+ addToCart: {
270
+ enabled: true,
271
+ sources: [
272
+ {
273
+ name: 'customer-form',
274
+ type: 'form',
275
+ selectorForm: {
276
+ fields: ['email', 'phone'],
277
+ mode: 'all',
278
+ formSelector: '#customer-form',
279
+ trigger: 'auto',
280
+ debounceMs: 300,
281
+ fireOnce: true,
282
+ },
283
+ selector: ['#customer-form'],
284
+ selectorType: 'css',
285
+ },
286
+ ],
287
+ },
288
+ addPaymentInfo: {
289
+ enabled: true,
290
+ sources: [
291
+ {
292
+ name: 'pay-click',
293
+ type: 'selector',
294
+ selector: '[data-track="add_payment_info"]',
295
+ selectorType: 'css',
296
+ trigger: 'click',
297
+ fireOnce: false,
298
+ },
299
+ ],
300
+ },
301
+ },
302
+ },
303
+ },
304
+ },
305
+ };
306
+ }
307
+
308
+ function appendLog(message) {
309
+ const line = '[' + new Date().toISOString() + '] ' + message;
310
+ const prev = els.logs.textContent;
311
+ els.logs.textContent =
312
+ prev === 'Aguardando eventos...' ? line : line + '\n' + prev;
313
+ }
314
+
315
+ function renderCounts() {
316
+ const lines = Object.keys(counts)
317
+ .sort()
318
+ .map(function (type) { return type + ': ' + counts[type]; });
319
+ els.counts.textContent =
320
+ lines.length > 0 ? lines.join('\n') : 'Nenhum evento ainda';
321
+ }
322
+
323
+ function eventCustomer(event) {
324
+ if (event && event.customer) return event.customer;
325
+ if (event && event.data && event.data.customer) return event.data.customer;
326
+ return null;
327
+ }
328
+
329
+ function renderCustomer() {
330
+ const services = pixel && pixel.getDebugServices ? pixel.getDebugServices() : null;
331
+ const snap =
332
+ services && services.customerIdentity
333
+ ? services.customerIdentity.getSnapshot()
334
+ : null;
335
+ els.customer.textContent = snap ? JSON.stringify(snap, null, 2) : 'null';
336
+ }
337
+
338
+ function renderDebug() {
339
+ els.runtime.textContent =
340
+ 'initialized: ' +
341
+ (pixel ? pixel.isInitialized() : false) +
342
+ '\ninit count: ' +
343
+ initCount +
344
+ '\ndestroy count: ' +
345
+ destroyCount +
346
+ '\npixelId: ' +
347
+ PIXEL_ID +
348
+ '\nscenario: customer em todos os eventos';
349
+ els.pill.textContent =
350
+ pixel && pixel.isInitialized() ? 'ready' : 'offline';
351
+ els.pill.className =
352
+ 'pill' + (pixel && pixel.isInitialized() ? ' ok' : '');
353
+ renderCustomer();
354
+ }
355
+
356
+ function onEvent(event) {
357
+ counts[event.type] = (counts[event.type] || 0) + 1;
358
+ renderCounts();
359
+ els.last.textContent = JSON.stringify(event, null, 2);
360
+ const customer = eventCustomer(event);
361
+ els.lastCustomer.textContent = customer
362
+ ? JSON.stringify(customer, null, 2)
363
+ : 'null';
364
+ appendLog(event.type + ' customer=' + JSON.stringify(customer));
365
+ renderDebug();
366
+ }
367
+
368
+ async function boot() {
369
+ if (unsubscribe) { unsubscribe(); unsubscribe = null; }
370
+ if (pixel) {
371
+ await pixel.destroy();
372
+ destroyCount += 1;
373
+ pixel = null;
374
+ }
375
+ pixel = await Pixel.create(buildSettings());
376
+ initCount += 1;
377
+ const services = pixel.getDebugServices();
378
+ if (services && services.dispatcher) {
379
+ unsubscribe = services.dispatcher.subscribe(onEvent);
380
+ const already = services.dispatcher.getLastEvent
381
+ ? services.dispatcher.getLastEvent()
382
+ : null;
383
+ if (already) onEvent(already);
384
+ }
385
+ appendLog('Pixel initialized — customer events');
386
+ renderDebug();
387
+ }
388
+
389
+ async function destroyPixel() {
390
+ if (unsubscribe) { unsubscribe(); unsubscribe = null; }
391
+ if (pixel) {
392
+ await pixel.destroy();
393
+ destroyCount += 1;
394
+ pixel = null;
395
+ }
396
+ appendLog('Pixel destroyed');
397
+ renderDebug();
398
+ }
399
+
400
+ document.getElementById('btn-reinit').onclick = function () { boot(); };
401
+ document.getElementById('btn-destroy').onclick = function () { destroyPixel(); };
402
+ document.getElementById('btn-clear').onclick = function () {
403
+ els.logs.textContent = 'Aguardando eventos...';
404
+ els.last.textContent = 'null';
405
+ els.lastCustomer.textContent = 'null';
406
+ Object.keys(counts).forEach(function (k) { delete counts[k]; });
407
+ renderCounts();
408
+ };
409
+ document.getElementById('btn-fill').onclick = function () {
410
+ document.getElementById('email').value = 'eventos@exemplo.com';
411
+ document.getElementById('phone').value = '11966665555';
412
+ document.getElementById('first_name').value = 'Eva';
413
+ document.getElementById('last_name').value = 'Santos';
414
+ document.getElementById('address').value = 'Av. Paulista 1000';
415
+ document.getElementById('cep').value = '01310-200';
416
+ document.getElementById('customer-form').querySelectorAll('input').forEach(function (input) {
417
+ input.dispatchEvent(new Event('input', { bubbles: true }));
418
+ });
419
+ };
420
+
421
+ document.getElementById('customer-form').addEventListener('input', function () {
422
+ setTimeout(renderCustomer, 250);
423
+ });
424
+
425
+ boot();
426
+ </script>
427
+ </body>
428
+ </html>