stat18ion 0.0.2
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/README.md +54 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +83 -0
- package/package.json +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Stat18ion Tracker
|
|
2
|
+
|
|
3
|
+
The official client SDK for [Stat18ion Analytics](https://stat18ion.com).
|
|
4
|
+
Privacy-first, lightweight (< 1KB), and cookie-free analytics.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install stat18ion
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
Initialize the tracker once in your application root (e.g., `layout.tsx` or `App.js`).
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
import { init } from 'stat18ion';
|
|
18
|
+
|
|
19
|
+
init({
|
|
20
|
+
siteId: 'YOUR_SITE_ID',
|
|
21
|
+
// Optional: defaults to production endpoint
|
|
22
|
+
// endpoint: 'https://api.your-domain.com/api/event',
|
|
23
|
+
// Optional: enable logs in console
|
|
24
|
+
// debug: false
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Next.js Integration
|
|
29
|
+
|
|
30
|
+
In `app/layout.tsx`:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
'use client';
|
|
34
|
+
import { useEffect } from 'react';
|
|
35
|
+
import { init } from 'stat18ion';
|
|
36
|
+
|
|
37
|
+
export default function RootLayout({ children }) {
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
init({ siteId: 'YOUR_UUID_HERE' });
|
|
40
|
+
}, []);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<html lang="en">
|
|
44
|
+
<body>{children}</body>
|
|
45
|
+
</html>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Features
|
|
51
|
+
- 🚀 **Lightweight**: Zero dependencies, tiny bundle.
|
|
52
|
+
- 🕵️ **Privacy Friendly**: No IP storage, no cookies.
|
|
53
|
+
- ⚡ **Auto Tracking**: Automatically tracks route changes in SPAs (Next.js, React Router).
|
|
54
|
+
- 🛡️ **Dev Safety**: Automatically ignores `localhost` traffic unless `debug: true` is set.
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Analytics = exports.init = void 0;
|
|
4
|
+
let config = {
|
|
5
|
+
siteId: '',
|
|
6
|
+
endpoint: '', // Should be provided via init
|
|
7
|
+
};
|
|
8
|
+
const log = (message, ...args) => {
|
|
9
|
+
if (config.debug) {
|
|
10
|
+
console.log(`[Stat18ion] ${message}`, ...args);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
const sendEvent = (payload) => {
|
|
14
|
+
const url = config.endpoint;
|
|
15
|
+
const body = JSON.stringify(payload);
|
|
16
|
+
if (navigator.sendBeacon) {
|
|
17
|
+
const blob = new Blob([body], { type: 'application/json' });
|
|
18
|
+
navigator.sendBeacon(url, blob);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
fetch(url, {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
body,
|
|
24
|
+
headers: { 'Content-Type': 'application/json' },
|
|
25
|
+
keepalive: true,
|
|
26
|
+
}).catch((err) => console.error(err));
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const trackPageView = () => {
|
|
30
|
+
// Ignore localhost by default to avoid pollution
|
|
31
|
+
const isLocal = ['localhost', '127.0.0.1', '0.0.0.0'].includes(window.location.hostname);
|
|
32
|
+
if (isLocal && !config.debug) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const payload = {
|
|
36
|
+
siteId: config.siteId,
|
|
37
|
+
path: window.location.pathname,
|
|
38
|
+
referrer: document.referrer,
|
|
39
|
+
ua: navigator.userAgent,
|
|
40
|
+
ts: Date.now(),
|
|
41
|
+
};
|
|
42
|
+
log('Track PageView', payload);
|
|
43
|
+
sendEvent(payload);
|
|
44
|
+
};
|
|
45
|
+
// History API Monkey Patching
|
|
46
|
+
const patchHistory = () => {
|
|
47
|
+
const originalPushState = history.pushState;
|
|
48
|
+
const originalReplaceState = history.replaceState;
|
|
49
|
+
history.pushState = function (...args) {
|
|
50
|
+
originalPushState.apply(this, args);
|
|
51
|
+
trackPageView();
|
|
52
|
+
};
|
|
53
|
+
history.replaceState = function (...args) {
|
|
54
|
+
originalReplaceState.apply(this, args);
|
|
55
|
+
trackPageView();
|
|
56
|
+
};
|
|
57
|
+
window.addEventListener('popstate', () => {
|
|
58
|
+
trackPageView();
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
const init = (options) => {
|
|
62
|
+
if (config.siteId) {
|
|
63
|
+
console.warn('Stat18ion already initialized');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
config = { ...config, ...options };
|
|
67
|
+
if (!config.endpoint) {
|
|
68
|
+
console.error('[Stat18ion] Error: No endpoint provided. Analytics will not be sent.');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
log('Initialized', config);
|
|
72
|
+
// Initial Page View
|
|
73
|
+
trackPageView();
|
|
74
|
+
// Route Changes
|
|
75
|
+
patchHistory();
|
|
76
|
+
};
|
|
77
|
+
exports.init = init;
|
|
78
|
+
const Analytics = () => {
|
|
79
|
+
// Config would typically be passed via props or context in React
|
|
80
|
+
// For now this is a placeholder if we want a Component wrapper
|
|
81
|
+
return null;
|
|
82
|
+
};
|
|
83
|
+
exports.Analytics = Analytics;
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "stat18ion",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Privacy-first, lightweight analytics tracker for the modern web.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "npx tsc",
|
|
12
|
+
"prepublishOnly": "npm run build"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"analytics",
|
|
16
|
+
"privacy",
|
|
17
|
+
"stat18ion",
|
|
18
|
+
"tracking"
|
|
19
|
+
],
|
|
20
|
+
"author": "Stat18ion",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"dependencies": {},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"typescript": "^5.3.2"
|
|
25
|
+
}
|
|
26
|
+
}
|