@crelora/mark 0.0.16
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/LICENSE +26 -0
- package/README.md +210 -0
- package/dist/browser.es.js +517 -0
- package/dist/browser.umd.js +1 -0
- package/dist/node.cjs +1 -0
- package/dist/node.es.js +236 -0
- package/dist/types/browser/BrowserStorage.d.ts +32 -0
- package/dist/types/browser/Mark.d.ts +28 -0
- package/dist/types/browser/index.d.ts +3 -0
- package/dist/types/browser/urlAttribution.d.ts +6 -0
- package/dist/types/core/HttpTransport.d.ts +11 -0
- package/dist/types/core/MarkCore.d.ts +26 -0
- package/dist/types/core/adapters.d.ts +18 -0
- package/dist/types/core/constants.d.ts +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/node/StatelessStorage.d.ts +17 -0
- package/dist/types/node/index.d.ts +25 -0
- package/dist/types/types.d.ts +157 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Crelora Mark SDK License
|
|
2
|
+
Copyright (c) 2025 Crelora. All rights reserved.
|
|
3
|
+
|
|
4
|
+
This software, documentation, and any accompanying materials (collectively, the “Software”)
|
|
5
|
+
are proprietary and confidential to Crelora. Crelora grants you a limited, non-exclusive,
|
|
6
|
+
non-transferable, revocable license to install and use the Software solely to integrate with
|
|
7
|
+
the Mark platform as part of your active customer or evaluation agreement with Crelora.
|
|
8
|
+
|
|
9
|
+
You may not (and may not permit any third party to):
|
|
10
|
+
1. Copy, modify, reverse engineer, decompile, disassemble, or create derivative works of the Software
|
|
11
|
+
except to the extent such restrictions are prohibited by applicable law.
|
|
12
|
+
2. Distribute, sublicense, rent, lease, loan, or otherwise transfer the Software to any third party.
|
|
13
|
+
3. Use the Software for any purpose other than interacting with Crelora services that you are
|
|
14
|
+
expressly authorized to access.
|
|
15
|
+
|
|
16
|
+
ALL WARRANTIES, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
|
17
|
+
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT,
|
|
18
|
+
ARE DISCLAIMED TO THE MAXIMUM EXTENT PERMITTED BY LAW. IN NO EVENT WILL CRELORA OR ITS SUPPLIERS
|
|
19
|
+
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
20
|
+
ARISING IN ANY WAY OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF ADVISED OF THE
|
|
21
|
+
POSSIBILITY OF SUCH DAMAGES.
|
|
22
|
+
|
|
23
|
+
The Software is provided “AS IS.” All rights not expressly granted here are reserved by Crelora.
|
|
24
|
+
For licensing questions, contact legal@crelora.com.
|
|
25
|
+
|
|
26
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# Crelora Mark SDK
|
|
2
|
+
|
|
3
|
+
Mark is Crelora's lightweight attribution SDK for capturing user journeys, conversions, and consent across browsers and server-side runtimes. The npm package includes both browser and Node entry points so you can send consistent data from any surface.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @crelora/mark
|
|
9
|
+
# or
|
|
10
|
+
yarn add @crelora/mark
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Runtime Imports
|
|
14
|
+
|
|
15
|
+
- Browser runtime: `import { Mark } from '@crelora/mark'`
|
|
16
|
+
- Node runtime: `import { createNodeMark } from '@crelora/mark/node'`
|
|
17
|
+
|
|
18
|
+
## CDN / Script Tag Usage
|
|
19
|
+
|
|
20
|
+
You can also drop the SDK directly into your browser applications via a script tag. This exposes the global `window.Mark` object.
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<!-- Use a CDN like unpkg or jsdelivr -->
|
|
24
|
+
<script src="https://unpkg.com/@crelora/mark@latest/dist/browser.umd.js"></script>
|
|
25
|
+
|
|
26
|
+
<script>
|
|
27
|
+
// Mark is available globally
|
|
28
|
+
Mark.init({
|
|
29
|
+
key: 'pk_xxxxx',
|
|
30
|
+
// ... configuration
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
Mark.track('Page View');
|
|
34
|
+
</script>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Browser Quickstart
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { Mark } from '@crelora/mark';
|
|
41
|
+
|
|
42
|
+
Mark.init({
|
|
43
|
+
key: 'pk_xxxxx',
|
|
44
|
+
require_consent: 'auto',
|
|
45
|
+
cross_domain: { cookie_domain: '.example.com' },
|
|
46
|
+
site_id: 'uuid-...', // Optional: associate events with a registered site
|
|
47
|
+
site_host: 'shop.example.com', // Optional: site host for audit/debug
|
|
48
|
+
autocapture: { pageview: true }, // Optional: auto-emit page_view on load and SPA route changes
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
Mark.identify('user_123', {
|
|
52
|
+
email: 'customer@example.com',
|
|
53
|
+
display_name: 'John Doe',
|
|
54
|
+
language: 'en-US'
|
|
55
|
+
});
|
|
56
|
+
Mark.track('Checkout Started', { value: 12900, currency: 'usd' });
|
|
57
|
+
Mark.setConsent('granted');
|
|
58
|
+
|
|
59
|
+
// Per-event site overrides (optional)
|
|
60
|
+
Mark.track('Conversion', {
|
|
61
|
+
site_id: 'different-site-uuid', // Overrides init config for this event
|
|
62
|
+
site_host: 'other.example.com',
|
|
63
|
+
value: 5000,
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`Mark.init` should be called once during app bootstrap. Subsequent calls to `track`, `identify`, or `setConsent` reuse the same client instance.
|
|
68
|
+
|
|
69
|
+
## Node / Server Usage
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { createNodeMark } from '@crelora/mark/node';
|
|
73
|
+
|
|
74
|
+
const mark = createNodeMark({
|
|
75
|
+
key: process.env.MARK_SECRET_KEY!,
|
|
76
|
+
site_id: process.env.MARK_SITE_ID, // Optional: associate events with a registered site
|
|
77
|
+
site_host: process.env.MARK_SITE_HOST, // Optional: site host for audit/debug
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
mark.track('Server Conversion', {
|
|
81
|
+
visitor_id: 'vis_abc',
|
|
82
|
+
order_id: 'ord_789',
|
|
83
|
+
value: 19900,
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The Node factory accepts optional custom storage or transport adapters so you can plug the SDK into queues or serverless environments.
|
|
88
|
+
|
|
89
|
+
## Available Methods
|
|
90
|
+
|
|
91
|
+
- `Mark.init(config)` / `createNodeMark(config)` – bootstraps the client with your publishable or secret key.
|
|
92
|
+
- `track(eventName, payload?)` – records custom events with arbitrary properties (numbers, strings, arrays, objects). Use `site_id` and `site_host` for per-event site overrides.
|
|
93
|
+
- `conversion(eventName, payload?)` – records conversion events. Currently behaves like `track` but tags the event with `is_conversion: true`.
|
|
94
|
+
- `identify(userId, traits?)` – ties a known user identifier to previous anonymous activity. Recommended traits: `email`, `display_name`, `language`. Custom traits are also supported.
|
|
95
|
+
- `setConsent(status)` – enforces consent gating; pass `'granted'` or `'denied'`.
|
|
96
|
+
- `getVisitorId()` – returns the current pseudonymous visitor ID when available. On the browser, returns `undefined` until consent is granted when `require_consent` is set. Use it to send the ID to your backend (e.g. in a header or body) for server-side attribution when you don't have an authenticated user ID.
|
|
97
|
+
|
|
98
|
+
Reserved SDK fields (for example `event_name`, `user_id`, `consent_state`, and internal identity metadata) are sanitized from user payloads/traits and cannot override SDK-managed values.
|
|
99
|
+
|
|
100
|
+
## Automatic Attribution Tracking
|
|
101
|
+
|
|
102
|
+
The SDK automatically captures and persists the following URL parameters:
|
|
103
|
+
- UTM keys: `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content`
|
|
104
|
+
- Referral aliases: `ref`, `referral`, `affiliate_id` (normalized to `ref`)
|
|
105
|
+
- Generic IDs: `click_id`, `ch_click_id`, `cid`, `campaign_id`
|
|
106
|
+
- Paid platform IDs: `gclid`, `gbraid`, `wbraid`, `dclid`, `msclkid`, `fbclid`, `ttclid`, `twclid`, `li_fat_id`
|
|
107
|
+
|
|
108
|
+
These parameters are included in every tracked event to ensure proper attribution.
|
|
109
|
+
|
|
110
|
+
Capture is evaluated at SDK initialization and refreshed before each auto page view emit when `autocapture.pageview` + route tracking are enabled.
|
|
111
|
+
- If consent is not yet granted (`require_consent: true` or `'auto'`), attribution is kept in runtime memory and not persisted.
|
|
112
|
+
- After consent is granted, pending in-memory attribution and current URL attribution are persisted.
|
|
113
|
+
|
|
114
|
+
### Custom Query Param Capture
|
|
115
|
+
|
|
116
|
+
You can expand the default attribution allowlist or opt into full query capture:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
Mark.init({
|
|
120
|
+
key: 'pk_xxxxx',
|
|
121
|
+
capture_query_params: ['sub_id1', 'sub_id2', 'publisher_code'],
|
|
122
|
+
// Optional:
|
|
123
|
+
// capture_all_query_params: true,
|
|
124
|
+
// query_param_denylist: ['email', 'token', 'auth'],
|
|
125
|
+
// max_captured_query_params: 30,
|
|
126
|
+
// max_query_param_value_length: 256,
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Configuration Reference
|
|
131
|
+
|
|
132
|
+
All config options use snake_case. Stored event payloads and database columns match 1:1.
|
|
133
|
+
|
|
134
|
+
| Option | Type | Description |
|
|
135
|
+
| --- | --- | --- |
|
|
136
|
+
| `key` | `string` | Publishable (browser) or secret (server) key issued in the Crelora dashboard. |
|
|
137
|
+
| `debug` | `boolean` | Enables verbose console logging to help with integration tests. |
|
|
138
|
+
| `require_consent` | `boolean \| 'auto'` | `true` blocks tracking until consent is granted, `'auto'` requires stored granted consent and treats missing consent as denied, default `false` (`'auto'` recommended for production). |
|
|
139
|
+
| `autocapture` | `{ pageview?: boolean }` | When `pageview: true`, automatically sends `page_view` on init and SPA route changes. If consent is required, the first `page_view` is sent as soon as consent becomes granted. |
|
|
140
|
+
| `track_route_changes` | `boolean` | When `autocapture.pageview` is true, also emits on SPA route changes (pushState/replaceState/popstate); defaults to `true`. |
|
|
141
|
+
| `include_page_context` | `boolean` | When true (default), enriches events with `page`, `title`, `referrer`, `site` (full `url` is only sent if you pass it explicitly in payload). |
|
|
142
|
+
| `cross_domain` | `CrossDomainConfig` | Controls cookie domain, bridge URL, and allowlist for multi-domain attribution. |
|
|
143
|
+
| `site_id` | `string` | Optional UUID for associating events with a registered site. Included in all event payloads as `site_id`. |
|
|
144
|
+
| `site_host` | `string` | Optional site host for audit/debug purposes. Included in all event payloads as `site_host`. If not provided, browser SDK uses `window.location.host`. |
|
|
145
|
+
| `capture_query_params` | `string[]` | Additional query keys to capture for attribution (merged into the default allowlist). |
|
|
146
|
+
| `capture_all_query_params` | `boolean` | Capture all query params after denylist/limits. Defaults to `false`. |
|
|
147
|
+
| `query_param_denylist` | `string[]` | Query keys that are never captured (exact-key matching; default includes sensitive keys like `email`, `token`, `password`). |
|
|
148
|
+
| `max_captured_query_params` | `number` | Maximum number of captured query keys stored per visitor (default `30`). |
|
|
149
|
+
| `max_query_param_value_length` | `number` | Maximum stored length per captured query value (default `256`). |
|
|
150
|
+
|
|
151
|
+
Server runtimes can also pass `storage`, `storageDefaults`, or `transport` via `createNodeMark` to fully control persistence and delivery.
|
|
152
|
+
|
|
153
|
+
## Consent & Privacy
|
|
154
|
+
|
|
155
|
+
- Call `setConsent('denied')` to immediately halt tracking when visitors opt out.
|
|
156
|
+
- Use `require_consent: true` (or `'auto'`) to make the SDK wait until a positive consent signal is received.
|
|
157
|
+
- In `'auto'` mode, missing consent is treated as denied until consent is explicitly granted.
|
|
158
|
+
- Event payloads cannot bypass consent checks.
|
|
159
|
+
- Attribution parameters are not persisted pre-consent; they are held in runtime memory until consent is granted.
|
|
160
|
+
- Cross-domain mode supports first-party iframe bridges so identifiers remain in your control.
|
|
161
|
+
- IP/Geo: IP is never taken from the browser; it is captured server-side, hashed, and used to derive coarse geo (country/region/city, coarse lat/lon) when allowed by consent/tenant settings.
|
|
162
|
+
|
|
163
|
+
## Visitor ID for server attribution
|
|
164
|
+
|
|
165
|
+
When you don't have an authenticated user ID, you can pass the SDK's visitor ID to your backend so server-side events (e.g. checkout, webhooks) are attributed to the same visitor as browser events.
|
|
166
|
+
|
|
167
|
+
**Browser:** Call `Mark.getVisitorId()` after init. If you use `require_consent: true` or `'auto'`, it returns `undefined` until consent is granted. Once available, send it in a header or request body to your API and use it as the `visitor_id` when calling the Node SDK or your ingestion.
|
|
168
|
+
|
|
169
|
+
**Node:** Call `mark.getVisitorId()` to read the visitor ID from the storage you passed to `createNodeMark` (e.g. from `storageDefaults.visitor_id`). Use it to associate server events with the same visitor.
|
|
170
|
+
|
|
171
|
+
The visitor ID is a pseudonymous, SDK-scoped identifier. Do not use it as a cross-site or long-term user identity; use it only for joining browser and server events within your attribution flow.
|
|
172
|
+
|
|
173
|
+
## User Identification
|
|
174
|
+
|
|
175
|
+
The `identify()` method links anonymous visitors to known users. Recommended traits:
|
|
176
|
+
|
|
177
|
+
- **`email`** (string) - User's email address. Will be hashed server-side for privacy.
|
|
178
|
+
- **`display_name`** (string) - User's display name or full name.
|
|
179
|
+
- **`language`** (string) - User's preferred language code (e.g., `'en'`, `'en-US'`, `'fr'`).
|
|
180
|
+
- **`phone`** (string) - User's phone number. Will be hashed server-side for privacy.
|
|
181
|
+
|
|
182
|
+
You can also include any custom traits as key-value pairs. All traits are stored in the user profile and can be used for segmentation and personalization.
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
Mark.identify('user_123', {
|
|
186
|
+
email: 'customer@example.com',
|
|
187
|
+
display_name: 'John Doe',
|
|
188
|
+
language: 'en-US',
|
|
189
|
+
plan: 'premium',
|
|
190
|
+
signup_date: '2024-01-15',
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Page Views
|
|
195
|
+
- Event name: `page_view` (canonical). Use display names in your product UI if you prefer human-readable labels.
|
|
196
|
+
- Autocapture (optional): set `autocapture: { pageview: true }` (and optionally `track_route_changes: true`) to emit on first load and SPA route changes. If consent is required and not yet granted, initial pageview is deferred and emitted once consent is granted.
|
|
197
|
+
- All SDK config and event fields use snake_case (`site_id`, `site_host`, etc.) and map directly to stored payloads and database columns.
|
|
198
|
+
|
|
199
|
+
## Breaking changes (snake_case API)
|
|
200
|
+
|
|
201
|
+
The SDK uses snake_case for all config options and reserved event fields, aligning with analytics ecosystem conventions (e.g. GA4, Mixpanel). If migrating from an older version:
|
|
202
|
+
|
|
203
|
+
- Config: `requireConsent` → `require_consent`, `autoPageview` → `autocapture: { pageview: true }`, `trackRouteChanges` → `track_route_changes`, `includePageContext` → `include_page_context`, `siteId`/`siteHost` → `site_id`/`site_host`, `crossDomain` → `cross_domain`, etc.
|
|
204
|
+
- Track payload: use `site_id` and `site_host` for per-event overrides.
|
|
205
|
+
- Node `storageDefaults`: use `visitor_id`, `last_click_id`, `campaign_id`, `query_params`, `consent_status`.
|
|
206
|
+
|
|
207
|
+
## Support
|
|
208
|
+
|
|
209
|
+
Need help? Reach out through your Crelora account team or file a ticket via the dashboard. Please include the SDK version, runtime (browser or Node), and any reproduction steps so we can assist quickly.
|
|
210
|
+
|