@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.
- package/CHANGELOG.md +157 -0
- package/README.md +176 -0
- package/RELEASE_CANDIDATE.md +37 -0
- package/dist/browser/index.cjs.js +2598 -0
- package/dist/browser/index.cjs.js.map +1 -0
- package/dist/browser/index.d.mts +184 -0
- package/dist/browser/index.d.ts +184 -0
- package/dist/browser/index.esm.js +2557 -0
- package/dist/browser/index.esm.js.map +1 -0
- package/dist/browser/pixel-bemony.global.js +9848 -0
- package/dist/browser/pixel-bemony.global.js.map +1 -0
- package/dist/createBemonyPixel-BGRD66p-.d.mts +474 -0
- package/dist/createBemonyPixel-BGRD66p-.d.ts +474 -0
- package/dist/index.cjs.js +2154 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.mts +320 -0
- package/dist/index.d.ts +320 -0
- package/dist/index.esm.js +2081 -0
- package/dist/index.esm.js.map +1 -0
- package/docs/BACKEND_PURCHASE_AND_REDIRECTS.md +125 -0
- package/docs/BROWSER_EVENT_ENRICHMENT.md +116 -0
- package/docs/SCENARIOS.md +92 -0
- package/docs/SECURITY_LIMITATIONS.md +45 -0
- package/docs/TEST_MATRIX.md +39 -0
- package/docs/TROUBLESHOOTING.md +81 -0
- package/examples/README.md +73 -0
- package/examples/browser-bootstrap.html +47 -0
- package/examples/checkout-price-code.html +37 -0
- package/examples/funnel/donsell/downsell_1.html +130 -0
- package/examples/funnel/donsell/downsell_2.html +130 -0
- package/examples/funnel/donsell/downsell_3.html +130 -0
- package/examples/funnel/offer-page.html +105 -0
- package/examples/funnel/upsell/upsell_1.html +130 -0
- package/examples/funnel/upsell/upsell_2.html +130 -0
- package/examples/funnel/upsell/upsell_3.html +139 -0
- package/examples/offer-page-price-code.html +22 -0
- package/examples/one-click-price-code.html +38 -0
- package/examples/security/checkout-sim.css +408 -0
- package/examples/security/checkout-sim.js +414 -0
- package/examples/security/one-click/pri_downsell_1.html +85 -0
- package/examples/security/one-click/pri_downsell_1a.html +85 -0
- package/examples/security/one-click/pri_downsell_1b.html +78 -0
- package/examples/security/one-click/pri_downsell_2.html +78 -0
- package/examples/security/one-click/pri_downsell_2a.html +78 -0
- package/examples/security/one-click/pri_downsell_2b.html +78 -0
- package/examples/security/one-click/pri_downsell_3.html +78 -0
- package/examples/security/one-click/pri_downsell_3a.html +78 -0
- package/examples/security/one-click/pri_downsell_3b.html +78 -0
- package/examples/security/one-click/pri_upsell_1.html +78 -0
- package/examples/security/one-click/pri_upsell_1a.html +78 -0
- package/examples/security/one-click/pri_upsell_1b.html +78 -0
- package/examples/security/one-click/pri_upsell_2.html +78 -0
- package/examples/security/one-click/pri_upsell_2a.html +78 -0
- package/examples/security/one-click/pri_upsell_2b.html +78 -0
- package/examples/security/one-click/pri_upsell_3.html +78 -0
- package/examples/security/one-click/pri_upsell_3a.html +78 -0
- package/examples/security/one-click/pri_upsell_3b.html +78 -0
- package/examples/security/one-click/pri_upsell_3c.html +78 -0
- package/examples/security/pri1766322.html +333 -0
- package/examples/security/pri5529930.html +333 -0
- package/examples/security/pri6670988.html +334 -0
- package/examples/security/thank-you.html +65 -0
- package/examples/sim/funnel-flow.js +258 -0
- package/examples/sim/one-click-sim.js +167 -0
- package/examples/upsell-price-code.html +41 -0
- package/examples/url-context-navigation.html +96 -0
- package/package.json +63 -0
|
@@ -0,0 +1,334 @@
|
|
|
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>Oferta pri6670988 — Checkout sim</title>
|
|
7
|
+
<link rel="stylesheet" href="checkout-sim.css" />
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div class="wrap">
|
|
11
|
+
<div class="main">
|
|
12
|
+
<header>
|
|
13
|
+
<h1 class="page-title">Checkout</h1>
|
|
14
|
+
<p class="page-sub">
|
|
15
|
+
Oferta pri6670988 (R$ 97) · lead → bump ADD/REMOVE · Complete
|
|
16
|
+
order → payment. Continuação do <code>sid</code>/<code>afid</code>
|
|
17
|
+
da VSL.
|
|
18
|
+
</p>
|
|
19
|
+
</header>
|
|
20
|
+
|
|
21
|
+
<form id="checkout-form">
|
|
22
|
+
<section class="card">
|
|
23
|
+
<h2>Customer Information</h2>
|
|
24
|
+
<div class="field">
|
|
25
|
+
<label for="email">Email</label>
|
|
26
|
+
<input
|
|
27
|
+
id="email"
|
|
28
|
+
name="email"
|
|
29
|
+
type="email"
|
|
30
|
+
autocomplete="email"
|
|
31
|
+
placeholder="user@example.com"
|
|
32
|
+
/>
|
|
33
|
+
</div>
|
|
34
|
+
<div class="field">
|
|
35
|
+
<label for="phone">Phone number</label>
|
|
36
|
+
<input
|
|
37
|
+
id="phone"
|
|
38
|
+
name="phone"
|
|
39
|
+
type="tel"
|
|
40
|
+
autocomplete="tel"
|
|
41
|
+
placeholder="(11) 99999-9999"
|
|
42
|
+
/>
|
|
43
|
+
<p class="hint">In case we need to call about the order.</p>
|
|
44
|
+
</div>
|
|
45
|
+
<label class="check">
|
|
46
|
+
<input type="checkbox" name="smsAlerts" checked />
|
|
47
|
+
<span>
|
|
48
|
+
<div class="check-label">
|
|
49
|
+
Get SMS alerts for order and shipping confirmations.
|
|
50
|
+
</div>
|
|
51
|
+
<div class="check-desc">
|
|
52
|
+
Consent is not required for purchase.
|
|
53
|
+
</div>
|
|
54
|
+
</span>
|
|
55
|
+
</label>
|
|
56
|
+
</section>
|
|
57
|
+
|
|
58
|
+
<section class="card">
|
|
59
|
+
<h2>Shipping Information</h2>
|
|
60
|
+
<div class="field">
|
|
61
|
+
<label for="address">Street Address</label>
|
|
62
|
+
<input
|
|
63
|
+
id="address"
|
|
64
|
+
name="address"
|
|
65
|
+
type="text"
|
|
66
|
+
autocomplete="street-address"
|
|
67
|
+
placeholder="Rua Exemplo, 123"
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
<button type="button" class="linkish" id="addr2-toggle">
|
|
71
|
+
+ Add additional address line
|
|
72
|
+
</button>
|
|
73
|
+
<div class="field" id="addr2-field" hidden>
|
|
74
|
+
<label for="address2">Address line 2</label>
|
|
75
|
+
<input
|
|
76
|
+
id="address2"
|
|
77
|
+
name="address2"
|
|
78
|
+
type="text"
|
|
79
|
+
placeholder="Apto, bloco, etc."
|
|
80
|
+
/>
|
|
81
|
+
</div>
|
|
82
|
+
<div class="row-3">
|
|
83
|
+
<div class="field">
|
|
84
|
+
<label for="state">State / Region</label>
|
|
85
|
+
<select id="state" name="state">
|
|
86
|
+
<option value="">Select…</option>
|
|
87
|
+
<option value="SP">São Paulo</option>
|
|
88
|
+
<option value="RJ">Rio de Janeiro</option>
|
|
89
|
+
<option value="MG">Minas Gerais</option>
|
|
90
|
+
<option value="PR">Paraná</option>
|
|
91
|
+
</select>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="field">
|
|
94
|
+
<label for="city">City</label>
|
|
95
|
+
<input
|
|
96
|
+
id="city"
|
|
97
|
+
name="city"
|
|
98
|
+
type="text"
|
|
99
|
+
placeholder="São Paulo"
|
|
100
|
+
/>
|
|
101
|
+
</div>
|
|
102
|
+
<div class="field">
|
|
103
|
+
<label for="postal">Postal Code</label>
|
|
104
|
+
<input
|
|
105
|
+
id="postal"
|
|
106
|
+
name="postal"
|
|
107
|
+
type="text"
|
|
108
|
+
autocomplete="postal-code"
|
|
109
|
+
placeholder="01310-100"
|
|
110
|
+
/>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
<label class="check">
|
|
114
|
+
<input type="checkbox" name="billingSame" checked />
|
|
115
|
+
<span>
|
|
116
|
+
<div class="check-label">Billing same as Shipping</div>
|
|
117
|
+
<div class="check-desc">
|
|
118
|
+
Uncheck to enter a different billing address.
|
|
119
|
+
</div>
|
|
120
|
+
</span>
|
|
121
|
+
</label>
|
|
122
|
+
</section>
|
|
123
|
+
|
|
124
|
+
<section class="card">
|
|
125
|
+
<h2>Payment Information</h2>
|
|
126
|
+
<p class="card-desc">All transactions are secure and encrypted.</p>
|
|
127
|
+
<p class="secure">We only accept Visa and MasterCard.</p>
|
|
128
|
+
<div class="pay-tabs" role="tablist" aria-label="Payment methods">
|
|
129
|
+
<button
|
|
130
|
+
type="button"
|
|
131
|
+
class="pay-tab"
|
|
132
|
+
data-method="CREDIT_CARD"
|
|
133
|
+
aria-selected="true"
|
|
134
|
+
>
|
|
135
|
+
Credit Card
|
|
136
|
+
</button>
|
|
137
|
+
<button
|
|
138
|
+
type="button"
|
|
139
|
+
class="pay-tab"
|
|
140
|
+
data-method="PAYPAL"
|
|
141
|
+
aria-selected="false"
|
|
142
|
+
>
|
|
143
|
+
PayPal
|
|
144
|
+
</button>
|
|
145
|
+
<button type="button" class="pay-tab" disabled>Apple Pay</button>
|
|
146
|
+
<button type="button" class="pay-tab" disabled>Google Pay</button>
|
|
147
|
+
</div>
|
|
148
|
+
<div id="card-fields">
|
|
149
|
+
<div class="field">
|
|
150
|
+
<label for="cardNumber">Card Number</label>
|
|
151
|
+
<input
|
|
152
|
+
id="cardNumber"
|
|
153
|
+
name="cardNumber"
|
|
154
|
+
type="text"
|
|
155
|
+
inputmode="numeric"
|
|
156
|
+
autocomplete="cc-number"
|
|
157
|
+
placeholder="1234 5678 9012 3456"
|
|
158
|
+
/>
|
|
159
|
+
<p class="hint">Só UI — o Pixel nunca envia PAN/CVV.</p>
|
|
160
|
+
</div>
|
|
161
|
+
<div class="row-2">
|
|
162
|
+
<div class="field">
|
|
163
|
+
<label for="expiration">Expiration Date</label>
|
|
164
|
+
<input
|
|
165
|
+
id="expiration"
|
|
166
|
+
name="expiration"
|
|
167
|
+
type="text"
|
|
168
|
+
autocomplete="cc-exp"
|
|
169
|
+
placeholder="MM / YY"
|
|
170
|
+
/>
|
|
171
|
+
</div>
|
|
172
|
+
<div class="field">
|
|
173
|
+
<label for="cvc">Security Code</label>
|
|
174
|
+
<input
|
|
175
|
+
id="cvc"
|
|
176
|
+
name="cvc"
|
|
177
|
+
type="text"
|
|
178
|
+
autocomplete="cc-csc"
|
|
179
|
+
placeholder="123"
|
|
180
|
+
/>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</section>
|
|
185
|
+
|
|
186
|
+
<button class="btn-primary" type="submit">Complete order</button>
|
|
187
|
+
</form>
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
<aside class="aside">
|
|
191
|
+
<section class="card">
|
|
192
|
+
<h2>Order Summary</h2>
|
|
193
|
+
<p class="card-desc">
|
|
194
|
+
Estado do cart (commerce.cart.initialItems + bumps).
|
|
195
|
+
</p>
|
|
196
|
+
<div class="meta-row">
|
|
197
|
+
<span class="muted">Pixel</span>
|
|
198
|
+
<span id="pixel-status" class="pill">Init…</span>
|
|
199
|
+
</div>
|
|
200
|
+
<p id="cart-empty" class="empty-cart" hidden>Carrinho vazio.</p>
|
|
201
|
+
<ul id="cart-lines" class="lines"></ul>
|
|
202
|
+
<div class="total-row">
|
|
203
|
+
<strong>Total do pedido</strong>
|
|
204
|
+
<span id="cart-total" class="amount">—</span>
|
|
205
|
+
</div>
|
|
206
|
+
</section>
|
|
207
|
+
|
|
208
|
+
<section class="card">
|
|
209
|
+
<div class="bump-head">
|
|
210
|
+
<span class="pill bump">Order bump</span>
|
|
211
|
+
<h2>Entrega expressa</h2>
|
|
212
|
+
</div>
|
|
213
|
+
<p class="card-desc">
|
|
214
|
+
Marque para adicionar ao cart — dispara ADD_TO_CART via
|
|
215
|
+
<code>data-track</code>. Desmarcar dispara REMOVE_FROM_CART.
|
|
216
|
+
</p>
|
|
217
|
+
<label class="check" for="bump-check">
|
|
218
|
+
<input id="bump-check" type="checkbox" />
|
|
219
|
+
<span>
|
|
220
|
+
<div class="check-label">Order Bump Especial</div>
|
|
221
|
+
<div class="check-desc">
|
|
222
|
+
+R$ 47,00 · <code>order_bump_01</code>
|
|
223
|
+
</div>
|
|
224
|
+
</span>
|
|
225
|
+
</label>
|
|
226
|
+
<!-- Triggers — detectors auto (não usar attribute hidden) -->
|
|
227
|
+
<button
|
|
228
|
+
id="bump-add"
|
|
229
|
+
class="sr-trigger"
|
|
230
|
+
type="button"
|
|
231
|
+
data-track="add_to_cart"
|
|
232
|
+
data-product-id="order_bump_01"
|
|
233
|
+
data-product-name="Order Bump Especial"
|
|
234
|
+
data-price="47"
|
|
235
|
+
data-currency="BRL"
|
|
236
|
+
data-quantity="1"
|
|
237
|
+
tabindex="-1"
|
|
238
|
+
aria-hidden="true"
|
|
239
|
+
>
|
|
240
|
+
add bump
|
|
241
|
+
</button>
|
|
242
|
+
<button
|
|
243
|
+
id="bump-remove"
|
|
244
|
+
class="sr-trigger"
|
|
245
|
+
type="button"
|
|
246
|
+
data-track="remove_from_cart"
|
|
247
|
+
data-product-id="order_bump_01"
|
|
248
|
+
tabindex="-1"
|
|
249
|
+
aria-hidden="true"
|
|
250
|
+
>
|
|
251
|
+
remove bump
|
|
252
|
+
</button>
|
|
253
|
+
</section>
|
|
254
|
+
|
|
255
|
+
<section class="card debug">
|
|
256
|
+
<h2>Debug · eventos</h2>
|
|
257
|
+
<div class="kv">
|
|
258
|
+
<span class="muted">Transport sent</span>
|
|
259
|
+
<span id="dbg-transport" class="mono">—</span>
|
|
260
|
+
</div>
|
|
261
|
+
<div class="kv">
|
|
262
|
+
<span class="muted">sid</span>
|
|
263
|
+
<span id="dbg-sid" class="mono">—</span>
|
|
264
|
+
</div>
|
|
265
|
+
<div class="kv">
|
|
266
|
+
<span class="muted">afid</span>
|
|
267
|
+
<span id="dbg-afid" class="mono">—</span>
|
|
268
|
+
</div>
|
|
269
|
+
<p class="label">Cart runtime</p>
|
|
270
|
+
<p id="dbg-cart" class="mono">—</p>
|
|
271
|
+
<p class="label">Detectors ativos</p>
|
|
272
|
+
<p id="dbg-detectors" class="mono">—</p>
|
|
273
|
+
<p class="label">Dedupe key count</p>
|
|
274
|
+
<p id="dbg-dedupe" class="mono">—</p>
|
|
275
|
+
</section>
|
|
276
|
+
</aside>
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
<script src="../sim/funnel-flow.js"></script>
|
|
280
|
+
<script>
|
|
281
|
+
window.__CHECKOUT_SIM__ = {
|
|
282
|
+
currency: 'BRL',
|
|
283
|
+
nextHref: '../funnel/upsell/upsell_1.html',
|
|
284
|
+
main: {
|
|
285
|
+
id: 'pri6670988',
|
|
286
|
+
offerId: 'pri6670988',
|
|
287
|
+
name: 'Oferta Principal',
|
|
288
|
+
price: 97,
|
|
289
|
+
},
|
|
290
|
+
bump: {
|
|
291
|
+
id: 'order_bump_01',
|
|
292
|
+
offerId: 'offer_bump',
|
|
293
|
+
name: 'Order Bump Especial',
|
|
294
|
+
price: 47,
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
window.BemonyPixelConfig = {
|
|
299
|
+
scenario: 'checkout',
|
|
300
|
+
page: {
|
|
301
|
+
public: {
|
|
302
|
+
offerId: 'pri6670988',
|
|
303
|
+
productId: 'pri6670988',
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
commerce: {
|
|
307
|
+
currency: 'BRL',
|
|
308
|
+
products: [
|
|
309
|
+
{
|
|
310
|
+
id: 'pri6670988',
|
|
311
|
+
name: 'Oferta Principal',
|
|
312
|
+
type: 'main',
|
|
313
|
+
price: 97,
|
|
314
|
+
currency: 'BRL',
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
id: 'order_bump_01',
|
|
318
|
+
name: 'Order Bump Especial',
|
|
319
|
+
type: 'order_bump',
|
|
320
|
+
price: 47,
|
|
321
|
+
currency: 'BRL',
|
|
322
|
+
},
|
|
323
|
+
],
|
|
324
|
+
},
|
|
325
|
+
};
|
|
326
|
+
</script>
|
|
327
|
+
<script
|
|
328
|
+
src="../../dist/browser/pixel-bemony.global.js"
|
|
329
|
+
data-scenario="checkout"
|
|
330
|
+
data-debug="true"
|
|
331
|
+
></script>
|
|
332
|
+
<script src="checkout-sim.js"></script>
|
|
333
|
+
</body>
|
|
334
|
+
</html>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-BR">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>Security · Thank you</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: 32rem;
|
|
11
|
+
margin: 0 auto;
|
|
12
|
+
padding: 2rem 1rem;
|
|
13
|
+
background: linear-gradient(165deg, #eef6f2, #f7f3ea);
|
|
14
|
+
color: #17201b;
|
|
15
|
+
line-height: 1.5;
|
|
16
|
+
}
|
|
17
|
+
pre {
|
|
18
|
+
background: #142019;
|
|
19
|
+
color: #dceee6;
|
|
20
|
+
padding: 0.85rem;
|
|
21
|
+
font-size: 0.72rem;
|
|
22
|
+
overflow: auto;
|
|
23
|
+
}
|
|
24
|
+
</style>
|
|
25
|
+
</head>
|
|
26
|
+
<body>
|
|
27
|
+
<p>Bemony · security</p>
|
|
28
|
+
<h1>Obrigado!</h1>
|
|
29
|
+
<p>
|
|
30
|
+
Scenario <code>thank-you</code>. Sem purchase browser; sem catálogo.
|
|
31
|
+
Purchase continua server-side — esta página não inventa Order a partir
|
|
32
|
+
dos prices do funil.
|
|
33
|
+
</p>
|
|
34
|
+
<p id="order"></p>
|
|
35
|
+
<pre id="funnel-debug">aguardando…</pre>
|
|
36
|
+
|
|
37
|
+
<script src="../sim/funnel-flow.js"></script>
|
|
38
|
+
<script
|
|
39
|
+
src="../../dist/browser/pixel-bemony.global.js"
|
|
40
|
+
data-environment="development"
|
|
41
|
+
data-scenario="thank-you"
|
|
42
|
+
data-funnel-id="funnel_1"
|
|
43
|
+
data-funnel-step-id="step_thank_you"
|
|
44
|
+
data-allowed-domains="localhost,127.0.0.1,security.bemony.com"
|
|
45
|
+
></script>
|
|
46
|
+
<script>
|
|
47
|
+
(function () {
|
|
48
|
+
var sim = window.BemonyFunnelSim;
|
|
49
|
+
var oid = sim.readOid();
|
|
50
|
+
if (oid) {
|
|
51
|
+
document.getElementById('order').textContent = 'Order pública: ' + oid;
|
|
52
|
+
}
|
|
53
|
+
sim.whenReady().then(function (pixel) {
|
|
54
|
+
sim.logPixel('thank-you', pixel);
|
|
55
|
+
sim.wireDebugPanel(pixel);
|
|
56
|
+
var fromPixel = pixel.getPublicOrderId && pixel.getPublicOrderId();
|
|
57
|
+
if (fromPixel) {
|
|
58
|
+
document.getElementById('order').textContent =
|
|
59
|
+
'Order pública: ' + fromPixel;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
})();
|
|
63
|
+
</script>
|
|
64
|
+
</body>
|
|
65
|
+
</html>
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper compartilhado dos examples do funil Bemony (simulação local).
|
|
3
|
+
*
|
|
4
|
+
* Funciona em:
|
|
5
|
+
* - HTTP: `pnpm dlx serve packages/pixel-bemony` → /examples/...
|
|
6
|
+
* - file://: abrir HTML direto no disco (paths absolutos `/examples/...` quebram)
|
|
7
|
+
*
|
|
8
|
+
* Preserva params públicos (sid, afid, oid, utm_*, fbclid, …) entre páginas.
|
|
9
|
+
*/
|
|
10
|
+
(function (global) {
|
|
11
|
+
var MANAGED = {
|
|
12
|
+
sid: true,
|
|
13
|
+
afid: true,
|
|
14
|
+
oid: true,
|
|
15
|
+
fid: true,
|
|
16
|
+
fsid: true,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
var ATTRIBUTION = {
|
|
20
|
+
utm_source: true,
|
|
21
|
+
utm_medium: true,
|
|
22
|
+
utm_campaign: true,
|
|
23
|
+
utm_content: true,
|
|
24
|
+
utm_term: true,
|
|
25
|
+
fbclid: true,
|
|
26
|
+
gclid: true,
|
|
27
|
+
ttclid: true,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Prefixo até `/examples` na URL atual.
|
|
32
|
+
* file:///C:/Users/.../pixel-bemony/examples/funnel/upsell/upsell_1.html
|
|
33
|
+
* → .../pixel-bemony/examples
|
|
34
|
+
* http://localhost:3000/examples/funnel/...
|
|
35
|
+
* → /examples
|
|
36
|
+
*/
|
|
37
|
+
function examplesRootUrl() {
|
|
38
|
+
var url = new URL(global.location.href);
|
|
39
|
+
var path = url.pathname.replace(/\\/g, '/');
|
|
40
|
+
var marker = '/examples';
|
|
41
|
+
var idx = path.lastIndexOf(marker);
|
|
42
|
+
if (idx === -1) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
'[BemonyFunnelSim] URL atual não contém /examples/: ' + url.href
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
url.pathname = path.slice(0, idx + marker.length);
|
|
48
|
+
url.search = '';
|
|
49
|
+
url.hash = '';
|
|
50
|
+
// garantir barra final para new URL(rel, base) resolver como diretório
|
|
51
|
+
if (!url.pathname.endsWith('/')) {
|
|
52
|
+
url.pathname += '/';
|
|
53
|
+
}
|
|
54
|
+
return url;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Converte path lógico sob examples/ em href absoluto correto (file:// ou http).
|
|
59
|
+
* Aceita: "funnel/upsell/upsell_1.html" ou "/examples/funnel/..."
|
|
60
|
+
*/
|
|
61
|
+
function resolveExamplesHref(logicalPath) {
|
|
62
|
+
var clean = String(logicalPath || '').replace(/\\/g, '/');
|
|
63
|
+
clean = clean.replace(/^\/+/, '');
|
|
64
|
+
if (clean.indexOf('examples/') === 0) {
|
|
65
|
+
clean = clean.slice('examples/'.length);
|
|
66
|
+
}
|
|
67
|
+
return new URL(clean, examplesRootUrl()).href;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function currentParams() {
|
|
71
|
+
return new URLSearchParams(global.location.search);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function mergeParams(extra) {
|
|
75
|
+
var out = currentParams();
|
|
76
|
+
if (extra) {
|
|
77
|
+
Object.keys(extra).forEach(function (key) {
|
|
78
|
+
var value = extra[key];
|
|
79
|
+
if (value === null || value === undefined || value === '') {
|
|
80
|
+
out.delete(key);
|
|
81
|
+
} else {
|
|
82
|
+
out.set(key, String(value));
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function withParams(href, extra) {
|
|
90
|
+
var absolute;
|
|
91
|
+
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(href)) {
|
|
92
|
+
// http:, https:, file:, etc.
|
|
93
|
+
absolute = href;
|
|
94
|
+
} else if (href.charAt(0) === '.') {
|
|
95
|
+
// relativo ao documento atual (../funnel/...)
|
|
96
|
+
absolute = new URL(href, global.location.href).href;
|
|
97
|
+
} else {
|
|
98
|
+
// path lógico sob examples/ (funnel/upsell/...)
|
|
99
|
+
absolute = resolveExamplesHref(href);
|
|
100
|
+
}
|
|
101
|
+
var url = new URL(absolute, global.location.href);
|
|
102
|
+
var merged = mergeParams(extra);
|
|
103
|
+
merged.forEach(function (value, key) {
|
|
104
|
+
if (MANAGED[key] || ATTRIBUTION[key] || key.indexOf('utm_') === 0) {
|
|
105
|
+
url.searchParams.set(key, value);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
return url.href;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function navigate(href, extra) {
|
|
112
|
+
global.location.assign(withParams(href, extra));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function ensureOid() {
|
|
116
|
+
var params = currentParams();
|
|
117
|
+
var oid = params.get('oid');
|
|
118
|
+
if (oid && oid.trim()) return oid.trim();
|
|
119
|
+
oid = 'ord_' + Math.random().toString(36).slice(2, 10);
|
|
120
|
+
var url = new URL(global.location.href);
|
|
121
|
+
url.searchParams.set('oid', oid);
|
|
122
|
+
global.history.replaceState({}, '', url.href);
|
|
123
|
+
return oid;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function readOid() {
|
|
127
|
+
return currentParams().get('oid');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function getApi() {
|
|
131
|
+
var bp = global.BemonyPixel;
|
|
132
|
+
if (!bp) return null;
|
|
133
|
+
if (typeof bp.whenReady === 'function') return bp;
|
|
134
|
+
if (
|
|
135
|
+
bp.bemonyPixelGlobalApi &&
|
|
136
|
+
typeof bp.bemonyPixelGlobalApi.whenReady === 'function'
|
|
137
|
+
) {
|
|
138
|
+
return bp.bemonyPixelGlobalApi;
|
|
139
|
+
}
|
|
140
|
+
return bp;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function whenReady() {
|
|
144
|
+
var api = getApi();
|
|
145
|
+
if (api && typeof api.whenReady === 'function') {
|
|
146
|
+
return api.whenReady();
|
|
147
|
+
}
|
|
148
|
+
return new Promise(function (resolve, reject) {
|
|
149
|
+
var n = 0;
|
|
150
|
+
function tick() {
|
|
151
|
+
var again = getApi();
|
|
152
|
+
if (again && typeof again.whenReady === 'function') {
|
|
153
|
+
again.whenReady().then(resolve, reject);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (n++ > 80) {
|
|
157
|
+
reject(new Error('BemonyPixel.whenReady indisponível'));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
global.setTimeout(tick, 50);
|
|
161
|
+
}
|
|
162
|
+
tick();
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function logPixel(label, pixel) {
|
|
167
|
+
console.log('[' + label + ']', {
|
|
168
|
+
scenario: pixel.getScenario && pixel.getScenario(),
|
|
169
|
+
state: pixel.getState && pixel.getState(),
|
|
170
|
+
sid: pixel.getPublicSessionId && pixel.getPublicSessionId(),
|
|
171
|
+
oid: readOid(),
|
|
172
|
+
url: global.location.href,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function wireDebugPanel(pixel, rootId) {
|
|
177
|
+
var root = global.document.getElementById(rootId || 'funnel-debug');
|
|
178
|
+
if (!root) return;
|
|
179
|
+
root.textContent = JSON.stringify(
|
|
180
|
+
{
|
|
181
|
+
scenario: pixel.getScenario && pixel.getScenario(),
|
|
182
|
+
sid: pixel.getPublicSessionId && pixel.getPublicSessionId(),
|
|
183
|
+
oid: readOid(),
|
|
184
|
+
},
|
|
185
|
+
null,
|
|
186
|
+
2
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Paths lógicos relativos a examples/ (NÃO começam com /).
|
|
192
|
+
* resolveExamplesHref() monta a URL correta em file:// e http://.
|
|
193
|
+
*
|
|
194
|
+
* Pasta tipada historicamente como "donsell" (typo mantido no FS).
|
|
195
|
+
*/
|
|
196
|
+
var FLOW = {
|
|
197
|
+
lastStage: 3,
|
|
198
|
+
offer: 'funnel/offer-page.html',
|
|
199
|
+
checkoutByPrice: {
|
|
200
|
+
pri6670988: 'security/pri6670988.html',
|
|
201
|
+
pri5529930: 'security/pri5529930.html',
|
|
202
|
+
pri1766322: 'security/pri1766322.html',
|
|
203
|
+
},
|
|
204
|
+
afterCheckout: 'funnel/upsell/upsell_1.html',
|
|
205
|
+
upsellOffer: {
|
|
206
|
+
1: 'funnel/upsell/upsell_1.html',
|
|
207
|
+
2: 'funnel/upsell/upsell_2.html',
|
|
208
|
+
3: 'funnel/upsell/upsell_3.html',
|
|
209
|
+
},
|
|
210
|
+
upsellOneClick: {
|
|
211
|
+
1: 'security/one-click/pri_upsell_1.html',
|
|
212
|
+
2: 'security/one-click/pri_upsell_2.html',
|
|
213
|
+
3: 'security/one-click/pri_upsell_3.html',
|
|
214
|
+
},
|
|
215
|
+
downsellOffer: {
|
|
216
|
+
1: 'funnel/donsell/downsell_1.html',
|
|
217
|
+
2: 'funnel/donsell/downsell_2.html',
|
|
218
|
+
3: 'funnel/donsell/downsell_3.html',
|
|
219
|
+
},
|
|
220
|
+
downsellOneClick: {
|
|
221
|
+
1: 'security/one-click/pri_downsell_1.html',
|
|
222
|
+
2: 'security/one-click/pri_downsell_2.html',
|
|
223
|
+
3: 'security/one-click/pri_downsell_3.html',
|
|
224
|
+
},
|
|
225
|
+
thankYou: 'security/thank-you.html',
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
function nextAfterUpsellAccept(stage) {
|
|
229
|
+
if (stage >= FLOW.lastStage) return FLOW.thankYou;
|
|
230
|
+
return FLOW.upsellOffer[stage + 1];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function nextAfterUpsellDecline(stage) {
|
|
234
|
+
return FLOW.downsellOffer[stage] || FLOW.thankYou;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function nextAfterDownsell(stage) {
|
|
238
|
+
if (stage >= FLOW.lastStage) return FLOW.thankYou;
|
|
239
|
+
return FLOW.upsellOffer[stage + 1];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
global.BemonyFunnelSim = {
|
|
243
|
+
withParams: withParams,
|
|
244
|
+
navigate: navigate,
|
|
245
|
+
ensureOid: ensureOid,
|
|
246
|
+
readOid: readOid,
|
|
247
|
+
whenReady: whenReady,
|
|
248
|
+
logPixel: logPixel,
|
|
249
|
+
wireDebugPanel: wireDebugPanel,
|
|
250
|
+
resolveExamplesHref: resolveExamplesHref,
|
|
251
|
+
FLOW: FLOW,
|
|
252
|
+
nextAfterUpsellAccept: nextAfterUpsellAccept,
|
|
253
|
+
nextAfterUpsellDecline: nextAfterUpsellDecline,
|
|
254
|
+
nextAfterDownsell: nextAfterDownsell,
|
|
255
|
+
/** Token demo — só memória local; nunca usar em produção. */
|
|
256
|
+
DEMO_ONE_CLICK_TOKEN: 'demo_oc_token_LOCAL_SIM_ONLY',
|
|
257
|
+
};
|
|
258
|
+
})(typeof window !== 'undefined' ? window : globalThis);
|