@beworke/pixel 0.1.0-rc.5 → 0.1.0-rc.7

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 (150) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +38 -69
  3. package/RELEASE_CANDIDATE.md +19 -13
  4. package/dist/{StorageFactory-CPghDPBj.d.mts → StorageFactory-Cq29vF32.d.mts} +2 -2
  5. package/dist/{StorageFactory-tjfzk57c.d.ts → StorageFactory-DeMaZ8wk.d.ts} +2 -2
  6. package/dist/config/index.cjs.js +1 -1
  7. package/dist/config/index.cjs.js.map +1 -1
  8. package/dist/config/index.d.mts +4 -4
  9. package/dist/config/index.d.ts +4 -4
  10. package/dist/config/index.esm.js +1 -1
  11. package/dist/config/index.esm.js.map +1 -1
  12. package/dist/events/index.cjs.js.map +1 -1
  13. package/dist/events/index.d.mts +2 -2
  14. package/dist/events/index.d.ts +2 -2
  15. package/dist/events/index.esm.js.map +1 -1
  16. package/dist/examples/html-script/README.md +20 -76
  17. package/dist/examples/html-script/RELEASE_CANDIDATE.md +14 -13
  18. package/dist/examples/html-script/add-payment-info/example-add-payment-info-card-autocomplete.html +1 -1
  19. package/dist/examples/html-script/add-payment-info/example-add-payment-info-card-disabled.html +1 -1
  20. package/dist/examples/html-script/add-payment-info/example-add-payment-info-card-fields.html +1 -1
  21. package/dist/examples/html-script/add-payment-info/example-add-payment-info-data-track.html +1 -1
  22. package/dist/examples/html-script/add-payment-info/example-add-payment-info-dedupe.html +1 -1
  23. package/dist/examples/html-script/add-payment-info/example-add-payment-info-manual.html +1 -1
  24. package/dist/examples/html-script/add-payment-info/example-add-payment-info-rules-card.html +1 -1
  25. package/dist/examples/html-script/add-payment-info/example-add-payment-info-security.html +1 -1
  26. package/dist/examples/html-script/add-to-cart/README.md +6 -3
  27. package/dist/examples/html-script/add-to-cart/example-add-to-cart-attribute.html +3 -2
  28. package/dist/examples/html-script/add-to-cart/example-add-to-cart-auto.html +3 -2
  29. package/dist/examples/html-script/add-to-cart/example-add-to-cart-click.html +3 -2
  30. package/dist/examples/html-script/add-to-cart/example-add-to-cart-dedupe.html +3 -2
  31. package/dist/examples/html-script/add-to-cart/example-add-to-cart-link.html +597 -0
  32. package/dist/examples/html-script/add-to-cart/example-add-to-cart-manual.html +3 -2
  33. package/dist/examples/html-script/add-to-cart/example-add-to-cart-order-bump.html +3 -2
  34. package/dist/examples/html-script/add-to-cart/example-add-to-cart-text.html +3 -2
  35. package/dist/examples/html-script/behavior/example-behavior-engagement.html +1 -1
  36. package/dist/examples/html-script/behavior/example-behavior-heartbeat.html +1 -1
  37. package/dist/examples/html-script/behavior/example-behavior-runtime-intelligence.html +1 -1
  38. package/dist/examples/html-script/behavior/example-behavior-viewport.html +1 -1
  39. package/dist/examples/html-script/behavior/example-behavior.html +1 -1
  40. package/dist/examples/html-script/example-basic.html +1 -1
  41. package/dist/examples/html-script/example-checkout-commerce.html +1 -1
  42. package/dist/examples/html-script/example-conversion.html +1 -1
  43. package/dist/examples/html-script/example-integration.html +1 -1
  44. package/dist/examples/html-script/example-landing-commerce.html +42 -1
  45. package/dist/examples/html-script/example-runtime-diagnostics.html +1 -1
  46. package/dist/examples/html-script/example-transport.html +6 -1
  47. package/dist/examples/html-script/full-funnel/README.md +1 -1
  48. package/dist/examples/html-script/full-funnel/checkout.html +1 -1
  49. package/dist/examples/html-script/full-funnel/downsell.html +1 -1
  50. package/dist/examples/html-script/full-funnel/landing.html +54 -2
  51. package/dist/examples/html-script/full-funnel/thank-you.html +1 -1
  52. package/dist/examples/html-script/full-funnel/upsell.html +1 -1
  53. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-attribute.html +1 -1
  54. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-auto.html +1 -1
  55. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-click.html +1 -1
  56. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-manual.html +1 -1
  57. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-snapshot.html +1 -1
  58. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-submit.html +1 -1
  59. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-text.html +1 -1
  60. package/dist/examples/html-script/lead/example-lead-trigger-attribute.html +1 -1
  61. package/dist/examples/html-script/lead/example-lead-trigger-auto.html +1 -1
  62. package/dist/examples/html-script/lead/example-lead-trigger-click.html +1 -1
  63. package/dist/examples/html-script/release-candidate.html +1 -1
  64. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-attribute.html +1 -1
  65. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-css.html +1 -1
  66. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-dedupe.html +1 -1
  67. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-manual.html +1 -1
  68. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-multi.html +1 -1
  69. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-state.html +1 -1
  70. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-text.html +1 -1
  71. package/dist/examples/html-script/search/example-search-attribute.html +1 -1
  72. package/dist/examples/html-script/search/example-search-button-sync.html +1 -1
  73. package/dist/examples/html-script/search/example-search-dedupe.html +1 -1
  74. package/dist/examples/html-script/search/example-search-input.html +1 -1
  75. package/dist/examples/html-script/search/example-search-manual.html +1 -1
  76. package/dist/examples/html-script/search/example-search-submit.html +1 -1
  77. package/dist/examples/html-script/search/example-search-text.html +1 -1
  78. package/dist/examples/html-script/url-context/example-url-context-allowed-domains.html +38 -9
  79. package/dist/examples/html-script/url-context/example-url-context-landing.html +53 -13
  80. package/dist/examples/html-script/url-context/example-url-context-upsell.html +48 -10
  81. package/dist/examples/html-script/url-context/example-url-context.html +51 -17
  82. package/dist/examples/html-script/view-content/example-view-content-attribute.html +1 -1
  83. package/dist/examples/html-script/view-content/example-view-content-css.html +1 -1
  84. package/dist/examples/html-script/view-content/example-view-content-dedupe.html +1 -1
  85. package/dist/examples/html-script/view-content/example-view-content-empty.html +1 -1
  86. package/dist/examples/html-script/view-content/example-view-content-manual.html +1 -1
  87. package/dist/examples/html-script/view-content/example-view-content-product-card.html +1 -1
  88. package/dist/examples/html-script/view-content/example-view-content-text.html +1 -1
  89. package/dist/examples/release-candidate/README.md +2 -1
  90. package/dist/examples/v2/README.md +15 -15
  91. package/dist/{index-CQAyT5Od.d.ts → index-B8u_3PGG.d.ts} +21 -2
  92. package/dist/{index-JlKPz4pp.d.mts → index-BxT2d-TK.d.mts} +21 -2
  93. package/dist/index.cjs.js +1 -1
  94. package/dist/index.cjs.js.map +1 -1
  95. package/dist/index.d.mts +19 -782
  96. package/dist/index.d.ts +19 -782
  97. package/dist/index.esm.js +1 -1
  98. package/dist/index.esm.js.map +1 -1
  99. package/dist/{pixel-BxZZx8l5.d.ts → pixel-2uL4LSyC.d.ts} +126 -5
  100. package/dist/{pixel-CKc4OQUx.d.mts → pixel-DMwpppf_.d.mts} +126 -5
  101. package/dist/{pixel-default-config-aAOujzwp.d.ts → pixel-default-config-BDPUVHse.d.ts} +1 -1
  102. package/dist/{pixel-default-config-CJl-eypl.d.mts → pixel-default-config-C5uLt52W.d.mts} +1 -1
  103. package/dist/runtime/index.cjs.js +1 -1
  104. package/dist/runtime/index.cjs.js.map +1 -1
  105. package/dist/runtime/index.d.mts +6 -6
  106. package/dist/runtime/index.d.ts +6 -6
  107. package/dist/runtime/index.esm.js +1 -1
  108. package/dist/runtime/index.esm.js.map +1 -1
  109. package/dist/services/index.cjs.js +1 -1
  110. package/dist/services/index.cjs.js.map +1 -1
  111. package/dist/services/index.d.mts +7 -7
  112. package/dist/services/index.d.ts +7 -7
  113. package/dist/services/index.esm.js +1 -1
  114. package/dist/services/index.esm.js.map +1 -1
  115. package/dist/{types-BP8dz1gP.d.mts → types-6HF3UlsL.d.mts} +2 -2
  116. package/dist/{types-C75pQP31.d.ts → types-BqUEoZo0.d.ts} +2 -2
  117. package/dist/{types-DMhzHSVC.d.mts → types-CgrabttM.d.mts} +2 -2
  118. package/dist/{types-D_SsCur9.d.ts → types-fFcQ1apy.d.ts} +2 -2
  119. package/dist/{url-context-BjAsQoVl.d.mts → url-context-Ck2LK18V.d.mts} +4 -2
  120. package/dist/{url-context-BjAsQoVl.d.ts → url-context-Ck2LK18V.d.ts} +4 -2
  121. package/dist/v2/global.global.js +1 -1
  122. package/dist/v2/global.global.js.map +1 -1
  123. package/dist/v2/index.cjs.js +1 -1
  124. package/dist/v2/index.cjs.js.map +1 -1
  125. package/dist/v2/index.d.mts +793 -9
  126. package/dist/v2/index.d.ts +793 -9
  127. package/dist/v2/index.esm.js +1 -1
  128. package/dist/v2/index.esm.js.map +1 -1
  129. package/docs/public/README.md +77 -0
  130. package/docs/public/api/exports.md +47 -0
  131. package/docs/public/api/pixel.md +65 -0
  132. package/docs/public/configuration/commerce.md +44 -0
  133. package/docs/public/configuration/modules.md +66 -0
  134. package/docs/public/configuration/overview.md +66 -0
  135. package/docs/public/events/catalog.md +65 -0
  136. package/docs/public/getting-started/installation.md +78 -0
  137. package/docs/public/getting-started/quick-start.md +77 -0
  138. package/docs/public/getting-started/react-nextjs.md +55 -0
  139. package/docs/public/getting-started/script-tag.md +57 -0
  140. package/docs/public/guides/funnel-checkout.md +52 -0
  141. package/docs/public/guides/funnel-downsell.md +53 -0
  142. package/docs/public/guides/funnel-full.md +64 -0
  143. package/docs/public/guides/funnel-landing.md +68 -0
  144. package/docs/public/guides/funnel-thank-you.md +48 -0
  145. package/docs/public/guides/funnel-upsell.md +72 -0
  146. package/docs/public/limitations.md +32 -0
  147. package/docs/public/privacy/limitations.md +33 -0
  148. package/docs/public/release-candidate/validation.md +42 -0
  149. package/docs/public/troubleshooting.md +55 -0
  150. package/package.json +10 -13
@@ -0,0 +1,597 @@
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_TO_CART source link</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 {
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
+ @media (max-width: 560px) { .row { grid-template-columns: 1fr; } }
58
+ .status, pre {
59
+ background: #0f172a; color: #e2e8f0; border-radius: 8px; padding: 0.75rem;
60
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
61
+ font-size: 0.78rem; white-space: pre-wrap; word-break: break-word;
62
+ max-height: 260px; overflow: auto;
63
+ }
64
+ .pill {
65
+ display: inline-block; border-radius: 999px; padding: 0.15rem 0.55rem;
66
+ font-size: 0.72rem; background: #e2e8f0; color: #334155; margin-left: 0.35rem;
67
+ }
68
+ .pill.ok { background: #bbf7d0; color: #166534; }
69
+ .checklist { margin: 0; padding-left: 1.1rem; font-size: 0.88rem; color: var(--muted); }
70
+ .checklist li { margin: 0.35rem 0; }
71
+ .ctx {
72
+ border-left: 3px solid var(--accent); padding-left: 0.75rem; margin-bottom: 0.85rem;
73
+ color: var(--muted); font-size: 0.88rem;
74
+ }
75
+ .product {
76
+ border: 1px dashed var(--border); border-radius: 10px; padding: 0.75rem; margin: 0.5rem 0;
77
+ }
78
+ .product strong { display: block; margin-bottom: 0.2rem; }
79
+ code { font-size: 0.85em; }
80
+ </style>
81
+ </head>
82
+ <body>
83
+ <div class="wrap">
84
+ <h1>ADD_TO_CART — source <code>link</code></h1>
85
+ <p class="sub">
86
+ Destino do &lt;a href&gt; (não a URL da página). Match + bindings + catálogo.
87
+ <span class="pill" id="init-pill">offline</span>
88
+ </p>
89
+ <div class="nav"><a href="example-add-to-cart-attribute.html" class="">1. Atributo</a>
90
+ <a href="example-add-to-cart-click.html" class="">2. Click+Form</a>
91
+ <a href="example-add-to-cart-auto.html" class="">3. Auto+Form</a>
92
+ <a href="example-add-to-cart-text.html" class="">4. Text</a>
93
+ <a href="example-add-to-cart-manual.html" class="">5. Manual API</a>
94
+ <a href="example-add-to-cart-dedupe.html" class="">6. Dedupe</a>
95
+ <a href="example-add-to-cart-order-bump.html" class="">7. Order bump</a>
96
+ <a href="example-add-to-cart-link.html" class="active">8. Link</a></div>
97
+ <div class="hint"><strong>Contexto:</strong> CTA que aponta para checkout externo.
98
+ Source <code>type: 'link'</code> casa origin/path/query, resolve
99
+ <code>productId</code> (dataset → query → pathParam) e dispara
100
+ <code>ADD_TO_CART</code> via <code>ConfiguredLinkDetector</code>.
101
+ Enrich pelo catálogo. Navegação real não é bloqueada pelo Pixel
102
+ (este playground só impede o leave da página para demo).</div>
103
+
104
+ <div class="card">
105
+ <h2>Lifecycle</h2>
106
+ <div class="actions">
107
+ <button id="btn-reinit" class="primary" type="button">Reinitialize</button>
108
+ <button id="btn-destroy" class="danger" type="button">Destroy</button>
109
+ <button id="btn-clear" type="button">Clear logs</button>
110
+ </div>
111
+ <div class="status" id="runtime-status">Aguardando init...</div>
112
+ </div>
113
+
114
+ <div class="grid">
115
+ <div>
116
+ <div class="card">
117
+ <h2>Links de checkout <span class="pill">ConfiguredLink</span></h2>
118
+ <div class="ctx">
119
+ Match: <code>https://checkout.example.com/pay/:offerId?product=…</code>
120
+ </div>
121
+ <div class="product">
122
+ <strong>Oferta Principal — query product</strong>
123
+ <span class="sub" style="margin:0">productId via query → enrich catalog</span>
124
+ <div class="actions">
125
+ <a
126
+ class="primary"
127
+ data-demo-stay
128
+ href="https://checkout.example.com/pay/offer_1?product=main_offer"
129
+ style="display:inline-block;text-decoration:none;border-radius:8px;padding:0.5rem 0.85rem;background:#0f766e;color:#fff;border:1px solid #0f766e;"
130
+ >
131
+ Comprar (query)
132
+ </a>
133
+ </div>
134
+ </div>
135
+ <div class="product">
136
+ <strong>Oferta Principal — dataset</strong>
137
+ <span class="sub" style="margin:0">data-product-id tem precedência sobre query</span>
138
+ <div class="actions">
139
+ <a
140
+ class="primary"
141
+ data-demo-stay
142
+ data-product-id="main_offer"
143
+ href="https://checkout.example.com/pay/offer_1?product=ignored_query"
144
+ style="display:inline-block;text-decoration:none;border-radius:8px;padding:0.5rem 0.85rem;background:#0f766e;color:#fff;border:1px solid #0f766e;"
145
+ >
146
+ Comprar (dataset)
147
+ </a>
148
+ </div>
149
+ </div>
150
+ <div class="product">
151
+ <strong>Negativos</strong>
152
+ <div class="actions">
153
+ <a
154
+ data-demo-stay
155
+ href="https://other.example.com/pay/offer_1?product=main_offer"
156
+ style="display:inline-block;text-decoration:none;border-radius:8px;padding:0.5rem 0.85rem;background:#fff;color:#0f172a;border:1px solid #e2e8f0;"
157
+ >
158
+ Origin diferente
159
+ </a>
160
+ <a
161
+ data-demo-stay
162
+ href="https://checkout.example.com/pay/offer_1"
163
+ style="display:inline-block;text-decoration:none;border-radius:8px;padding:0.5rem 0.85rem;background:#fff;color:#0f172a;border:1px solid #e2e8f0;"
164
+ >
165
+ Sem query product
166
+ </a>
167
+ <a
168
+ data-demo-stay
169
+ href="mailto:demo@example.com"
170
+ style="display:inline-block;text-decoration:none;border-radius:8px;padding:0.5rem 0.85rem;background:#fff;color:#0f172a;border:1px solid #e2e8f0;"
171
+ >
172
+ mailto (ignorado)
173
+ </a>
174
+ </div>
175
+ </div>
176
+ <p class="sub">
177
+ Clique em filho (&lt;span&gt;) dentro do link também dispara.
178
+ Ctrl/meta-click também rastreia (nova aba).
179
+ </p>
180
+ </div>
181
+ <div class="card">
182
+ <h2>Checklist</h2>
183
+ <ul class="checklist">
184
+ <li>[ ] Link com match → <code>ADD_TO_CART</code> + enrich catalog</li>
185
+ <li>[ ] Dataset vence query no fallback de bindings</li>
186
+ <li>[ ] Origin / mailto / sem query product → não dispara</li>
187
+ <li>[ ] Cart mirror atualiza</li>
188
+ <li>[ ] Detector: <code>ConfiguredLink(ADD_TO_CART:checkout-product-link)</code></li>
189
+ </ul>
190
+ </div>
191
+ </div>
192
+ <div>
193
+ <div class="card">
194
+ <h2>Event counts</h2>
195
+ <div class="status" id="event-counts">Nenhum evento ainda</div>
196
+ </div>
197
+ <div class="card">
198
+ <h2>Cart mirror (via eventos)</h2>
199
+ <div class="status" id="cart-mirror">{}</div>
200
+ </div>
201
+ <div class="card">
202
+ <h2>Active detectors</h2>
203
+ <div class="status" id="detectors">—</div>
204
+ </div>
205
+
206
+ <div class="card">
207
+ <h2>Last event JSON</h2>
208
+ <pre id="last-event">null</pre>
209
+ </div>
210
+ <div class="card">
211
+ <h2>Event log</h2>
212
+ <pre id="logs">Aguardando eventos...</pre>
213
+ </div>
214
+ </div>
215
+ </div>
216
+ </div>
217
+
218
+ <script src="../../../v2/global.global.js"></script>
219
+ <script>
220
+ const { Pixel, DEFAULT_PIXEL_CONFIG } = window.PixelV2;
221
+ const API_ENDPOINT =
222
+ 'https://micro-service-pixel-production-4826.up.railway.app';
223
+ const PIXEL_ID = 'pix_7315610';
224
+
225
+ const els = {
226
+ logs: document.getElementById('logs'),
227
+ last: document.getElementById('last-event'),
228
+ counts: document.getElementById('event-counts'),
229
+ cart: document.getElementById('cart-mirror'),
230
+ detectors: document.getElementById('detectors'),
231
+ dedupe: document.getElementById('dedupe-keys'),
232
+ runtime: document.getElementById('runtime-status'),
233
+ pill: document.getElementById('init-pill'),
234
+ };
235
+
236
+ let pixel = null;
237
+ let unsubscribe = null;
238
+ let initCount = 0;
239
+ let destroyCount = 0;
240
+ const counts = {};
241
+ const cartMirror = {};
242
+
243
+ function addToCartDetectorConfig() {
244
+ return {
245
+ enabled: true,
246
+ sources: [
247
+ {
248
+ name: 'checkout-product-link',
249
+ type: 'link',
250
+ enabled: true,
251
+ fireOnce: false,
252
+ match: {
253
+ protocols: ['https:'],
254
+ origins: ['https://checkout.example.com'],
255
+ path: { template: '/pay/:offerId' },
256
+ query: {
257
+ mode: 'all',
258
+ conditions: [{ key: 'product', operator: 'exists' }],
259
+ },
260
+ },
261
+ bindings: {
262
+ productId: {
263
+ from: [
264
+ { source: 'dataset', key: 'productId' },
265
+ { source: 'query', key: 'product' },
266
+ { source: 'pathParam', key: 'productId' },
267
+ ],
268
+ required: true,
269
+ },
270
+ offerId: {
271
+ from: { source: 'pathParam', key: 'offerId' },
272
+ },
273
+ destinationUrl: {
274
+ from: { source: 'href' },
275
+ },
276
+ },
277
+ },
278
+ ],
279
+ };
280
+ }
281
+
282
+ function buildConfig() {
283
+ const base = DEFAULT_PIXEL_CONFIG;
284
+ return {
285
+ ...base,
286
+ app: {
287
+ ...base.app,
288
+ source: 'custom',
289
+ environment: 'development',
290
+ debug: true,
291
+ },
292
+ transport: {
293
+ ...DEFAULT_PIXEL_CONFIG.transport,
294
+ apiEndpoint: API_ENDPOINT,
295
+ timeoutMs: 10000,
296
+ },
297
+ identity: { ...base.identity, pixelId: PIXEL_ID },
298
+ commerce: {
299
+ enabled: true,
300
+ currency: 'BRL',
301
+ catalog: { products: [
302
+ {
303
+ id: 'main_offer',
304
+ name: 'Oferta Principal',
305
+ type: 'main',
306
+ price: 197,
307
+ currency: 'BRL',
308
+ quantity: 1,
309
+ },
310
+ {
311
+ id: 'order_bump_01',
312
+ name: 'Order Bump Especial',
313
+ type: 'order_bump',
314
+ price: 47,
315
+ currency: 'BRL',
316
+ quantity: 1,
317
+ },
318
+ {
319
+ id: 'upsell_01',
320
+ name: 'Upsell 01',
321
+ type: 'upsell',
322
+ price: 97,
323
+ currency: 'BRL',
324
+ quantity: 1,
325
+ },
326
+ ] },
327
+ cart: {
328
+ mode: 'single_product',
329
+ initialItems: [{ productId: "main_offer", quantity: 1 }],
330
+ calculateValueFrom: 'cart',
331
+ allowDynamicItems: true,
332
+ },
333
+ mappings: {
334
+ attributes: {
335
+ productId: ['data-product-id', 'data-sku', 'data-offer-id'],
336
+ productName: ['data-product-name', 'data-name'],
337
+ price: ['data-product-price', 'data-price'],
338
+ quantity: ['data-quantity', 'data-qty'],
339
+ currency: ['data-currency'],
340
+ },
341
+ fields: {
342
+ productId: ['productId', 'product_id', 'offerId', 'sku'],
343
+ productName: ['productName', 'product_name'],
344
+ price: ['price', 'amount'],
345
+ quantity: ['quantity', 'qty'],
346
+ currency: ['currency'],
347
+ email: ['email', 'customerEmail'],
348
+ phone: ['phone', 'telefone', 'customerPhone'],
349
+ },
350
+ },
351
+ enrichment: {
352
+ pageView: { enabled: false, source: 'cart' },
353
+ viewContent: { enabled: true, source: 'event_or_cart' },
354
+ lead: { enabled: false, source: 'event_or_cart' },
355
+ addToCart: { enabled: true, source: 'event_or_cart' },
356
+ removeFromCart: { enabled: true, source: 'event_or_cart' },
357
+ initiateCheckout: { enabled: true, source: 'cart' },
358
+ addPaymentInfo: { enabled: true, source: 'cart' },
359
+ purchase: { enabled: true, source: 'cart' },
360
+ }
361
+ },
362
+ modules: {
363
+ ...base.modules,
364
+ core: {
365
+ ...base.modules.core,
366
+ enabled: false,
367
+ pageView: {
368
+ ...base.modules.core.pageView,
369
+ enabled: false,
370
+ trackInitialPageView: false,
371
+ spa: false,
372
+ },
373
+ },
374
+ behavior: { ...base.modules.behavior, enabled: false },
375
+ privacy: { ...base.modules.privacy, enabled: false },
376
+ transport: {
377
+ enabled: true,
378
+ mockSender: { enabled: false },
379
+ sender: { mode: 'http' },
380
+ persistence: { enabled: true },
381
+ replay: { enabled: true },
382
+ ordering: { enabled: true },
383
+ coordination: { enabled: true },
384
+ circuitBreaker: {
385
+ enabled: true,
386
+ failureThreshold: 5,
387
+ resetTimeoutMs: 30000,
388
+ halfOpenMaxAttempts: 2,
389
+ },
390
+ backpressure: {
391
+ enabled: true,
392
+ maxQueueSize: 500,
393
+ policy: 'drop_oldest',
394
+ sampleRate: 0.5,
395
+ },
396
+ deadLetter: { enabled: true, maxEntries: 200 },
397
+ compression: { enabled: true, strategy: 'identity' },
398
+ retry: {
399
+ enabled: true,
400
+ maxAttempts: 4,
401
+ baseDelayMs: 500,
402
+ maxDelayMs: 4000,
403
+ multiplier: 2,
404
+ },
405
+ batch: {
406
+ enabled: true,
407
+ batchSize: 10,
408
+ flushIntervalMs: 2000,
409
+ maxWaitMs: 5000,
410
+ },
411
+ timeout: { enabled: true, timeoutMs: 10000 },
412
+ offline: { enabled: true },
413
+ flush: {
414
+ enabled: true,
415
+ flushIntervalMs: 2000,
416
+ flushOnDestroy: true,
417
+ prepareUnloadHooks: true,
418
+ },
419
+ },
420
+ integrations: { ...base.modules.integrations, enabled: false },
421
+ conversion: {
422
+ enabled: true,
423
+ manual: {
424
+ pageView: { enabled: false },
425
+ purchase: { enabled: false, sources: [] },
426
+ lead: { enabled: false, sources: [] },
427
+ addToCart: { enabled: true },
428
+ removeFromCart: { enabled: true },
429
+ initiateCheckout: { enabled: false, sources: [] },
430
+ addPaymentInfo: { enabled: false, sources: [] },
431
+ search: { enabled: false, sources: [] },
432
+ viewContent: { enabled: false, sources: [] },
433
+ },
434
+ auto: {
435
+ enabled: true,
436
+ detectors: {
437
+ lead: { enabled: false, sources: [] },
438
+ purchase: { enabled: false, sources: [] },
439
+ addToCart: addToCartDetectorConfig(),
440
+ removeFromCart: { enabled: false, sources: [] },
441
+ initiateCheckout: { enabled: false, sources: [] },
442
+ addPaymentInfo: { enabled: false, sources: [] },
443
+ search: { enabled: false, sources: [] },
444
+ viewContent: { enabled: false, sources: [] },
445
+ },
446
+ },
447
+ rules: {
448
+ enabled: false,
449
+ selectors: [],
450
+ texts: [],
451
+ urlPatterns: [],
452
+ checkout: { enabled: false },
453
+ card: { enabled: false },
454
+ },
455
+ },
456
+ },
457
+ };
458
+ }
459
+
460
+ function appendLog(message) {
461
+ const line = '[' + new Date().toISOString() + '] ' + message;
462
+ const prev = els.logs.textContent;
463
+ els.logs.textContent =
464
+ prev === 'Aguardando eventos...' ? line : line + '\n' + prev;
465
+ }
466
+
467
+ function renderCounts() {
468
+ const lines = Object.keys(counts)
469
+ .sort()
470
+ .map(function (type) { return type + ': ' + counts[type]; });
471
+ els.counts.textContent =
472
+ lines.length > 0 ? lines.join('\n') : 'Nenhum evento ainda';
473
+ }
474
+
475
+ function renderCart() {
476
+ if (!els.cart) return;
477
+ els.cart.textContent = JSON.stringify(cartMirror, null, 2);
478
+ }
479
+
480
+ function renderDebug() {
481
+ const detectors =
482
+ pixel && pixel.getDebugActiveDetectors
483
+ ? pixel.getDebugActiveDetectors()
484
+ : [];
485
+ els.detectors.textContent =
486
+ detectors.length > 0 ? detectors.join('\n') : 'Nenhum detector ativo';
487
+ if (els.dedupe) {
488
+ const keys =
489
+ pixel && pixel.getDebugDedupeKeys ? pixel.getDebugDedupeKeys() : [];
490
+ els.dedupe.textContent =
491
+ keys.length > 0 ? keys.join('\n') : 'Nenhuma chave';
492
+ }
493
+ els.runtime.textContent =
494
+ 'initialized: ' +
495
+ (pixel ? pixel.isInitialized() : false) +
496
+ '\ninit count: ' +
497
+ initCount +
498
+ '\ndestroy count: ' +
499
+ destroyCount +
500
+ '\npixelId: ' +
501
+ PIXEL_ID +
502
+ '\nscenario: source link · checkout href';
503
+ els.pill.textContent =
504
+ pixel && pixel.isInitialized() ? 'ready' : 'offline';
505
+ els.pill.className =
506
+ 'pill' + (pixel && pixel.isInitialized() ? ' ok' : '');
507
+ }
508
+
509
+ function updateCartFromEvent(event) {
510
+ if (
511
+ event.type === 'ADD_TO_CART' &&
512
+ event.data &&
513
+ event.data.productId
514
+ ) {
515
+ cartMirror[event.data.productId] = {
516
+ productId: event.data.productId,
517
+ productName: event.data.productName,
518
+ price: event.data.price,
519
+ currency: event.data.currency,
520
+ quantity: event.data.quantity != null ? event.data.quantity : 1,
521
+ };
522
+ }
523
+ if (
524
+ event.type === 'REMOVE_FROM_CART' &&
525
+ event.data &&
526
+ event.data.productId
527
+ ) {
528
+ delete cartMirror[event.data.productId];
529
+ }
530
+ renderCart();
531
+ }
532
+
533
+ function onEvent(event) {
534
+ counts[event.type] = (counts[event.type] || 0) + 1;
535
+ renderCounts();
536
+ updateCartFromEvent(event);
537
+ els.last.textContent = JSON.stringify(event, null, 2);
538
+ appendLog(event.type + ' ' + JSON.stringify(event.data || {}));
539
+ renderDebug();
540
+ }
541
+
542
+ async function boot() {
543
+ if (unsubscribe) { unsubscribe(); unsubscribe = null; }
544
+ if (pixel) {
545
+ await pixel.destroy();
546
+ destroyCount += 1;
547
+ pixel = null;
548
+ }
549
+ Object.keys(cartMirror).forEach(function (k) { delete cartMirror[k]; });
550
+ renderCart();
551
+ pixel = new Pixel(buildConfig());
552
+ await pixel.init();
553
+ initCount += 1;
554
+ const services = pixel.getDebugServices();
555
+ if (services && services.dispatcher) {
556
+ unsubscribe = services.dispatcher.subscribe(onEvent);
557
+ }
558
+ appendLog('Pixel initialized — source link · checkout href');
559
+ renderDebug();
560
+ }
561
+
562
+ async function destroyPixel() {
563
+ if (unsubscribe) { unsubscribe(); unsubscribe = null; }
564
+ if (pixel) {
565
+ await pixel.destroy();
566
+ destroyCount += 1;
567
+ pixel = null;
568
+ }
569
+ appendLog('Pixel destroyed');
570
+ renderDebug();
571
+ }
572
+
573
+ document.getElementById('btn-reinit').onclick = function () { boot(); };
574
+ document.getElementById('btn-destroy').onclick = function () { destroyPixel(); };
575
+ document.getElementById('btn-clear').onclick = function () {
576
+ els.logs.textContent = 'Aguardando eventos...';
577
+ els.last.textContent = 'null';
578
+ Object.keys(counts).forEach(function (k) { delete counts[k]; });
579
+ Object.keys(cartMirror).forEach(function (k) { delete cartMirror[k]; });
580
+ renderCounts();
581
+ renderCart();
582
+ };
583
+
584
+ document.querySelectorAll('[data-demo-stay]').forEach(function (el) {
585
+ el.addEventListener('click', function (event) {
586
+ // Pixel escuta em capture e já trackeou; aqui só evitamos sair da página.
587
+ event.preventDefault();
588
+ appendLog(
589
+ '(playground) navegação bloqueada para demo — Pixel não chama preventDefault'
590
+ );
591
+ });
592
+ });
593
+
594
+ boot();
595
+ </script>
596
+ </body>
597
+ </html>
@@ -92,7 +92,8 @@ code { font-size: 0.85em; }
92
92
  <a href="example-add-to-cart-text.html" class="">4. Text</a>
93
93
  <a href="example-add-to-cart-manual.html" class="active">5. Manual API</a>
94
94
  <a href="example-add-to-cart-dedupe.html" class="">6. Dedupe</a>
95
- <a href="example-add-to-cart-order-bump.html" class="">7. Order bump</a></div>
95
+ <a href="example-add-to-cart-order-bump.html" class="">7. Order bump</a>
96
+ <a href="example-add-to-cart-link.html" class="">8. Link</a></div>
96
97
  <div class="hint"><strong>Contexto:</strong> API manual. Auto detector <strong>desligado</strong>.
97
98
  Valida prioridade do payload, enrich do catálogo e override de preço.</div>
98
99
 
@@ -166,7 +167,7 @@ code { font-size: 0.85em; }
166
167
  </div>
167
168
  </div>
168
169
 
169
- <script src="../../../dist/v2/global.global.js"></script>
170
+ <script src="../../../v2/global.global.js"></script>
170
171
  <script>
171
172
  const { Pixel, DEFAULT_PIXEL_CONFIG } = window.PixelV2;
172
173
  const API_ENDPOINT =
@@ -92,7 +92,8 @@ code { font-size: 0.85em; }
92
92
  <a href="example-add-to-cart-text.html" class="">4. Text</a>
93
93
  <a href="example-add-to-cart-manual.html" class="">5. Manual API</a>
94
94
  <a href="example-add-to-cart-dedupe.html" class="">6. Dedupe</a>
95
- <a href="example-add-to-cart-order-bump.html" class="active">7. Order bump</a></div>
95
+ <a href="example-add-to-cart-order-bump.html" class="active">7. Order bump</a>
96
+ <a href="example-add-to-cart-link.html" class="">8. Link</a></div>
96
97
  <div class="hint"><strong>Contexto:</strong> oferta principal + order bump. Cada add atualiza
97
98
  CommerceState (<code>allowDynamicItems</code>). Remover bump limpa o item
98
99
  (detector remove habilitado neste cenário).</div>
@@ -188,7 +189,7 @@ code { font-size: 0.85em; }
188
189
  </div>
189
190
  </div>
190
191
 
191
- <script src="../../../dist/v2/global.global.js"></script>
192
+ <script src="../../../v2/global.global.js"></script>
192
193
  <script>
193
194
  const { Pixel, DEFAULT_PIXEL_CONFIG } = window.PixelV2;
194
195
  const API_ENDPOINT =
@@ -92,7 +92,8 @@ code { font-size: 0.85em; }
92
92
  <a href="example-add-to-cart-text.html" class="active">4. Text</a>
93
93
  <a href="example-add-to-cart-manual.html" class="">5. Manual API</a>
94
94
  <a href="example-add-to-cart-dedupe.html" class="">6. Dedupe</a>
95
- <a href="example-add-to-cart-order-bump.html" class="">7. Order bump</a></div>
95
+ <a href="example-add-to-cart-order-bump.html" class="">7. Order bump</a>
96
+ <a href="example-add-to-cart-link.html" class="">8. Link</a></div>
96
97
  <div class="hint"><strong>Contexto:</strong> CTA sem <code>data-track</code>, só texto visível.
97
98
  Selector <code>text:Comprar agora</code>. Produto via <code>data-product-id</code>
98
99
  no botão + catálogo. Com <code>selectorForm</code> exigindo contato.</div>
@@ -177,7 +178,7 @@ code { font-size: 0.85em; }
177
178
  </div>
178
179
  </div>
179
180
 
180
- <script src="../../../dist/v2/global.global.js"></script>
181
+ <script src="../../../v2/global.global.js"></script>
181
182
  <script>
182
183
  const { Pixel, DEFAULT_PIXEL_CONFIG } = window.PixelV2;
183
184
  const API_ENDPOINT =
@@ -173,7 +173,7 @@
173
173
  </section>
174
174
  <div id="dynamic-zone"></div>
175
175
 
176
- <script src="../../../dist/v2/global.global.js"></script>
176
+ <script src="../../../v2/global.global.js"></script>
177
177
  <script>
178
178
  (function () {
179
179
  const { Pixel, DEFAULT_PIXEL_CONFIG } = window.PixelV2;
@@ -104,7 +104,7 @@
104
104
 
105
105
  <div id="logs"></div>
106
106
 
107
- <script src="../../../dist/v2/global.global.js"></script>
107
+ <script src="../../../v2/global.global.js"></script>
108
108
  <script>
109
109
  (function () {
110
110
  const { Pixel, DEFAULT_PIXEL_CONFIG } = window.PixelV2;