@arthurreira/analytics
v0.23.0
Published
Analytics SDK for af-analytics (browser client + helpers)
Readme
@arthurreira/analytics
Lightweight analytics SDK with three usage modes:
| Mode | Use when |
| --- | --- |
| <Analytics /> component | Next.js / React apps — zero-config, drop it in the root layout |
| useAnalytics hook | React, need custom events from individual components |
| Vanilla script tag | Any HTML page — no framework required |
Tracks pageviews, clicks, scroll depth, text copies, JS errors, CTAs, searches, and session duration — with automatic session management and optional real-time presence via WebSocket.
Installation
React / Next.js
pnpm add @arthurreira/analytics
# or
npm install @arthurreira/analyticsPeer dependencies: react ^18 || ^19, next ^14 || ^15 || ^16
Vanilla JS (no package manager)
<script
src="https://unpkg.com/@arthurreira/[email protected]/dist/af-analytics.umd.js"
data-api-key="proj_xxx"
data-url="https://your-edge-worker.dev"
></script>Drops a global AfAnalytics object and auto-initialises on DOMContentLoaded — no other code needed.
WordPress
Option A — functions.php (recommended for theme/child-theme)
Add to your theme's functions.php:
function af_analytics_enqueue() {
wp_enqueue_script(
'af-analytics',
'https://unpkg.com/@arthurreira/[email protected]/dist/af-analytics.umd.js',
[],
null,
true // load in footer
);
// Attach data attributes after the script tag is output
add_filter( 'script_loader_tag', function ( $tag, $handle ) {
if ( $handle !== 'af-analytics' ) return $tag;
return str_replace(
'<script ',
'<script data-api-key="proj_xxx" data-url="https://your-edge-worker.dev" ',
$tag
);
}, 10, 2 );
}
add_action( 'wp_enqueue_scripts', 'af_analytics_enqueue' );Option B — "Insert Headers and Footers" plugin (no code)
- Install the Insert Headers and Footers plugin.
- Go to Settings → Insert Headers and Footers.
- Paste the snippet below into the Scripts in Footer box and save:
<script
src="https://unpkg.com/@arthurreira/[email protected]/dist/af-analytics.umd.js"
data-api-key="proj_xxx"
data-url="https://your-edge-worker.dev"
></script>Replace proj_xxx with your project API key and https://your-edge-worker.dev with your Edge Worker URL. The script auto-tracks pageviews, clicks, scroll depth, and JS errors with no further configuration.
Quick start
Option A — <Analytics /> component (Next.js, recommended)
Add it once in your root layout. Automatically tracks pageviews, clicks, scroll-depth milestones (25 / 50 / 75 / 100 %), text copies, and uncaught JS errors.
// app/layout.tsx
import { Analytics } from '@arthurreira/analytics/client'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
{children}
<Analytics
apiUrl={process.env.NEXT_PUBLIC_ANALYTICS_URL!}
apiKey={process.env.NEXT_PUBLIC_ANALYTICS_KEY!}
/>
</body>
</html>
)
}Option B — useAnalytics hook (custom events)
Use the hook when you need to fire custom events from your own components.
'use client'
import { useAnalytics } from '@arthurreira/analytics/client'
export function SearchBar() {
const { trackSearch, trackCTA } = useAnalytics(
process.env.NEXT_PUBLIC_ANALYTICS_URL!,
process.env.NEXT_PUBLIC_ANALYTICS_KEY!,
)
return (
<input
onKeyDown={(e) => {
if (e.key === 'Enter') trackSearch(e.currentTarget.value)
}}
/>
)
}Option C — Vanilla JS script tag
Works with any HTML page or server-rendered site. Config is read from data-* attributes on the script tag itself.
<script
src="/sdk/af-analytics.umd.js"
data-api-key="proj_xxx"
data-url="https://your-edge-worker.dev"
></script>Auto-tracks the same events as the React component. No configuration code required. Call AfAnalytics.init() manually if you need to reinitialise after the script was loaded dynamically.
API reference
<Analytics /> props
| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| apiUrl | string | yes | Base URL of your analytics backend (no trailing slash) |
| apiKey | string | yes | Project API key |
| wsUrl | string | no | WebSocket URL for real-time presence (default: wss://edge.arthurreira.dev/realtime) |
Auto-tracks: pageview, click, scroll (depth milestones), copy, error.
useAnalytics(apiUrl, apiKey, options?)
| Option | Type | Description |
| --- | --- | --- |
| options.wsUrl | string | Override the default presence WebSocket URL |
Events are queued internally until the session is ready — safe to call immediately on mount.
| Method | Signature | Description |
| --- | --- | --- |
| trackPageview | (path: string) => void | Manual pageview (SPA route changes) |
| trackClick | (e: MouseEvent, element: HTMLElement) => void | Click with position + element metadata |
| trackScroll | (depth: number) => void | Scroll depth percentage (0–100) |
| trackCopy | () => void | Text copy event (captures selected text, up to 200 chars) |
| trackError | (error: Error) => void | JS error with message + stack trace |
| trackCTA | (ctaId: string, ctaVariant?: string) => void | CTA button interaction |
| trackSearch | (query: string) => void | Search query |
Raw API helpers (server / build safe)
The default entry exports the low-level functions with no browser globals — safe to import in server components or Node.js scripts.
import {
createSession,
trackPageview,
trackClick,
trackScroll,
trackCopy,
trackError,
trackCTA,
trackSearch,
} from '@arthurreira/analytics'All helpers take (apiUrl, apiKey, sessionId, ...) as their first arguments and call your backend directly via fetch.
Presence (real-time WebSocket)
Optional live-visitor presence tracking over WebSocket.
import { connectPresence, DEFAULT_WS_URL } from '@arthurreira/analytics'
import type { PresenceConnection } from '@arthurreira/analytics'
const conn: PresenceConnection = connectPresence(apiKey, sessionId, DEFAULT_WS_URL)
// later
conn.disconnect()The connection retries up to 3 times with exponential back-off on unexpected close. When used via the <Analytics /> component or useAnalytics, presence connects automatically and disconnects on session end.
Package exports
| Import path | Format | Contents | Use in |
| --- | --- | --- | --- |
| @arthurreira/analytics | ESM | Raw API helpers + presence (no browser globals) | Server / Node |
| @arthurreira/analytics/client | ESM | Analytics component + useAnalytics hook | React client |
| dist/af-analytics.umd.js | IIFE | Self-contained auto-tracking script | Any HTML page |
Session management
- A session is created on first load and stored in
localStorage(af_session_id). - Sessions expire after 30 minutes of inactivity.
- On tab hide (
visibilitychange → hidden) or page unload (beforeunload) the SDK callsnavigator.sendBeaconto close the session gracefully — no events are dropped. - Visitor identity persists across sessions via
af_analytics_visitor_id(a random UUID inlocalStorage).
Data collected
On session start
| Field | Description |
| --- | --- |
| visitor_id | Persistent anonymous UUID |
| language | navigator.language |
| screen_width / height | Physical screen resolution |
| viewport_width / height | Current browser viewport |
| referrer | document.referrer |
| landing_page | window.location.pathname |
| timezone | IANA timezone string |
| cpu_threads | navigator.hardwareConcurrency |
| memory_gb | navigator.deviceMemory (Chrome only) |
| gpu | WebGL unmasked renderer string |
| network_type | effectiveType from Network Information API |
| connection_speed_mbps | downlink from Network Information API |
| utm_source/medium/campaign/term/content | UTM parameters from the landing URL |
On each event
session_id, event_type, path, page_url, plus event-specific fields:
| Event | Extra fields |
| --- | --- |
| pageview | page_title, referrer, scroll_depth: 0 |
| click | x_position, y_position, element_id, element_class, element_text |
| scroll | scroll_depth (25 / 50 / 75 / 100) |
| copy | copied_text (up to 200 chars) |
| error | error_message, stack_trace |
| cta_click | cta_id, cta_variant |
| search | search_query |
Environment variables (Next.js)
| Variable | Description |
| --- | --- |
| NEXT_PUBLIC_ANALYTICS_URL | Backend base URL, e.g. https://analytics.example.com |
| NEXT_PUBLIC_ANALYTICS_KEY | Project API key |
Building locally
pnpm install
pnpm buildOutputs:
| File | Format | Entry |
| --- | --- | --- |
| dist/index.js + dist/index.d.ts | ESM | src/index.ts |
| dist/client.js + dist/client.d.ts | ESM | src/client.ts |
| dist/af-analytics.umd.js | IIFE/UMD | src/vanilla.ts |
Publishing
Tag a release after adding an NPM_TOKEN secret to the repository to trigger the CI publish workflow.
License
MIT
