@mazyos/lp-tracker 0.1.0
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/AGENTS.md +71 -0
- package/LICENSE +16 -0
- package/README.md +208 -0
- package/SKILL.md +71 -0
- package/dist/attribution.d.ts +16 -0
- package/dist/attribution.d.ts.map +1 -0
- package/dist/attribution.js +77 -0
- package/dist/attribution.js.map +1 -0
- package/dist/checkout/profiles.d.ts +18 -0
- package/dist/checkout/profiles.d.ts.map +1 -0
- package/dist/checkout/profiles.js +89 -0
- package/dist/checkout/profiles.js.map +1 -0
- package/dist/checkout/resolve.d.ts +16 -0
- package/dist/checkout/resolve.d.ts.map +1 -0
- package/dist/checkout/resolve.js +95 -0
- package/dist/checkout/resolve.js.map +1 -0
- package/dist/checkout.d.ts +3 -0
- package/dist/checkout.d.ts.map +1 -0
- package/dist/checkout.js +3 -0
- package/dist/checkout.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +78 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/browser-attribution.d.ts +9 -0
- package/dist/client/browser-attribution.d.ts.map +1 -0
- package/dist/client/browser-attribution.js +116 -0
- package/dist/client/browser-attribution.js.map +1 -0
- package/dist/client/delegated.d.ts +6 -0
- package/dist/client/delegated.d.ts.map +1 -0
- package/dist/client/delegated.js +139 -0
- package/dist/client/delegated.js.map +1 -0
- package/dist/client/engagement-tracking.d.ts +11 -0
- package/dist/client/engagement-tracking.d.ts.map +1 -0
- package/dist/client/engagement-tracking.js +138 -0
- package/dist/client/engagement-tracking.js.map +1 -0
- package/dist/client/events.d.ts +43 -0
- package/dist/client/events.d.ts.map +1 -0
- package/dist/client/events.js +223 -0
- package/dist/client/events.js.map +1 -0
- package/dist/client/meta-pixel.d.ts +33 -0
- package/dist/client/meta-pixel.d.ts.map +1 -0
- package/dist/client/meta-pixel.js +143 -0
- package/dist/client/meta-pixel.js.map +1 -0
- package/dist/client/provider.d.ts +4 -0
- package/dist/client/provider.d.ts.map +1 -0
- package/dist/client/provider.js +113 -0
- package/dist/client/provider.js.map +1 -0
- package/dist/client/public-api.d.ts +7 -0
- package/dist/client/public-api.d.ts.map +1 -0
- package/dist/client/public-api.js +74 -0
- package/dist/client/public-api.js.map +1 -0
- package/dist/client/retry-queue.d.ts +20 -0
- package/dist/client/retry-queue.d.ts.map +1 -0
- package/dist/client/retry-queue.js +165 -0
- package/dist/client/retry-queue.js.map +1 -0
- package/dist/client/runtime.d.ts +81 -0
- package/dist/client/runtime.d.ts.map +1 -0
- package/dist/client/runtime.js +301 -0
- package/dist/client/runtime.js.map +1 -0
- package/dist/client/spa-tracking.d.ts +3 -0
- package/dist/client/spa-tracking.d.ts.map +1 -0
- package/dist/client/spa-tracking.js +54 -0
- package/dist/client/spa-tracking.js.map +1 -0
- package/dist/client/transport.d.ts +14 -0
- package/dist/client/transport.d.ts.map +1 -0
- package/dist/client/transport.js +54 -0
- package/dist/client/transport.js.map +1 -0
- package/dist/client/view-tracking.d.ts +3 -0
- package/dist/client/view-tracking.d.ts.map +1 -0
- package/dist/client/view-tracking.js +71 -0
- package/dist/client/view-tracking.js.map +1 -0
- package/dist/doctor/format.d.ts +3 -0
- package/dist/doctor/format.d.ts.map +1 -0
- package/dist/doctor/format.js +18 -0
- package/dist/doctor/format.js.map +1 -0
- package/dist/doctor/remote-checks.d.ts +3 -0
- package/dist/doctor/remote-checks.d.ts.map +1 -0
- package/dist/doctor/remote-checks.js +132 -0
- package/dist/doctor/remote-checks.js.map +1 -0
- package/dist/doctor/run.d.ts +3 -0
- package/dist/doctor/run.d.ts.map +1 -0
- package/dist/doctor/run.js +18 -0
- package/dist/doctor/run.js.map +1 -0
- package/dist/doctor/scan.d.ts +2 -0
- package/dist/doctor/scan.d.ts.map +1 -0
- package/dist/doctor/scan.js +70 -0
- package/dist/doctor/scan.js.map +1 -0
- package/dist/doctor/static-checks.d.ts +5 -0
- package/dist/doctor/static-checks.d.ts.map +1 -0
- package/dist/doctor/static-checks.js +130 -0
- package/dist/doctor/static-checks.js.map +1 -0
- package/dist/doctor/types.d.ts +20 -0
- package/dist/doctor/types.d.ts.map +1 -0
- package/dist/doctor/types.js +2 -0
- package/dist/doctor/types.js.map +1 -0
- package/dist/handler/body.d.ts +7 -0
- package/dist/handler/body.d.ts.map +1 -0
- package/dist/handler/body.js +67 -0
- package/dist/handler/body.js.map +1 -0
- package/dist/handler/create.d.ts +16 -0
- package/dist/handler/create.d.ts.map +1 -0
- package/dist/handler/create.js +69 -0
- package/dist/handler/create.js.map +1 -0
- package/dist/handler/forward.d.ts +13 -0
- package/dist/handler/forward.d.ts.map +1 -0
- package/dist/handler/forward.js +65 -0
- package/dist/handler/forward.js.map +1 -0
- package/dist/handler/health.d.ts +7 -0
- package/dist/handler/health.d.ts.map +1 -0
- package/dist/handler/health.js +85 -0
- package/dist/handler/health.js.map +1 -0
- package/dist/handler/sanitize.d.ts +12 -0
- package/dist/handler/sanitize.d.ts.map +1 -0
- package/dist/handler/sanitize.js +87 -0
- package/dist/handler/sanitize.js.map +1 -0
- package/dist/ids.d.ts +4 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +37 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/capture.d.ts +11 -0
- package/dist/middleware/capture.d.ts.map +1 -0
- package/dist/middleware/capture.js +78 -0
- package/dist/middleware/capture.js.map +1 -0
- package/dist/middleware.d.ts +8 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +9 -0
- package/dist/middleware.js.map +1 -0
- package/dist/next.d.ts +8 -0
- package/dist/next.d.ts.map +1 -0
- package/dist/next.js +10 -0
- package/dist/next.js.map +1 -0
- package/dist/server/site.d.ts +23 -0
- package/dist/server/site.d.ts.map +1 -0
- package/dist/server/site.js +147 -0
- package/dist/server/site.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +170 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/package.json +99 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# LP tracker maintenance rules
|
|
2
|
+
|
|
3
|
+
Apply these rules to every change under `packages/lp-tracker`.
|
|
4
|
+
|
|
5
|
+
## Protect the event boundary
|
|
6
|
+
|
|
7
|
+
- Keep `BrowserEventName` closed. Permit only `PageView`, `ViewContent`, `Lead`,
|
|
8
|
+
`AddToCart`, `InitiateCheckout`, `CompleteRegistration`, and `Contact`.
|
|
9
|
+
- Never add `Purchase`, `Subscribe`, `Refund`, or `Chargeback` to a browser
|
|
10
|
+
type, delegated hook, or collect route allowlist. Those events belong to
|
|
11
|
+
authenticated checkout/provider ingestion.
|
|
12
|
+
- Never hash PII in browser code. Send raw normalized values only to the
|
|
13
|
+
same-origin collect route and let the core apply hashing.
|
|
14
|
+
- Strip browser-supplied IP and user-agent values in the Next handler. Trust
|
|
15
|
+
only the documented proxy-header order.
|
|
16
|
+
|
|
17
|
+
## Preserve consent and attribution
|
|
18
|
+
|
|
19
|
+
- Keep `required` as the default consent mode.
|
|
20
|
+
- Do not initialize pixels, POST events, or persist pre-consent events.
|
|
21
|
+
- Keep pre-consent events in memory only. Clear memory when consent is denied.
|
|
22
|
+
- Generate `_mzc` only with Web Crypto as exactly 22 base62 characters.
|
|
23
|
+
- Prefer query attribution over cookies and rewrite first-party attribution
|
|
24
|
+
cookies without replacing a valid value with an empty value.
|
|
25
|
+
- Preserve `event_id` and `event_time` across every retry.
|
|
26
|
+
- Keep the retry key versioned, capped at 50 items, and limited to 72 hours.
|
|
27
|
+
|
|
28
|
+
## Keep client interactions immediate
|
|
29
|
+
|
|
30
|
+
- Return from `track()` synchronously with the event ID.
|
|
31
|
+
- Never await network activity in delegated click or submit listeners.
|
|
32
|
+
- Rewrite an existing checkout anchor's `href`; never call `preventDefault()`
|
|
33
|
+
and never call `window.open()`.
|
|
34
|
+
- Use one Meta event ID for both pixel and collect delivery.
|
|
35
|
+
- Do not add an implicit Meta `PageView`; the normal event pipeline owns it.
|
|
36
|
+
|
|
37
|
+
## Keep server credentials server-only
|
|
38
|
+
|
|
39
|
+
- Read `MAZYOS_SITE_SECRET` only in `./next`, `./server`, or CLI code.
|
|
40
|
+
- Never expose secrets in response bodies, cache keys, errors, logs, or public
|
|
41
|
+
health output.
|
|
42
|
+
- Keep production public health output limited to `ok` and `version`.
|
|
43
|
+
- Bound request bodies and network timeouts.
|
|
44
|
+
- Retry only one network or upstream 5xx failure.
|
|
45
|
+
- Do not add mutable request-scoped module state.
|
|
46
|
+
- Keep Next.js `config`, `runtime`, and `dynamic` literals in consumer
|
|
47
|
+
file-convention modules; Next.js cannot statically analyze reexported values.
|
|
48
|
+
|
|
49
|
+
## Treat checkout mappings as evidence-based
|
|
50
|
+
|
|
51
|
+
- Keep unknown checkout URLs on the verified `generic` profile.
|
|
52
|
+
- Mark a provider profile `verified` only with a checked-in real echo fixture
|
|
53
|
+
proving its accepted parameter names.
|
|
54
|
+
- Keep provisional profiles conservative: `mzc`, UTM, and no invented
|
|
55
|
+
provider-specific attribution parameters.
|
|
56
|
+
- Preserve existing query parameters and never overwrite them.
|
|
57
|
+
|
|
58
|
+
## Validate every change
|
|
59
|
+
|
|
60
|
+
Run:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pnpm --filter @mazyos/lp-tracker run lint
|
|
64
|
+
pnpm --filter @mazyos/lp-tracker run typecheck
|
|
65
|
+
pnpm --filter @mazyos/lp-tracker run test:run
|
|
66
|
+
pnpm --filter @mazyos/lp-tracker run build
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Retain tests for consent, event-ID parity, retries, middleware cookies, handler
|
|
70
|
+
filtering, checkout length bounds, doctor checks, and compile-time rejection of
|
|
71
|
+
server-only events.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Copyright (c) 2026 MazyOS
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted to use, copy, and modify this software solely
|
|
4
|
+
to instrument landing pages that send conversion events to a MazyOS
|
|
5
|
+
workspace.
|
|
6
|
+
|
|
7
|
+
Redistribution of this software as a competing tracking SDK, and use of
|
|
8
|
+
this software independently of MazyOS, are not granted.
|
|
9
|
+
|
|
10
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
11
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
12
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
13
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
14
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
15
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
16
|
+
DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# @mazyos/lp-tracker
|
|
2
|
+
|
|
3
|
+
First-party, full-funnel conversion tracking for React 19 and Next.js 16
|
|
4
|
+
landing pages. The package keeps browser events deliberately narrower than the
|
|
5
|
+
server conversion contract: a landing page cannot type-check a `Purchase`,
|
|
6
|
+
`Subscribe`, `Refund`, or `Chargeback`.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm add @mazyos/lp-tracker
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Use Node.js 22 or newer. Configure server credentials only on the Next.js
|
|
15
|
+
server:
|
|
16
|
+
|
|
17
|
+
```dotenv
|
|
18
|
+
MAZYOS_CORE_URL=https://api.example.com
|
|
19
|
+
MAZYOS_SITE_SECRET=
|
|
20
|
+
MAZYOS_DIAGNOSTICS_TOKEN=
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Never prefix `MAZYOS_SITE_SECRET` with `NEXT_PUBLIC_`.
|
|
24
|
+
|
|
25
|
+
## Next.js wiring
|
|
26
|
+
|
|
27
|
+
Reexport attribution middleware:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
// middleware.ts
|
|
31
|
+
export { middleware } from "@mazyos/lp-tracker/middleware";
|
|
32
|
+
|
|
33
|
+
// Next.js requires this configuration to be a local literal.
|
|
34
|
+
export const config = {
|
|
35
|
+
matcher: [
|
|
36
|
+
"/((?!api(?:/|$)|_next(?:/|$)|static(?:/|$)|\\.well-known(?:/|$)|.*\\.[^/]+$).*)",
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Reexport the first-party collection route:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
// app/api/mazyos/collect/route.ts
|
|
45
|
+
export { GET, POST } from "@mazyos/lp-tracker/next";
|
|
46
|
+
|
|
47
|
+
// Next.js requires route configuration to be locally analyzable.
|
|
48
|
+
export const runtime = "nodejs";
|
|
49
|
+
export const dynamic = "force-dynamic";
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The package also exports ready `config`, `runtime`, and `dynamic` values for
|
|
53
|
+
inspection and non-route composition. Do not reexport those constants from a
|
|
54
|
+
Next.js file convention: Next.js 16 rejects non-local route configuration.
|
|
55
|
+
|
|
56
|
+
Mount one provider in the root layout:
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { MazyosProvider } from "@mazyos/lp-tracker";
|
|
60
|
+
|
|
61
|
+
export default function RootLayout({ children }) {
|
|
62
|
+
return (
|
|
63
|
+
<html lang="pt-BR">
|
|
64
|
+
<body>
|
|
65
|
+
<MazyosProvider consentMode="implied" pageviewPolicy="ledger">
|
|
66
|
+
{children}
|
|
67
|
+
</MazyosProvider>
|
|
68
|
+
</body>
|
|
69
|
+
</html>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The MazyOS operational profile is explicit `implied` collection with PageViews
|
|
75
|
+
in the ledger, so tracking starts on the first load without a banner callback.
|
|
76
|
+
The package keeps `required` only as a backwards-compatible library fallback.
|
|
77
|
+
Configure Meta limited data use when required:
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
<MazyosProvider
|
|
81
|
+
dataProcessingOptions={{ options: ["LDU"], country: 1, state: 1000 }}
|
|
82
|
+
/>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Events and markup
|
|
86
|
+
|
|
87
|
+
Only these browser events are exported:
|
|
88
|
+
|
|
89
|
+
- `PageView`
|
|
90
|
+
- `ViewContent`
|
|
91
|
+
- `Lead`
|
|
92
|
+
- `AddToCart`
|
|
93
|
+
- `InitiateCheckout`
|
|
94
|
+
- `CompleteRegistration`
|
|
95
|
+
- `Contact`
|
|
96
|
+
|
|
97
|
+
Use delegated markup for ordinary interactions:
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
<form data-mazyos-lead>
|
|
101
|
+
<input name="email" type="email" />
|
|
102
|
+
<button type="submit">Quero participar</button>
|
|
103
|
+
</form>
|
|
104
|
+
|
|
105
|
+
<section data-mazyos-view="Offer name" />
|
|
106
|
+
|
|
107
|
+
<a
|
|
108
|
+
data-mazyos-checkout
|
|
109
|
+
data-mazyos-gateway="hotmart"
|
|
110
|
+
href="https://pay.hotmart.com/example?offer=primary"
|
|
111
|
+
>
|
|
112
|
+
Comprar
|
|
113
|
+
</a>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The provider emits `ViewContent` when 35% of the marked element is visible or
|
|
117
|
+
after eight seconds. It emits `PageView` when the SPA pathname changes. Checkout
|
|
118
|
+
links are rewritten in place before the browser follows them; the tracker never
|
|
119
|
+
calls `preventDefault()` or opens another window.
|
|
120
|
+
|
|
121
|
+
The provider also records first-party `page_start`, heartbeat, visibility,
|
|
122
|
+
route-change and `page_exit` pulses with engagement time, interaction count and
|
|
123
|
+
maximum scroll depth. Pulses are stored in the MazyOS ledger and are never sent
|
|
124
|
+
to ad destinations as conversion events.
|
|
125
|
+
|
|
126
|
+
Use the API after a real application outcome:
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import { identify, track } from "@mazyos/lp-tracker";
|
|
130
|
+
|
|
131
|
+
track("Lead", {
|
|
132
|
+
contentName: "Lead magnet",
|
|
133
|
+
userData: { email: "person@example.com" },
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
identify({ email: "person@example.com" });
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`identify()` emits `CompleteRegistration` only when it receives PII not already
|
|
140
|
+
known by the current tracker runtime. PII is sent unhashed to the same-origin
|
|
141
|
+
collect route; hashing is a server responsibility.
|
|
142
|
+
|
|
143
|
+
## Checkout profiles
|
|
144
|
+
|
|
145
|
+
`@mazyos/lp-tracker/checkout` exports the profile registry,
|
|
146
|
+
`defineCheckoutProfile`, `resolveCheckoutProfile`, and `resolveCheckoutUrl`.
|
|
147
|
+
Resolution order is explicit `data-mazyos-gateway`, environment default,
|
|
148
|
+
checkout hostname, then `generic`.
|
|
149
|
+
|
|
150
|
+
The `generic` profile is verified for conservative `mzc` and standard UTM
|
|
151
|
+
propagation. Built-in host recognition for Kirvano, Hotmart, Kiwify, Eduzz,
|
|
152
|
+
PerfectPay, Ticto, Braip, Monetizze, Cakto, and Stripe is explicitly
|
|
153
|
+
`provisional`; those profiles do not claim undocumented provider-specific
|
|
154
|
+
parameter mapping.
|
|
155
|
+
|
|
156
|
+
Cakto (`pay.cakto.com.br`) drops query parameters it does not know, so its
|
|
157
|
+
profile carries the `mzc` token in `sck` — the free-form tracking slot Cakto
|
|
158
|
+
documents and echoes back on the order. Standard UTM parameters pass through
|
|
159
|
+
unchanged.
|
|
160
|
+
|
|
161
|
+
## Server configuration
|
|
162
|
+
|
|
163
|
+
Read validated runtime configuration with a bounded 60-second in-memory cache:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
import { getMazyosSite } from "@mazyos/lp-tracker/server";
|
|
167
|
+
|
|
168
|
+
const site = await getMazyosSite();
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The cache key contains a SHA-256 lookup digest, never the raw site secret.
|
|
172
|
+
|
|
173
|
+
## Doctor
|
|
174
|
+
|
|
175
|
+
Run all static checks and any remote checks enabled by environment variables:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
npx @mazyos/lp-tracker doctor
|
|
179
|
+
npx @mazyos/lp-tracker doctor --json
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Set `MAZYOS_COLLECT_URL` or `MAZYOS_LP_URL` to check a deployed route. The
|
|
183
|
+
command exits nonzero on any failed check.
|
|
184
|
+
|
|
185
|
+
## Troubleshooting
|
|
186
|
+
|
|
187
|
+
| Symptom | What to check |
|
|
188
|
+
|---|---|
|
|
189
|
+
| Doctor fails on `config` / `runtime` / `dynamic` | Those values must be **local literals** in the Next 16 file. Do not reexport them from the package. |
|
|
190
|
+
| `401` on forward | `MAZYOS_SITE_SECRET` is missing, expired after rotation, or leaked into `NEXT_PUBLIC_*`. |
|
|
191
|
+
| Card stays “no traffic” | The browser must hit same-origin `/api/mazyos/collect`, not the core URL. Confirm `202` in Network. |
|
|
192
|
+
| Lead does not become a person | The form needs email or phone. `mzc` never creates `customer_id`. |
|
|
193
|
+
| Checkout has no attribution | Mark the CTA with `data-mazyos-checkout`. Do not strip click IDs in the root layout. |
|
|
194
|
+
| Safari drops the cookie | HTML snippet cookies may be shortened by ITP. Use Next middleware for the configured 400-day first-party horizon. |
|
|
195
|
+
| Apex cookie missing | Set `NEXT_PUBLIC_MAZYOS_COOKIE_DOMAIN`. |
|
|
196
|
+
| Pixel and CAPI disagree | Same `event_id`. Do not add a second Meta snippet or a second `PageView`. |
|
|
197
|
+
|
|
198
|
+
Operator-facing Portuguese docs live in the backoffice:
|
|
199
|
+
`docs/integrations/landing-pages.md`. This README stays the maintainer contract.
|
|
200
|
+
|
|
201
|
+
## Delivery behavior
|
|
202
|
+
|
|
203
|
+
Failed requests use `mazyos:queue:v1`, capped at 50 entries with a 72-hour TTL.
|
|
204
|
+
Choose `local`, `session`, or `off` storage. IDs and event timestamps survive
|
|
205
|
+
retries. Cumulative offline heartbeats are coalesced, and telemetry is evicted
|
|
206
|
+
before conversion events if the queue reaches its cap. On hidden-page flush,
|
|
207
|
+
same-origin events use `sendBeacon` with `text/plain`, followed by a keepalive
|
|
208
|
+
fetch fallback.
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mazyos-lp-tracker
|
|
3
|
+
description: Install and validate @mazyos/lp-tracker in React 19 and Next.js 16 landing pages.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Instrument a MazyOS landing page
|
|
7
|
+
|
|
8
|
+
Use this skill when adding first-party MazyOS conversion tracking to a landing
|
|
9
|
+
page.
|
|
10
|
+
|
|
11
|
+
## Install the package
|
|
12
|
+
|
|
13
|
+
1. Add `@mazyos/lp-tracker` with the repository package manager.
|
|
14
|
+
2. Reexport `middleware` from `@mazyos/lp-tracker/middleware` in the project's
|
|
15
|
+
root `middleware.ts`, and copy the documented matcher into a local `config`
|
|
16
|
+
literal. Next.js rejects reexported file-convention configuration.
|
|
17
|
+
3. Reexport `POST` and `GET` from `@mazyos/lp-tracker/next` in
|
|
18
|
+
`app/api/mazyos/collect/route.ts`. Declare local literal
|
|
19
|
+
`runtime = "nodejs"` and `dynamic = "force-dynamic"` exports so Next.js can
|
|
20
|
+
statically analyze them.
|
|
21
|
+
4. Render one `MazyosProvider` around root-layout children.
|
|
22
|
+
5. Put `MAZYOS_CORE_URL` and `MAZYOS_SITE_SECRET` in server-only environment
|
|
23
|
+
configuration and document them in `.env.example`.
|
|
24
|
+
6. Never use a `NEXT_PUBLIC_*` name for a value beginning with `sk_lp_`.
|
|
25
|
+
|
|
26
|
+
## Mark interactions
|
|
27
|
+
|
|
28
|
+
- Add `data-mazyos-lead` to native lead forms. Ensure each form has an email or
|
|
29
|
+
phone field.
|
|
30
|
+
- Add `data-mazyos-view` to the primary offer content.
|
|
31
|
+
- Add `data-mazyos-checkout` to every checkout anchor or button.
|
|
32
|
+
- Add `data-mazyos-cart`, `data-mazyos-contact`, or
|
|
33
|
+
`data-mazyos-register` only at the corresponding confirmed interaction.
|
|
34
|
+
- Add `data-mazyos-gateway="slug"` only when explicit profile selection is
|
|
35
|
+
needed.
|
|
36
|
+
- Call `track("Lead")` only after actual success when no native form submit
|
|
37
|
+
exists.
|
|
38
|
+
- Call `identify()` when new PII becomes known outside a funnel event.
|
|
39
|
+
|
|
40
|
+
## Enforce the browser boundary
|
|
41
|
+
|
|
42
|
+
Use only `PageView`, `ViewContent`, `Lead`, `AddToCart`,
|
|
43
|
+
`InitiateCheckout`, `CompleteRegistration`, and `Contact`. Do not bypass the
|
|
44
|
+
types to send `Purchase`, `Subscribe`, `Refund`, or `Chargeback`.
|
|
45
|
+
|
|
46
|
+
Do not:
|
|
47
|
+
|
|
48
|
+
- hash PII in the client;
|
|
49
|
+
- add a second Meta snippet or manual `fbq` PageView;
|
|
50
|
+
- add a browser `gtag` conversion;
|
|
51
|
+
- clear attribution query parameters in the root layout;
|
|
52
|
+
- interrupt checkout navigation with `preventDefault()` or `window.open()`;
|
|
53
|
+
- invent checkout-provider parameter names.
|
|
54
|
+
|
|
55
|
+
## Use the MazyOS operational profile
|
|
56
|
+
|
|
57
|
+
Mount the provider with `consentMode="implied"` and
|
|
58
|
+
`pageviewPolicy="ledger"`. Do not gate tracker startup behind a banner or a
|
|
59
|
+
later callback. The package's `required` mode exists only for older external
|
|
60
|
+
integrations.
|
|
61
|
+
|
|
62
|
+
## Validate
|
|
63
|
+
|
|
64
|
+
Run:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npx @mazyos/lp-tracker doctor
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Use `--json` in automation. Configure `MAZYOS_COLLECT_URL` or `MAZYOS_LP_URL`
|
|
71
|
+
for deployed health checks. Treat a nonzero exit as a release blocker.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const CLICK_ID_FIELDS: readonly ["fbclid", "gclid", "gbraid", "wbraid", "ttclid"];
|
|
2
|
+
export declare const UTM_FIELDS: readonly ["utm_source", "utm_medium", "utm_campaign", "utm_content", "utm_term"];
|
|
3
|
+
export declare const ATTRIBUTION_FIELDS: readonly ["fbclid", "gclid", "gbraid", "wbraid", "ttclid", "utm_source", "utm_medium", "utm_campaign", "utm_content", "utm_term", "fbp", "fbc", "ttp"];
|
|
4
|
+
export type ClickIdField = (typeof CLICK_ID_FIELDS)[number];
|
|
5
|
+
export type UtmField = (typeof UTM_FIELDS)[number];
|
|
6
|
+
export type AttributionField = (typeof ATTRIBUTION_FIELDS)[number];
|
|
7
|
+
export declare const ATTRIBUTION_COOKIE_MAX_AGE: number;
|
|
8
|
+
export declare function firstNonEmpty(...values: ReadonlyArray<string | null | undefined>): string | undefined;
|
|
9
|
+
export declare function normalizeAttributionValue(value: string | null | undefined): string | undefined;
|
|
10
|
+
export declare function mazyosCookieName(field: string): string;
|
|
11
|
+
export declare function isUtmField(value: string): boolean;
|
|
12
|
+
export declare function queryMap(searchParams: URLSearchParams): Record<string, string[]>;
|
|
13
|
+
export declare function createFbc(clickId: string, arrivalMs: number): string;
|
|
14
|
+
export declare function googleCookieClickId(value: string | null | undefined): string | undefined;
|
|
15
|
+
export declare function isMzc(value: string | null | undefined): value is string;
|
|
16
|
+
//# sourceMappingURL=attribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribution.d.ts","sourceRoot":"","sources":["../src/attribution.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,YAC1B,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,QAAQ,CACA,CAAC;AAEX,eAAO,MAAM,UAAU,YACrB,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,aAAa,EACb,UAAU,CACF,CAAC;AAEX,eAAO,MAAM,kBAAkB,wJAMrB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAC5D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AACnD,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE,eAAO,MAAM,0BAA0B,QAAqB,CAAC;AAE7D,wBAAgB,aAAa,CAC3B,GAAG,MAAM,EAAE,aAAa,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAClD,MAAM,GAAG,SAAS,CAQpB;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,MAAM,GAAG,SAAS,CAGpB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,QAAQ,CAAC,YAAY,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAgBhF;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,MAAM,GAAG,SAAS,CASpB;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,IAAI,MAAM,CAEvE"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export const CLICK_ID_FIELDS = [
|
|
2
|
+
"fbclid",
|
|
3
|
+
"gclid",
|
|
4
|
+
"gbraid",
|
|
5
|
+
"wbraid",
|
|
6
|
+
"ttclid",
|
|
7
|
+
];
|
|
8
|
+
export const UTM_FIELDS = [
|
|
9
|
+
"utm_source",
|
|
10
|
+
"utm_medium",
|
|
11
|
+
"utm_campaign",
|
|
12
|
+
"utm_content",
|
|
13
|
+
"utm_term",
|
|
14
|
+
];
|
|
15
|
+
export const ATTRIBUTION_FIELDS = [
|
|
16
|
+
...CLICK_ID_FIELDS,
|
|
17
|
+
...UTM_FIELDS,
|
|
18
|
+
"fbp",
|
|
19
|
+
"fbc",
|
|
20
|
+
"ttp",
|
|
21
|
+
];
|
|
22
|
+
export const ATTRIBUTION_COOKIE_MAX_AGE = 60 * 60 * 24 * 400;
|
|
23
|
+
export function firstNonEmpty(...values) {
|
|
24
|
+
for (const value of values) {
|
|
25
|
+
const normalized = normalizeAttributionValue(value);
|
|
26
|
+
if (normalized) {
|
|
27
|
+
return normalized;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
export function normalizeAttributionValue(value) {
|
|
33
|
+
const trimmed = value?.trim();
|
|
34
|
+
return trimmed ? trimmed.slice(0, 512) : undefined;
|
|
35
|
+
}
|
|
36
|
+
export function mazyosCookieName(field) {
|
|
37
|
+
return `_mzy_${field}`;
|
|
38
|
+
}
|
|
39
|
+
export function isUtmField(value) {
|
|
40
|
+
return /^utm_[a-z0-9_]{1,60}$/.test(value);
|
|
41
|
+
}
|
|
42
|
+
export function queryMap(searchParams) {
|
|
43
|
+
const output = {};
|
|
44
|
+
let count = 0;
|
|
45
|
+
for (const [rawKey, rawValue] of searchParams) {
|
|
46
|
+
if (count >= 100)
|
|
47
|
+
break;
|
|
48
|
+
const key = rawKey.trim().slice(0, 128);
|
|
49
|
+
const value = normalizeAttributionValue(rawValue);
|
|
50
|
+
if (!key || !value)
|
|
51
|
+
continue;
|
|
52
|
+
const values = output[key] ?? [];
|
|
53
|
+
if (values.length < 20) {
|
|
54
|
+
values.push(value);
|
|
55
|
+
output[key] = values;
|
|
56
|
+
}
|
|
57
|
+
count += 1;
|
|
58
|
+
}
|
|
59
|
+
return output;
|
|
60
|
+
}
|
|
61
|
+
export function createFbc(clickId, arrivalMs) {
|
|
62
|
+
return `fb.1.${Math.trunc(arrivalMs)}.${clickId}`;
|
|
63
|
+
}
|
|
64
|
+
export function googleCookieClickId(value) {
|
|
65
|
+
const normalized = normalizeAttributionValue(value);
|
|
66
|
+
if (!normalized) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
const segments = normalized.split(".");
|
|
70
|
+
return segments.length >= 3
|
|
71
|
+
? normalizeAttributionValue(segments.slice(2).join("."))
|
|
72
|
+
: normalized;
|
|
73
|
+
}
|
|
74
|
+
export function isMzc(value) {
|
|
75
|
+
return typeof value === "string" && /^[A-Za-z0-9]{22}$/.test(value);
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=attribution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribution.js","sourceRoot":"","sources":["../src/attribution.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AttributionData } from "../types.js";
|
|
2
|
+
export type CheckoutProfileStatus = "provisional" | "verified";
|
|
3
|
+
export type CheckoutAttributionKey = Exclude<keyof AttributionData, "mzc" | `utm_${string}`>;
|
|
4
|
+
export interface CheckoutProfile {
|
|
5
|
+
attributionParams: Readonly<Partial<Record<CheckoutAttributionKey, string>>>;
|
|
6
|
+
hostnames: readonly string[];
|
|
7
|
+
maxUrlLength: number;
|
|
8
|
+
slug: string;
|
|
9
|
+
status: CheckoutProfileStatus;
|
|
10
|
+
tokenParam: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function defineCheckoutProfile(profile: CheckoutProfile): CheckoutProfile;
|
|
13
|
+
export declare const BUILTIN_CHECKOUT_PROFILES: readonly CheckoutProfile[];
|
|
14
|
+
export declare function registerCheckoutProfile(profile: CheckoutProfile): () => void;
|
|
15
|
+
export declare function getCheckoutProfile(slug: string): CheckoutProfile | undefined;
|
|
16
|
+
export declare function listCheckoutProfiles(): readonly CheckoutProfile[];
|
|
17
|
+
export declare function genericCheckoutProfile(): CheckoutProfile;
|
|
18
|
+
//# sourceMappingURL=profiles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.d.ts","sourceRoot":"","sources":["../../src/checkout/profiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG,UAAU,CAAC;AAC/D,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAC1C,MAAM,eAAe,EACrB,KAAK,GAAG,OAAO,MAAM,EAAE,CACxB,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,iBAAiB,EAAE,QAAQ,CACzB,OAAO,CAAC,MAAM,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC,CAChD,CAAC;IACF,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,qBAAqB,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,eAAe,GACvB,eAAe,CAsBjB;AAmCD,eAAO,MAAM,yBAAyB,EAAE,SAAS,eAAe,EAuB5D,CAAC;AAOL,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,eAAe,GACvB,MAAM,IAAI,CAWZ;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAE5E;AAED,wBAAgB,oBAAoB,IAAI,SAAS,eAAe,EAAE,CAEjE;AAED,wBAAgB,sBAAsB,IAAI,eAAe,CAExD"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export function defineCheckoutProfile(profile) {
|
|
2
|
+
if (!/^[a-z0-9_-]{2,32}$/.test(profile.slug)) {
|
|
3
|
+
throw new TypeError("Checkout profile slug must be 2-32 lowercase characters");
|
|
4
|
+
}
|
|
5
|
+
if (!isParameterName(profile.tokenParam)) {
|
|
6
|
+
throw new TypeError("Checkout token parameter is invalid");
|
|
7
|
+
}
|
|
8
|
+
if (profile.maxUrlLength < 256 || profile.maxUrlLength > 16_384) {
|
|
9
|
+
throw new TypeError("Checkout maxUrlLength must be between 256 and 16384");
|
|
10
|
+
}
|
|
11
|
+
for (const parameter of Object.values(profile.attributionParams)) {
|
|
12
|
+
if (parameter && !isParameterName(parameter)) {
|
|
13
|
+
throw new TypeError(`Invalid checkout attribution parameter: ${parameter}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return Object.freeze({
|
|
17
|
+
...profile,
|
|
18
|
+
attributionParams: Object.freeze({ ...profile.attributionParams }),
|
|
19
|
+
hostnames: Object.freeze(profile.hostnames.map((host) => host.trim().toLowerCase())),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const genericProfile = defineCheckoutProfile({
|
|
23
|
+
attributionParams: {},
|
|
24
|
+
hostnames: [],
|
|
25
|
+
maxUrlLength: 2_048,
|
|
26
|
+
slug: "generic",
|
|
27
|
+
status: "verified",
|
|
28
|
+
tokenParam: "mzc",
|
|
29
|
+
});
|
|
30
|
+
function provisional(slug, hostnames, options = {}) {
|
|
31
|
+
return defineCheckoutProfile({
|
|
32
|
+
attributionParams: {},
|
|
33
|
+
hostnames,
|
|
34
|
+
maxUrlLength: 2_048,
|
|
35
|
+
slug,
|
|
36
|
+
status: "provisional",
|
|
37
|
+
tokenParam: options.tokenParam ?? "mzc",
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export const BUILTIN_CHECKOUT_PROFILES = Object.freeze([
|
|
41
|
+
genericProfile,
|
|
42
|
+
provisional("kirvano", ["checkout.kirvano.com", "pay.kirvano.com"]),
|
|
43
|
+
provisional("hotmart", ["pay.hotmart.com"]),
|
|
44
|
+
provisional("kiwify", ["pay.kiwify.com.br"]),
|
|
45
|
+
provisional("eduzz", ["checkout.eduzz.com", "sun.eduzz.com"]),
|
|
46
|
+
provisional("perfectpay", [
|
|
47
|
+
"checkout.perfectpay.com.br",
|
|
48
|
+
"perfectpay.com.br",
|
|
49
|
+
]),
|
|
50
|
+
provisional("ticto", ["checkout.ticto.app", "pay.ticto.com.br"]),
|
|
51
|
+
provisional("braip", ["pay.braip.com"]),
|
|
52
|
+
provisional("monetizze", [
|
|
53
|
+
"app.monetizze.com.br",
|
|
54
|
+
"pay.monetizze.com.br",
|
|
55
|
+
]),
|
|
56
|
+
// Cakto discards unknown query parameters; `sck` is its documented
|
|
57
|
+
// free-form tracking slot and is echoed back on the order.
|
|
58
|
+
provisional("cakto", ["pay.cakto.com.br", "checkout.cakto.com.br"], {
|
|
59
|
+
tokenParam: "sck",
|
|
60
|
+
}),
|
|
61
|
+
provisional("stripe", ["checkout.stripe.com"]),
|
|
62
|
+
]);
|
|
63
|
+
const customProfiles = new Map();
|
|
64
|
+
const builtinsBySlug = new Map(BUILTIN_CHECKOUT_PROFILES.map((profile) => [profile.slug, profile]));
|
|
65
|
+
export function registerCheckoutProfile(profile) {
|
|
66
|
+
const defined = defineCheckoutProfile(profile);
|
|
67
|
+
if (builtinsBySlug.has(defined.slug)) {
|
|
68
|
+
throw new TypeError(`Cannot replace built-in checkout profile: ${defined.slug}`);
|
|
69
|
+
}
|
|
70
|
+
customProfiles.set(defined.slug, defined);
|
|
71
|
+
return () => {
|
|
72
|
+
if (customProfiles.get(defined.slug) === defined) {
|
|
73
|
+
customProfiles.delete(defined.slug);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export function getCheckoutProfile(slug) {
|
|
78
|
+
return customProfiles.get(slug) ?? builtinsBySlug.get(slug);
|
|
79
|
+
}
|
|
80
|
+
export function listCheckoutProfiles() {
|
|
81
|
+
return [...BUILTIN_CHECKOUT_PROFILES, ...customProfiles.values()];
|
|
82
|
+
}
|
|
83
|
+
export function genericCheckoutProfile() {
|
|
84
|
+
return genericProfile;
|
|
85
|
+
}
|
|
86
|
+
function isParameterName(value) {
|
|
87
|
+
return /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/.test(value);
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=profiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../src/checkout/profiles.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AttributionData } from "../types.js";
|
|
2
|
+
import { type CheckoutProfile } from "./profiles.js";
|
|
3
|
+
export interface ResolveCheckoutProfileOptions {
|
|
4
|
+
defaultSlug?: string | undefined;
|
|
5
|
+
explicitSlug?: string | undefined;
|
|
6
|
+
url: URL | string;
|
|
7
|
+
}
|
|
8
|
+
export interface ResolveCheckoutUrlOptions {
|
|
9
|
+
attribution: Partial<AttributionData>;
|
|
10
|
+
defaultProfile?: string | undefined;
|
|
11
|
+
explicitProfile?: string | undefined;
|
|
12
|
+
maxLength?: number | undefined;
|
|
13
|
+
}
|
|
14
|
+
export declare function resolveCheckoutProfile(options: ResolveCheckoutProfileOptions): CheckoutProfile;
|
|
15
|
+
export declare function resolveCheckoutUrl(input: URL | string, options: ResolveCheckoutUrlOptions): string;
|
|
16
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/checkout/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AAqBvB,MAAM,WAAW,6BAA6B;IAC5C,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,GAAG,EAAE,GAAG,GAAG,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IACtC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,6BAA6B,GACrC,eAAe,CA2BjB;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,GAAG,GAAG,MAAM,EACnB,OAAO,EAAE,yBAAyB,GACjC,MAAM,CAgCR"}
|