@xsolla/metrika
Version:
A lightweight integration library for Xsolla Metrics (XMTS) that simplifies user tracking and analytics setup.
413 lines (325 loc) • 21.2 kB
Markdown
# Xsolla Metrika
[](https://www.npmjs.com/package/@xsolla/metrika)
[](LICENSE)
[](https://bundlephobia.com/result?p=@xsolla/metrika)
[](https://www.npmjs.com/package/@xsolla/metrika)
A lightweight integration library for Xsolla Metrics (XMTS) that simplifies user tracking and analytics setup.
Supports SPA and classic sites, works in all modern browsers, and provides full TypeScript support.
---
## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [npm / yarn](#npm--yarn)
- [CDN (jsDelivr / unpkg)](#cdn-jsdelivr--unpkg)
- [Usage](#usage)
- [ESM](#esm)
- [CommonJS](#commonjs)
- [IIFE](#iife)
- [IIFE (BOOTSTRAP)](#iife-bootstrap)
- [Configuration](#configuration)
- [Parameters Table](#parameters-table)
- [Sending data](#sending-data)
- [API Reference](#api-reference)
- [Instance Methods](#instance-methods)
- [Trackers](#trackers)
- [What Data Is Sent](#what-data-is-sent)
- [TypeScript Support](#typescript-support)
- [Migration from v1](#migration-from-v1)
- [Browser Support](#browser-support)
- [License](#license)
---
## Features
- 📦 **Tiny**: Minimal bundle size, no heavy dependencies.
- 🧑💻 **TypeScript-first**: Full type definitions out of the box.
- ⚡ **SPA-ready**: Tracks navigation in React, Vue, Angular, etc.
- 🖱️ **Auto-tracking**: Clicks, scrolls, external links, performance, and more.
- 🧬 **Device fingerprinting**.
- 🌍 **Flexible delivery**: Works with `sendBeacon` and `fetch`.
- 🔌 **Custom events**: Send any data, integrate with A/B tests, etc.
---
## Installation
### Bundles
Xsolla Metrika provides several bundle formats for different use cases:
| Format | File | Best For |
| ------ | -------------------------------------- | -------------------------------------------------------------------------- |
| IIFE | `dist/xsolla-metrika.js` | Direct `<script>` inclusion in browsers |
| IIFE | `dist/xsolla-metrika.min.js` | Minified version for browser usage |
| IIFE | `dist/xsolla-metrika.bootstrap.js` | Auto-initialization via `<script data-*>`, available as `window.analytics` |
| IIFE | `dist/xsolla-metrika.bootstrap.min.js` | Minified version of the auto-initialization bundle |
| CJS | `dist/xsolla-metrika.cjs.cjs` | Node.js/CommonJS (`require`) |
| ESM | `dist/xsolla-metrika.esm.js` | Modern bundlers and ESM imports (`import`) |
| Types | `dist/xsolla-metrika.d.ts` | TypeScript type definitions |
### npm / yarn
```bash
npm install @xsolla/metrika
# or
yarn add @xsolla/metrika
```
### CDN (jsDelivr / unpkg)
```html
<!-- jsDelivr (IIFE) -->
<script src="https://cdn.jsdelivr.net/npm/@xsolla/metrika@2"></script>
<!-- unpkg (IIFE) -->
<script src="https://unpkg.com/@xsolla/metrika@2"></script>
```
> **Note:** The `@2` version range automatically resolves to the latest `2.x.x` release. This is the recommended approach for production — semver guarantees backward compatibility within a major version.
---
## Usage
### ESM
```ts
import XsollaAnalytics from '@xsolla/metrika';
(async () => {
const analytics = await XsollaAnalytics.init({
id: 'YOUR_COUNTER_ID',
hit: true,
navigation: true,
// ...other options
});
analytics.hit(window.location.href);
analytics.elementClick('my-button');
})();
```
### CommonJS
```js
const XsollaAnalytics = require('@xsolla/metrika').default;
XsollaAnalytics.init({ id: 'YOUR_COUNTER_ID', hit: true }).then((analytics) => {
analytics.hit(window.location.href);
});
```
### IIFE
```html
<script src="https://cdn.jsdelivr.net/npm/@xsolla/metrika@2"></script>
<script>
window.XsollaAnalytics.init({
id: 'YOUR_COUNTER_ID',
hit: true,
navigation: true,
}).then(function (analytics) {
analytics.hit(window.location.href);
});
</script>
```
### IIFE (BOOTSTRAP)
A special **bootstrap IIFE** bundle: `dist/xsolla-metrika.bootstrap.js` and its minified version `dist/xsolla-metrika.bootstrap.min.js`.
This bundle allows you to specify configuration parameters directly via data-attributes on the `<script>` tag. The analytics instance is then automatically created and becomes available as `window.analytics`.
```html
<script
src="https://cdn.jsdelivr.net/npm/@xsolla/metrika@2/dist/xsolla-metrika.bootstrap.min.js"
data-id="123456"
data-hit="true"
data-click="true"
data-ext-link="true"
data-site-domains='["example.com","sub.example.com"]'
></script>
```
> **Note:**
- All parameters must be specified in kebab-case format.
- All values that require parsing (such as arrays or objects) must be enclosed in single quotes.
---
## Configuration
### Parameters Table
| Name | Type | Default | Description |
| --------------------- | ------------------------------------------- | ---------------------------------- | ----------------------------------------------------- |
| `id` | `string \| number` | **required** | Counter ID (unique for your project) |
| `hit` | `boolean` | `false` | Track page load (pageview) |
| `extLink` | `boolean` | `false` | Track external links (outside `siteDomains`) |
| `click` | `boolean` | `false` | Track clicks on elements with `data-analytics="true"` |
| `scroll` | `boolean` | `false` | Track scroll depth (10%, 50%, 90%) |
| `crossDomainTracking` | `boolean` | `false` | Track transitions to allowed domains (`siteDomains`) |
| `sendLoadMetrics` | `boolean` | `false` | Send performance metrics (LCP, TTFB, etc.) |
| `navigation` | `boolean` | `false` | Track navigation events (SPA support) |
| `siteDomains` | `string[]` | `[location.host]` | List of internal domains for link tracking |
| `server` | `string` | `'https://minimetrika.xsolla.com'` | Analytics server base URL |
| `hitEndpoint` | `string` | `'hit'` | Endpoint for pageview events |
| `externalId` | `number` | `undefined` | External user ID |
| `merchantId` | `number` | `undefined` | Merchant ID |
| `extraValues` | `Record<string, unknown>` | `{}` | Additional custom parameters |
| `abParams` | `Record<string, unknown>` | `{}` | A/B test parameters |
| `useBeacon` | `boolean` | `true` | Use `sendBeacon` API for sending data |
| `retryOptions` | `{ retries?: number, retryDelay?: number }` | `{ retries: 2, retryDelay: 500 }` | Options for retrying failed fetch requests |
| `ip` | `string` | `undefined` | User IP (for override, optional) |
---
## Sending Data
By default, Xsolla Metrika sends all events using [sendBeacon](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon) for maximum reliability (especially during page unload).
- **Global setting:**
If you want to use regular `fetch` instead of `sendBeacon` for manual methods (`hit`, `externalLink`, `elementClick`, etc.), set the `useBeacon: false` parameter during initialization:
```js
XsollaAnalytics.init({
id: 'YOUR_COUNTER_ID',
useBeacon: false,
// ...
});
```
- **Important:**
Automatic trackers (such as auto pageview, click, scroll tracking, etc.) always use `sendBeacon` regardless of the global parameter.
- **Override per event:**
In any manual method (`hit`, `externalLink`, `elementClick`, etc.), you can explicitly specify the sending method using the `useBeacon` option:
```js
analytics.hit(window.location.href, {}, false); // sends via fetch
analytics.hit(window.location.href, {}, true); // sends via sendBeacon
```
- **Retries with fetch:**
If `sendBeacon` is not available or fails, or if you explicitly use `fetch` for sending, the library will automatically retry the request up to **two additional times** (total of 3 attempts) in case of network errors or server errors.
- **Customizing retries:**
You can control the number of retry attempts and delay between them using the `retryOptions` parameter during initialization:
```js
XsollaAnalytics.init({
id: 'YOUR_COUNTER_ID',
retryOptions: {
retries: 5, // Number of retry attempts (default: 2)
retryDelay: 1000, // Delay between retries in ms (default: 500)
},
});
```
If `retryOptions` is not specified, the default is 2 retries with a 500ms delay.
This allows you to flexibly control how events are sent depending on your needs.
---
## API Reference
### Instance Methods
| Method | Arguments | Returns | Description |
| ----------------------- | ---------------------------------------------------------------------------- | --------------------- | ----------------------------------------------- |
| `hit` | `url: string, data?: object, useBeacon?: boolean` | `Promise<boolean>` | Send a pageview event |
| `externalLink` | `url: string, data?: object, useBeacon?: boolean` | `Promise<boolean>` | Track an external link click |
| `elementClick` | `name: string, data?: object, useBeacon?: boolean` | `Promise<boolean>` | Track a named element click |
| `formData` | `name: string, form: object \| FormData, data?: object, useBeacon?: boolean` | `Promise<boolean>` | Track form submission |
| `customEvent` | `name: string, data?: object, useBeacon?: boolean` | `Promise<boolean>` | Send a custom named event |
| `sendCustomData` | `endpoint: string, data: object, useBeacon?: boolean` | `Promise<boolean>` | Send arbitrary data to a custom analytics route |
| `payStationUserSession` | `data: object, useBeacon?: boolean` | `Promise<boolean>` | Track Pay Station user session |
| `eventForLCP` | `useBeacon?: boolean` | `Promise<boolean>` | Send Largest Contentful Paint event |
| `setAbParams` | `abParams: object` | `void` | Update A/B test parameters |
| `setExtraValues` | `extraValues: object` | `void` | Update extra values |
| `getClientId` | none | `string` | Get the current client ID |
| `getVisitorId` | none | `string` | Get the current visitor ID |
| `getFingerprintHash` | none | `string \| undefined` | Get device fingerprint hash |
| `getFingerprintData` | none | `object \| undefined` | Get raw device fingerprint data |
| `destroy` | none | `void` | Unsubscribe all trackers and clean up resources |
> **Note:** When sending data using any method (`hit`, `externalLink`, `elementClick`, `formData`, `customEvent`, etc.), you can temporarily extend the global `extraValues` or `abParams` by passing them in the data object:
```ts
analytics.hit(window.location.href, {
exv: { extraKey_1: 'extraValue_1', extraKey_2: 'extraValue_2' },
abParams: { abKey_1: 'abValue_1', abKey_2: 'abValue_2' },
});
```
Values passed this way will be added only to the current event and will not modify the global parameters set during initialization.
#### Example
```ts
analytics.hit(window.location.href);
analytics.externalLink('https://external.com');
analytics.elementClick('my-button');
analytics.formData('signup', { email: 'test@example.com' });
analytics.customEvent('my-event', { foo: 1 });
analytics.setAbParams({ experiment: 'A' });
analytics.destroy();
```
---
## List of Event Types
| Type (et) | Symbolic Name | Where Used / How to Enable | Description |
| ------------------------ | ------------------------ | ------------------------------------- | ------------------------------------------------------------ |
| 1 | HIT | PageLoadTracker, NavigationTracker | Page view (pageview), SPA navigation |
| 2 | EXTERNAL_LINK | ExternalLinkTracker, `externalLink()` | Click on an external link (not from `siteDomains`) |
| 3 | ELEMENT_CLICK | ClickTracker, `elementClick()` | Click on element with `data-analytics="true"` or manual call |
| 4 | FORM_DATA | `formData()` | Form submission |
| 5 | CUSTOM_EVENT | `customEvent()` | Custom user event |
| 6 | LCP | PerformanceTracker, `eventForLCP()` | Largest Contentful Paint metric |
| 10 | SCROLL_TOP | ScrollTracker | Scroll to 10% of the page |
| 11 | SCROLL_MIDDLE | ScrollTracker | Scroll to 50% of the page |
| 12 | SCROLL_BOTTOM | ScrollTracker | Scroll to 90% of the page |
| paystation-user-sessions | paystation-user-sessions | `payStationUserSession()` | PayStation user session event |
See [docs/event-types.md](docs/event-types.md) for details.
---
## Trackers
Xsolla Metrika includes several built-in trackers. Enable them via config flags:
| Tracker | Flag | Description |
| ------------------- | --------------------- | -------------------------------------------------------------------------------------------------- |
| PageLoadTracker | `hit` | Tracks page load (pageview) |
| ClickTracker | `click` | Tracks clicks on `[data-analytics="true"]` elements |
| ExternalLinkTracker | `extLink` | Tracks clicks on external links |
| ScrollTracker | `scroll` | Tracks scroll depth (10%, 50%, 90%) |
| CrossDomainTracker | `crossDomainTracking` | Appends xsollauid and visitorId to links and forms to allowed domains, cleans URL after extraction |
| PerformanceTracker | `sendLoadMetrics` | Tracks web-vitals metrics (LCP) |
| NavigationTracker | `navigation` | Tracks SPA navigation (history API, hashchange) |
See [docs/trackers.md](docs/trackers.md) for details.
---
## What Data Is Sent
Xsolla Metrika collects and sends only technical and anonymized data required for analytics and improving user experience.
**No personal user data is collected or transmitted by default.**
Example of the event data structure
```json
{
"et": 1, // Event type (e.g., HIT, CLICK, etc.)
"library_version": "X.Y.Z", // Library version (injected at build time)
"counter_id": "YOUR_COUNTER_ID", // Your project counter ID
"dfp": "fingerprint_hash", // Device fingerprint
"xsollauid": "380884044985925701", // Xsolla user ID
"eid": 123456, // External ID (if there is)
"ident": {
"ntf": 1, // Notifications enabled (1/0)
"net": "4g", // Network type
"t": "Page Title", // Document title
"pc": "UTF-8", // Charset
"la": "en", // Language
"tz": -180, // Timezone offset (minutes)
"wcw": 1920, // Viewport width
"wch": 1080, // Viewport height
"sw": 1920, // Screen width
"sh": 1080, // Screen height
"j": 0, // Java enabled (1/0)
"c": 1, // Cookies enabled (1/0)
"sc": 24, // Color depth
"ifr": 0, // Is in iframe (1/0)
"adb": 0, // AdBlock detected (1/0)
"gacid": "123456789.1234567890", // Google Analytics CID (if there is)
"clid": "1733820844784899640", // Client ID
"vid": "1747380405323933016", // Visitor ID,
"cts": 1709571234567, // Client timestamp (ms since epoch)
"plt": 356, // Page load time (ms),
"lcp": 567 // Largest Contentful Paint (ms)
// ...additional cookies (for example: yid, pv, cv, etc.)
},
"user_agent": "...", // User-Agent string
"browser_major": "125", // Browser major version
"browser_name": "Chrome", // Browser name
"title": "Page Title", // Document title
"utm": {
"utm_source": null,
"utm_medium": null,
"utm_campaign": null,
"utm_content": null,
"utm_term": null
},
"openstat": {
"openstat_service": null,
"openstat_campaign": null,
"openstat_ad": null,
"openstat_source": null
},
"url": "https://your.site/page", // Current page URL
"referer": "https://referrer.site/", // Referrer URL
"exv": {}, // Extra values (if there is)
"abParams": {} // A/B test params (if there is)
// ...event-specific fields (for example: value, en, form, metricData, etc.)
}
```
---
## TypeScript Support
- 100% typed API, no need for `@types` packages.
- Works out of the box with TypeScript 5.8+.
- See [docs/ts-support.md](docs/ts-support.md) for troubleshooting and tips.
---
## Migration from v1
- Async initialization: use `await XsollaAnalytics.init(...)`.
- Device Fingerprinting has become more reliable.
- Events are sent via `sendBeacon` by default, with fallback to `fetch`.
- The method `dfpGet` has been renamed to `getFingerprintHash`.
- The method `keyDfpGet` has been renamed to `getFingerprintData`.
- Retry logic for failed fetch requests.
- See [docs/migration/v1_v2.md](docs/migration/v1_v2.md) for a full migration guide.
---
## Browser Support
- All modern browsers (Chrome, Firefox, Edge, Safari, Opera, Samsung Internet, etc.)
- Chrome 80+, Safari 13.1+, Firefox 74+, Edge 80+, iOS Safari 13.4+, Samsung Internet 13+
- See [docs/browser-support.md](docs/browser-support.md) for the full list.
---
## License
[MIT](LICENSE.md) © Xsolla
---