@beworke/pixel-bemony 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 (67) hide show
  1. package/CHANGELOG.md +157 -0
  2. package/README.md +176 -0
  3. package/RELEASE_CANDIDATE.md +37 -0
  4. package/dist/browser/index.cjs.js +2598 -0
  5. package/dist/browser/index.cjs.js.map +1 -0
  6. package/dist/browser/index.d.mts +184 -0
  7. package/dist/browser/index.d.ts +184 -0
  8. package/dist/browser/index.esm.js +2557 -0
  9. package/dist/browser/index.esm.js.map +1 -0
  10. package/dist/browser/pixel-bemony.global.js +9848 -0
  11. package/dist/browser/pixel-bemony.global.js.map +1 -0
  12. package/dist/createBemonyPixel-BGRD66p-.d.mts +474 -0
  13. package/dist/createBemonyPixel-BGRD66p-.d.ts +474 -0
  14. package/dist/index.cjs.js +2154 -0
  15. package/dist/index.cjs.js.map +1 -0
  16. package/dist/index.d.mts +320 -0
  17. package/dist/index.d.ts +320 -0
  18. package/dist/index.esm.js +2081 -0
  19. package/dist/index.esm.js.map +1 -0
  20. package/docs/BACKEND_PURCHASE_AND_REDIRECTS.md +125 -0
  21. package/docs/BROWSER_EVENT_ENRICHMENT.md +116 -0
  22. package/docs/SCENARIOS.md +92 -0
  23. package/docs/SECURITY_LIMITATIONS.md +45 -0
  24. package/docs/TEST_MATRIX.md +39 -0
  25. package/docs/TROUBLESHOOTING.md +81 -0
  26. package/examples/README.md +73 -0
  27. package/examples/browser-bootstrap.html +47 -0
  28. package/examples/checkout-price-code.html +37 -0
  29. package/examples/funnel/donsell/downsell_1.html +130 -0
  30. package/examples/funnel/donsell/downsell_2.html +130 -0
  31. package/examples/funnel/donsell/downsell_3.html +130 -0
  32. package/examples/funnel/offer-page.html +105 -0
  33. package/examples/funnel/upsell/upsell_1.html +130 -0
  34. package/examples/funnel/upsell/upsell_2.html +130 -0
  35. package/examples/funnel/upsell/upsell_3.html +139 -0
  36. package/examples/offer-page-price-code.html +22 -0
  37. package/examples/one-click-price-code.html +38 -0
  38. package/examples/security/checkout-sim.css +408 -0
  39. package/examples/security/checkout-sim.js +414 -0
  40. package/examples/security/one-click/pri_downsell_1.html +85 -0
  41. package/examples/security/one-click/pri_downsell_1a.html +85 -0
  42. package/examples/security/one-click/pri_downsell_1b.html +78 -0
  43. package/examples/security/one-click/pri_downsell_2.html +78 -0
  44. package/examples/security/one-click/pri_downsell_2a.html +78 -0
  45. package/examples/security/one-click/pri_downsell_2b.html +78 -0
  46. package/examples/security/one-click/pri_downsell_3.html +78 -0
  47. package/examples/security/one-click/pri_downsell_3a.html +78 -0
  48. package/examples/security/one-click/pri_downsell_3b.html +78 -0
  49. package/examples/security/one-click/pri_upsell_1.html +78 -0
  50. package/examples/security/one-click/pri_upsell_1a.html +78 -0
  51. package/examples/security/one-click/pri_upsell_1b.html +78 -0
  52. package/examples/security/one-click/pri_upsell_2.html +78 -0
  53. package/examples/security/one-click/pri_upsell_2a.html +78 -0
  54. package/examples/security/one-click/pri_upsell_2b.html +78 -0
  55. package/examples/security/one-click/pri_upsell_3.html +78 -0
  56. package/examples/security/one-click/pri_upsell_3a.html +78 -0
  57. package/examples/security/one-click/pri_upsell_3b.html +78 -0
  58. package/examples/security/one-click/pri_upsell_3c.html +78 -0
  59. package/examples/security/pri1766322.html +333 -0
  60. package/examples/security/pri5529930.html +333 -0
  61. package/examples/security/pri6670988.html +334 -0
  62. package/examples/security/thank-you.html +65 -0
  63. package/examples/sim/funnel-flow.js +258 -0
  64. package/examples/sim/one-click-sim.js +167 -0
  65. package/examples/upsell-price-code.html +41 -0
  66. package/examples/url-context-navigation.html +96 -0
  67. package/package.json +63 -0
@@ -0,0 +1,414 @@
1
+ /**
2
+ * Wiring compartilhado das telas de checkout simuladas (offer_1/2/3).
3
+ * Order bump: checkbox dispara click em triggers com data-track
4
+ * (detectors auto ADD_TO_CART / REMOVE_FROM_CART).
5
+ */
6
+ (function () {
7
+ var cfg = window.__CHECKOUT_SIM__;
8
+ if (!cfg || !cfg.main || !cfg.bump) {
9
+ console.error('[checkout-sim] window.__CHECKOUT_SIM__ incompleto');
10
+ return;
11
+ }
12
+
13
+ var main = cfg.main;
14
+ var bump = cfg.bump;
15
+ var currency = cfg.currency || 'BRL';
16
+ var hasBump = false;
17
+ var paymentMethod = 'CREDIT_CARD';
18
+ var pixelRef = null;
19
+ var bumpLockUntil = 0;
20
+
21
+ function money(value) {
22
+ return new Intl.NumberFormat('pt-BR', {
23
+ style: 'currency',
24
+ currency: currency,
25
+ }).format(value);
26
+ }
27
+
28
+ function $(id) {
29
+ return document.getElementById(id);
30
+ }
31
+
32
+ function setStatus(ready, error) {
33
+ var el = $('pixel-status');
34
+ if (!el) return;
35
+ el.className = 'pill ' + (error ? 'bad' : ready ? 'ok' : '');
36
+ el.textContent = error ? 'Erro' : ready ? 'Pronto' : 'Init…';
37
+ }
38
+
39
+ /** Resolve o namespace real (API com whenReady), mesmo se o IIFE sobrescrever. */
40
+ function getBemonyApi() {
41
+ var bp = window.BemonyPixel;
42
+ if (!bp) return null;
43
+ if (typeof bp.whenReady === 'function') return bp;
44
+ if (
45
+ bp.bemonyPixelGlobalApi &&
46
+ typeof bp.bemonyPixelGlobalApi.whenReady === 'function'
47
+ ) {
48
+ return bp.bemonyPixelGlobalApi;
49
+ }
50
+ return bp;
51
+ }
52
+
53
+ function renderCart() {
54
+ var list = $('cart-lines');
55
+ var empty = $('cart-empty');
56
+ var totalEl = $('cart-total');
57
+ if (!list || !totalEl) return;
58
+
59
+ var lines = [
60
+ {
61
+ id: main.id,
62
+ name: main.name,
63
+ qty: 1,
64
+ price: main.price,
65
+ },
66
+ ];
67
+ if (hasBump) {
68
+ lines.push({
69
+ id: bump.id,
70
+ name: bump.name,
71
+ qty: 1,
72
+ price: bump.price,
73
+ });
74
+ }
75
+
76
+ list.innerHTML = '';
77
+ lines.forEach(function (line) {
78
+ var li = document.createElement('li');
79
+ li.innerHTML =
80
+ '<div><div>' +
81
+ line.name +
82
+ '</div><div class="line-meta">' +
83
+ line.id +
84
+ ' · qty ' +
85
+ line.qty +
86
+ '</div></div><span>' +
87
+ money(line.price * line.qty) +
88
+ '</span>';
89
+ list.appendChild(li);
90
+ });
91
+
92
+ if (empty) empty.hidden = lines.length > 0;
93
+ list.hidden = lines.length === 0;
94
+
95
+ var total = lines.reduce(function (sum, line) {
96
+ return sum + line.price * line.qty;
97
+ }, 0);
98
+ totalEl.textContent = money(total);
99
+ }
100
+
101
+ function syncDebug() {
102
+ if (!pixelRef) return;
103
+ var snap = pixelRef.getDebugSnapshot();
104
+ var sent = $('dbg-transport');
105
+ var detectors = $('dbg-detectors');
106
+ var dedupe = $('dbg-dedupe');
107
+ var sid = $('dbg-sid');
108
+ var afid = $('dbg-afid');
109
+ var cart = $('dbg-cart');
110
+
111
+ if (sent) {
112
+ sent.textContent =
113
+ snap.transport && snap.transport.sentCount !== undefined
114
+ ? String(snap.transport.sentCount)
115
+ : '—';
116
+ }
117
+ if (detectors) {
118
+ var active =
119
+ (snap.conversion && snap.conversion.activeDetectors) || [];
120
+ detectors.textContent =
121
+ active.length > 0 ? active.join(', ') : '—';
122
+ }
123
+ if (dedupe) {
124
+ dedupe.textContent =
125
+ snap.conversion && snap.conversion.dedupeKeyCount !== undefined
126
+ ? String(snap.conversion.dedupeKeyCount)
127
+ : '—';
128
+ }
129
+ if (sid) {
130
+ sid.textContent = pixelRef.getPublicSessionId() || '—';
131
+ }
132
+ if (afid) {
133
+ var fromUrl = new URLSearchParams(location.search).get('afid');
134
+ var fromSource =
135
+ snap.urlContext &&
136
+ snap.urlContext.source &&
137
+ snap.urlContext.source.afid;
138
+ var fromAttr =
139
+ snap.attribution &&
140
+ snap.attribution.identifiers &&
141
+ snap.attribution.identifiers.afid;
142
+ afid.textContent = fromUrl || fromSource || fromAttr || '—';
143
+ }
144
+ if (cart) {
145
+ var commerce = snap.commerce || {};
146
+ cart.textContent =
147
+ 'items=' +
148
+ (commerce.itemCount ?? '—') +
149
+ ' value=' +
150
+ (commerce.cartValue != null ? money(commerce.cartValue) : '—') +
151
+ ' ids=[' +
152
+ ((commerce.productIds || []).join(', ') || '—') +
153
+ ']';
154
+ }
155
+ }
156
+
157
+ function tryLead() {
158
+ if (!pixelRef) return;
159
+ var email = ($('email') && $('email').value) || '';
160
+ var phone = ($('phone') && $('phone').value) || '';
161
+ var emitted = pixelRef.captureLead({ email: email, phone: phone });
162
+ if (emitted) syncDebug();
163
+ }
164
+
165
+ function fireTrackClick(el) {
166
+ if (!el) return;
167
+ el.dispatchEvent(
168
+ new MouseEvent('click', {
169
+ bubbles: true,
170
+ cancelable: true,
171
+ view: window,
172
+ })
173
+ );
174
+ }
175
+
176
+ function applyBump(wantOn) {
177
+ var box = $('bump-check');
178
+ var addBtn = $('bump-add');
179
+ var removeBtn = $('bump-remove');
180
+ if (!pixelRef || !box || !addBtn || !removeBtn) return;
181
+
182
+ bumpLockUntil = Date.now() + 1200;
183
+ hasBump = wantOn;
184
+ box.checked = wantOn;
185
+ renderCart();
186
+
187
+ if (wantOn) {
188
+ console.log('[checkout-sim] bump ON → data-track=add_to_cart', bump.id);
189
+ fireTrackClick(addBtn);
190
+ } else {
191
+ console.log('[checkout-sim] bump OFF → data-track=remove_from_cart', bump.id);
192
+ fireTrackClick(removeBtn);
193
+ }
194
+
195
+ window.setTimeout(function () {
196
+ syncBumpFromPixel(false);
197
+ syncDebug();
198
+ }, 120);
199
+ }
200
+
201
+ function wireBump() {
202
+ var box = $('bump-check');
203
+ var addBtn = $('bump-add');
204
+ var removeBtn = $('bump-remove');
205
+ if (!box || !addBtn || !removeBtn) {
206
+ console.error(
207
+ '[checkout-sim] bump markup incompleto (#bump-check/#bump-add/#bump-remove)'
208
+ );
209
+ return;
210
+ }
211
+
212
+ box.disabled = false;
213
+
214
+ box.addEventListener('change', function () {
215
+ var wantOn = box.checked;
216
+ if (pixelRef) {
217
+ applyBump(wantOn);
218
+ return;
219
+ }
220
+ // Enfileira até o Pixel ficar ready (não descarta o clique)
221
+ console.log('[checkout-sim] bump pendente — aguardando Pixel ready…');
222
+ waitForPixel()
223
+ .then(function () {
224
+ applyBump(wantOn);
225
+ })
226
+ .catch(function (error) {
227
+ box.checked = false;
228
+ console.error('[checkout-sim] bump falhou', error);
229
+ });
230
+ });
231
+ }
232
+
233
+ function syncBumpFromPixel(forceCheckbox) {
234
+ if (!pixelRef) return;
235
+ var commerce = pixelRef.getDebugSnapshot().commerce || {};
236
+ var ids = commerce.productIds || [];
237
+ var inCart = ids.indexOf(bump.id) !== -1;
238
+ hasBump = inCart;
239
+
240
+ var box = $('bump-check');
241
+ var locked = Date.now() < bumpLockUntil;
242
+ if (box && (forceCheckbox || !locked) && box.checked !== inCart) {
243
+ box.checked = inCart;
244
+ }
245
+ renderCart();
246
+ }
247
+
248
+ function wirePayment() {
249
+ document.querySelectorAll('.pay-tab').forEach(function (btn) {
250
+ btn.addEventListener('click', function () {
251
+ if (btn.disabled) return;
252
+ paymentMethod = btn.getAttribute('data-method') || 'CREDIT_CARD';
253
+ document.querySelectorAll('.pay-tab').forEach(function (b) {
254
+ b.setAttribute('aria-selected', b === btn ? 'true' : 'false');
255
+ });
256
+ var cardFields = $('card-fields');
257
+ if (cardFields) {
258
+ cardFields.hidden = paymentMethod !== 'CREDIT_CARD';
259
+ }
260
+ if (pixelRef) {
261
+ pixelRef.trackPaymentMethod({ paymentMethod: paymentMethod });
262
+ syncDebug();
263
+ }
264
+ });
265
+ });
266
+ }
267
+
268
+ function wireForm() {
269
+ var form = $('checkout-form');
270
+ if (!form) return;
271
+
272
+ ['email', 'phone'].forEach(function (id) {
273
+ var el = $(id);
274
+ if (!el) return;
275
+ el.addEventListener('blur', tryLead);
276
+ el.addEventListener('change', tryLead);
277
+ });
278
+
279
+ var addr2Toggle = $('addr2-toggle');
280
+ var addr2 = $('addr2-field');
281
+ if (addr2Toggle && addr2) {
282
+ addr2Toggle.addEventListener('click', function () {
283
+ addr2.hidden = false;
284
+ addr2Toggle.hidden = true;
285
+ });
286
+ }
287
+
288
+ form.addEventListener('submit', function (event) {
289
+ event.preventDefault();
290
+ if (!pixelRef) return;
291
+ tryLead();
292
+ pixelRef.trackPaymentMethod({ paymentMethod: paymentMethod });
293
+ pixelRef.startCheckout({
294
+ value: hasBump ? main.price + bump.price : main.price,
295
+ currency: currency,
296
+ });
297
+ syncDebug();
298
+
299
+ var sim = window.BemonyFunnelSim;
300
+ var oid = sim ? sim.ensureOid() : 'ord_local';
301
+ var nextHref =
302
+ (cfg.nextHref) ||
303
+ (sim && sim.FLOW && sim.FLOW.afterCheckout) ||
304
+ '../funnel/upsell/upsell_1.html';
305
+
306
+ console.log('[checkout-sim] Complete order → upsell', {
307
+ sid: pixelRef.getPublicSessionId(),
308
+ paymentMethod: paymentMethod,
309
+ hasBump: hasBump,
310
+ oid: oid,
311
+ nextHref: nextHref,
312
+ });
313
+
314
+ // Simula redirect 302 pós-pagamento → página externa de upsell
315
+ window.setTimeout(function () {
316
+ if (sim) {
317
+ sim.navigate(nextHref, { oid: oid });
318
+ } else {
319
+ var url = new URL(nextHref, location.href);
320
+ url.searchParams.set('oid', oid);
321
+ location.assign(url.pathname + url.search);
322
+ }
323
+ }, 400);
324
+ });
325
+ }
326
+
327
+ function waitForPixel(attempt) {
328
+ var n = attempt || 0;
329
+ var api = getBemonyApi();
330
+
331
+ if (api) {
332
+ if (typeof api.getBootstrappedBemonyPixel === 'function') {
333
+ var existing = api.getBootstrappedBemonyPixel();
334
+ if (existing && existing.getState && existing.getState() === 'ready') {
335
+ return Promise.resolve(existing);
336
+ }
337
+ }
338
+ if (typeof api.whenReady === 'function') {
339
+ return api.whenReady();
340
+ }
341
+ if (api.ready && typeof api.ready.then === 'function') {
342
+ return api.ready.then(function (pixel) {
343
+ if (pixel) return pixel;
344
+ throw new Error('BemonyPixel.ready resolveu null');
345
+ });
346
+ }
347
+ }
348
+
349
+ if (n > 80) {
350
+ return Promise.reject(
351
+ new Error(
352
+ 'BemonyPixel indisponível após espera (sem whenReady/getBootstrapped)'
353
+ )
354
+ );
355
+ }
356
+
357
+ return new Promise(function (resolve, reject) {
358
+ window.setTimeout(function () {
359
+ waitForPixel(n + 1).then(resolve, reject);
360
+ }, 50);
361
+ });
362
+ }
363
+
364
+ function onPixelReady(pixel) {
365
+ pixelRef = pixel;
366
+ setStatus(true, null);
367
+ var box = $('bump-check');
368
+ if (box) box.disabled = false;
369
+ syncBumpFromPixel(true);
370
+ syncDebug();
371
+ setInterval(function () {
372
+ syncBumpFromPixel(false);
373
+ syncDebug();
374
+ }, 1500);
375
+ console.log('[checkout-sim] ready', {
376
+ offer: main.id,
377
+ sid: pixel.getPublicSessionId(),
378
+ detectors: pixel.getDebugSnapshot().conversion.activeDetectors,
379
+ commerce: pixel.getDebugSnapshot().commerce,
380
+ });
381
+ }
382
+
383
+ function boot() {
384
+ setStatus(false, null);
385
+ renderCart();
386
+ wireBump();
387
+ wirePayment();
388
+ wireForm();
389
+
390
+ document.addEventListener('bemony:pixel:ready', function (event) {
391
+ if (pixelRef) return;
392
+ var detail = event && event.detail;
393
+ var pixel = detail && detail.pixel;
394
+ if (pixel) onPixelReady(pixel);
395
+ });
396
+
397
+ waitForPixel()
398
+ .then(onPixelReady)
399
+ .catch(function (error) {
400
+ setStatus(false, true);
401
+ console.error('[checkout-sim] error', error);
402
+ console.error(
403
+ '[checkout-sim] window.BemonyPixel keys:',
404
+ window.BemonyPixel ? Object.keys(window.BemonyPixel) : null
405
+ );
406
+ });
407
+ }
408
+
409
+ if (document.readyState === 'loading') {
410
+ document.addEventListener('DOMContentLoaded', boot);
411
+ } else {
412
+ boot();
413
+ }
414
+ })();
@@ -0,0 +1,85 @@
1
+ <!doctype html>
2
+ <html lang="pt-BR">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Security · One-click Downsell · pri_downsell_1</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <style>
8
+ body {
9
+ font-family: Georgia, 'Times New Roman', serif;
10
+ max-width: 28rem;
11
+ margin: 0 auto;
12
+ padding: 2rem 1rem;
13
+ background: linear-gradient(165deg, #e8eef0, #f4f1ea);
14
+ color: #17201b;
15
+ line-height: 1.5;
16
+ }
17
+ button {
18
+ width: 100%;
19
+ padding: 0.9rem;
20
+ background: #122019;
21
+ color: #fff;
22
+ border: 0;
23
+ border-radius: 4px;
24
+ cursor: pointer;
25
+ }
26
+ button:disabled {
27
+ opacity: 0.5;
28
+ cursor: wait;
29
+ }
30
+ .pill {
31
+ display: inline-block;
32
+ padding: 0.15rem 0.5rem;
33
+ border-radius: 999px;
34
+ background: #dfe8e2;
35
+ font-size: 0.75rem;
36
+ }
37
+ .pill.ok {
38
+ background: #c6e6cf;
39
+ }
40
+ .pill.bad {
41
+ background: #f0c9c9;
42
+ }
43
+ pre {
44
+ background: #142019;
45
+ color: #dceee6;
46
+ padding: 0.85rem;
47
+ font-size: 0.72rem;
48
+ overflow: auto;
49
+ }
50
+ </style>
51
+ </head>
52
+ <body>
53
+ <p>Bemony · security (interno)</p>
54
+ <h1>One-click · Downsell 1</h1>
55
+ <p>
56
+ Identidade <code>pri_downsell_1</code> vem do path da URL (sem
57
+ <code>data-price-code</code>).
58
+ </p>
59
+ <p>Status: <span id="pixel-status" class="pill">Init…</span></p>
60
+ <button type="button" id="confirm" disabled>Confirmar oferta</button>
61
+ <pre id="funnel-debug">aguardando…</pre>
62
+ <!-- <script src="../../sim/funnel-flow.js"></script> -->
63
+ <!-- <script>
64
+ (function () {
65
+ var STAGE = 1;
66
+ var sim = window.BemonyFunnelSim;
67
+ window.__ONE_CLICK_SIM__ = {
68
+ label: 'oc-downsell_1',
69
+ offerId: 'offer_downsell_1',
70
+ productId: 'product_1',
71
+ price: 29,
72
+ currency: 'USD',
73
+ productType: 'downsell',
74
+ funnelStepId: 'step_downsell_1',
75
+ nextHref: sim.nextAfterDownsell(1),
76
+ };
77
+ })();
78
+ </script> -->
79
+ <script
80
+ src="../../../dist/browser/pixel-bemony.global.js"
81
+ data-auto-init="false"
82
+ ></script>
83
+ <!-- <script src="../../sim/one-click-sim.js"></script> -->
84
+ </body>
85
+ </html>
@@ -0,0 +1,85 @@
1
+ <!doctype html>
2
+ <html lang="pt-BR">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Security · One-click Downsell · pri_downsell_1a</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <style>
8
+ body {
9
+ font-family: Georgia, 'Times New Roman', serif;
10
+ max-width: 28rem;
11
+ margin: 0 auto;
12
+ padding: 2rem 1rem;
13
+ background: linear-gradient(165deg, #e8eef0, #f4f1ea);
14
+ color: #17201b;
15
+ line-height: 1.5;
16
+ }
17
+ button {
18
+ width: 100%;
19
+ padding: 0.9rem;
20
+ background: #122019;
21
+ color: #fff;
22
+ border: 0;
23
+ border-radius: 4px;
24
+ cursor: pointer;
25
+ }
26
+ button:disabled {
27
+ opacity: 0.5;
28
+ cursor: wait;
29
+ }
30
+ .pill {
31
+ display: inline-block;
32
+ padding: 0.15rem 0.5rem;
33
+ border-radius: 999px;
34
+ background: #dfe8e2;
35
+ font-size: 0.75rem;
36
+ }
37
+ .pill.ok {
38
+ background: #c6e6cf;
39
+ }
40
+ .pill.bad {
41
+ background: #f0c9c9;
42
+ }
43
+ pre {
44
+ background: #142019;
45
+ color: #dceee6;
46
+ padding: 0.85rem;
47
+ font-size: 0.72rem;
48
+ overflow: auto;
49
+ }
50
+ </style>
51
+ </head>
52
+ <body>
53
+ <p>Bemony · security (interno)</p>
54
+ <h1>One-click · Downsell 1</h1>
55
+ <p>
56
+ Identidade <code>pri_downsell_1a</code> vem do path da URL (sem
57
+ <code>data-price-code</code>).
58
+ </p>
59
+ <p>Status: <span id="pixel-status" class="pill">Init…</span></p>
60
+ <button type="button" id="confirm" disabled>Confirmar oferta</button>
61
+ <pre id="funnel-debug">aguardando…</pre>
62
+ <script src="../../sim/funnel-flow.js"></script>
63
+ <script>
64
+ (function () {
65
+ var STAGE = 1;
66
+ var sim = window.BemonyFunnelSim;
67
+ window.__ONE_CLICK_SIM__ = {
68
+ label: 'oc-downsell_1a',
69
+ offerId: 'offer_downsell_1a',
70
+ productId: 'product_1',
71
+ price: 27,
72
+ currency: 'USD',
73
+ productType: 'downsell',
74
+ funnelStepId: 'step_downsell_1',
75
+ nextHref: sim.nextAfterDownsell(1),
76
+ };
77
+ })();
78
+ </script>
79
+ <script
80
+ src="../../../dist/browser/pixel-bemony.global.js"
81
+ data-auto-init="false"
82
+ ></script>
83
+ <script src="../../sim/one-click-sim.js"></script>
84
+ </body>
85
+ </html>
@@ -0,0 +1,78 @@
1
+ <!doctype html>
2
+ <html lang="pt-BR">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Security · One-click Downsell · pri_downsell_1b</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <style>
8
+ body {
9
+ font-family: Georgia, 'Times New Roman', serif;
10
+ max-width: 28rem;
11
+ margin: 0 auto;
12
+ padding: 2rem 1rem;
13
+ background: linear-gradient(165deg, #e8eef0, #f4f1ea);
14
+ color: #17201b;
15
+ line-height: 1.5;
16
+ }
17
+ button {
18
+ width: 100%;
19
+ padding: 0.9rem;
20
+ background: #122019;
21
+ color: #fff;
22
+ border: 0;
23
+ border-radius: 4px;
24
+ cursor: pointer;
25
+ }
26
+ button:disabled { opacity: 0.5; cursor: wait; }
27
+ .pill {
28
+ display: inline-block;
29
+ padding: 0.15rem 0.5rem;
30
+ border-radius: 999px;
31
+ background: #dfe8e2;
32
+ font-size: 0.75rem;
33
+ }
34
+ .pill.ok { background: #c6e6cf; }
35
+ .pill.bad { background: #f0c9c9; }
36
+ pre {
37
+ background: #142019;
38
+ color: #dceee6;
39
+ padding: 0.85rem;
40
+ font-size: 0.72rem;
41
+ overflow: auto;
42
+ }
43
+ </style>
44
+ </head>
45
+ <body>
46
+ <p>Bemony · security (interno)</p>
47
+ <h1>One-click · Downsell 1</h1>
48
+ <p>
49
+ Identidade <code>pri_downsell_1b</code> vem do path da URL (sem
50
+ <code>data-price-code</code>).
51
+ </p>
52
+ <p>Status: <span id="pixel-status" class="pill">Init…</span></p>
53
+ <button type="button" id="confirm" disabled>Confirmar oferta</button>
54
+ <pre id="funnel-debug">aguardando…</pre>
55
+ <script src="../../sim/funnel-flow.js"></script>
56
+ <script>
57
+ (function () {
58
+ var STAGE = 1;
59
+ var sim = window.BemonyFunnelSim;
60
+ window.__ONE_CLICK_SIM__ = {
61
+ label: 'oc-downsell_1b',
62
+ offerId: 'offer_downsell_1b',
63
+ productId: 'product_1',
64
+ price: 19,
65
+ currency: 'USD',
66
+ productType: 'downsell',
67
+ funnelStepId: 'step_downsell_1',
68
+ nextHref: sim.nextAfterDownsell(1),
69
+ };
70
+ })();
71
+ </script>
72
+ <script
73
+ src="../../../dist/browser/pixel-bemony.global.js"
74
+ data-auto-init="false"
75
+ ></script>
76
+ <script src="../../sim/one-click-sim.js"></script>
77
+ </body>
78
+ </html>