
Security News
Insecure Agents Podcast: How to Keep AI Agents From Bypassing Security Controls
Socket CTO Ahmad Nassri discusses how to keep AI agents from bypassing package blocks, limit credential access, and monitor their actions.
@crelora/mark
Advanced tools
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.
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.
npm install @crelora/mark
# or
yarn add @crelora/mark
import { Mark } from '@crelora/mark'import { createNodeMark } from '@crelora/mark/node'You can also drop the SDK directly into your browser applications via a script tag. This exposes the global window.Mark object.
<!-- Use a CDN like unpkg or jsdelivr -->
<script src="https://unpkg.com/@crelora/mark@latest/dist/browser.umd.js"></script>
<script>
// Mark is available globally
Mark.init({
key: 'pk_xxxxx',
// ... configuration
});
Mark.track('Page View');
</script>
import { Mark } from '@crelora/mark';
Mark.init({
key: 'pk_xxxxx',
require_consent: 'auto',
cross_domain: { cookie_domain: '.example.com' },
site_id: 'uuid-...', // Optional: associate events with a registered site
site_host: 'shop.example.com', // Optional: site host for audit/debug
autocapture: { pageview: true }, // Optional: auto-emit page_view on load and SPA route changes
});
Mark.identify('user_123', {
email: 'customer@example.com',
display_name: 'John Doe',
language: 'en-US'
});
Mark.track('Checkout Started', { value: 12900, currency: 'usd' });
Mark.setConsent('granted');
// Per-event site overrides (optional)
Mark.track('Conversion', {
site_id: 'different-site-uuid', // Overrides init config for this event
site_host: 'other.example.com',
value: 5000,
});
Mark.init should be called once during app bootstrap. Subsequent calls to track, identify, or setConsent reuse the same client instance.
import { createNodeMark } from '@crelora/mark/node';
const mark = createNodeMark({
key: process.env.MARK_SECRET_KEY!,
site_id: process.env.MARK_SITE_ID, // Optional: associate events with a registered site
site_host: process.env.MARK_SITE_HOST, // Optional: site host for audit/debug
});
mark.track('Server Conversion', {
visitor_id: 'vis_abc',
order_id: 'ord_789',
value: 19900,
});
The Node factory accepts optional custom storage or transport adapters so you can plug the SDK into queues or serverless environments.
Mark.init(config) / createNodeMark(config) – bootstraps the client with your publishable or secret key.track(eventName, payload?) – records custom events with arbitrary properties (numbers, strings, arrays, objects). Use site_id and site_host for per-event site overrides.conversion(eventName, payload?) – records conversion events. Currently behaves like track but tags the event with is_conversion: true.identify(userId, traits?) – ties a known user identifier to previous anonymous activity. Recommended traits: email, display_name, language. Custom traits are also supported.setConsent(status) – enforces consent gating; pass 'granted' or 'denied'.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.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.
The SDK automatically captures and persists the following URL parameters:
utm_source, utm_medium, utm_campaign, utm_term, utm_contentref, referral, affiliate_id (normalized to ref)click_id, ch_click_id, cid, campaign_idgclid, gbraid, wbraid, dclid, msclkid, fbclid, ttclid, twclid, li_fat_idThese parameters are included in every tracked event to ensure proper attribution.
Capture is evaluated at SDK initialization and refreshed before each auto page view emit when autocapture.pageview + route tracking are enabled.
require_consent: true or 'auto'), attribution is kept in runtime memory and not persisted.You can expand the default attribution allowlist or opt into full query capture:
Mark.init({
key: 'pk_xxxxx',
capture_query_params: ['sub_id1', 'sub_id2', 'publisher_code'],
// Optional:
// capture_all_query_params: true,
// query_param_denylist: ['email', 'token', 'auth'],
// max_captured_query_params: 30,
// max_query_param_value_length: 256,
});
All config options use snake_case. Stored event payloads and database columns match 1:1.
| Option | Type | Description |
|---|---|---|
key | string | Publishable (browser) or secret (server) key issued in the Crelora dashboard. |
debug | boolean | Enables verbose console logging to help with integration tests. |
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). |
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. |
track_route_changes | boolean | When autocapture.pageview is true, also emits on SPA route changes (pushState/replaceState/popstate); defaults to true. |
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). |
cross_domain | CrossDomainConfig | Controls cookie domain, bridge URL, and allowlist for multi-domain attribution. |
site_id | string | Optional UUID for associating events with a registered site. Included in all event payloads as site_id. |
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. |
capture_query_params | string[] | Additional query keys to capture for attribution (merged into the default allowlist). |
capture_all_query_params | boolean | Capture all query params after denylist/limits. Defaults to false. |
query_param_denylist | string[] | Query keys that are never captured (exact-key matching; default includes sensitive keys like email, token, password). |
max_captured_query_params | number | Maximum number of captured query keys stored per visitor (default 30). |
max_query_param_value_length | number | Maximum stored length per captured query value (default 256). |
Server runtimes can also pass storage, storageDefaults, or transport via createNodeMark to fully control persistence and delivery.
setConsent('denied') to immediately halt tracking when visitors opt out.require_consent: true (or 'auto') to make the SDK wait until a positive consent signal is received.'auto' mode, missing consent is treated as denied until consent is explicitly granted.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.
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.
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.
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.
The identify() method links anonymous visitors to known users. Recommended traits:
email (string) - User's email address. Will be hashed server-side for privacy.display_name (string) - User's display name or full name.language (string) - User's preferred language code (e.g., 'en', 'en-US', 'fr').phone (string) - User's phone number. Will be hashed server-side for privacy.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.
Mark.identify('user_123', {
email: 'customer@example.com',
display_name: 'John Doe',
language: 'en-US',
plan: 'premium',
signup_date: '2024-01-15',
});
page_view (canonical). Use display names in your product UI if you prefer human-readable labels.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.site_id, site_host, etc.) and map directly to stored payloads and database columns.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.
FAQs
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.
The npm package @crelora/mark receives a total of 68 weekly downloads. As such, @crelora/mark popularity was classified as not popular.
We found that @crelora/mark demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.

Security News
Socket CTO Ahmad Nassri discusses how to keep AI agents from bypassing package blocks, limit credential access, and monitor their actions.

Security News
GPT-6 Astra tried to plant malicious code in simulated open source projects using fake GitHub accounts and deceptive PRs during an assigned CTF challenge.

Security News
upm uses Node.js to deliver fast npm installs in about 250 KB, with a JavaScript API and security defaults.