tech0-statistics
v1.0.0
Published
Production-ready, non-blocking frontend analytics tracker for: - visit analytics (`page_view`, `navigation`, `page_exit`) - success/business events
Readme
tech0-statistics
Production-ready, non-blocking frontend analytics tracker for:
- visit analytics (
page_view,navigation,page_exit) - success/business events
Works framework-agnostic with adapters for React Router and Next.js.
Proposed Public API (TypeScript)
export type TrackerMode = "proxy" | "direct";
export interface TrackerOptions {
visitEndpoint?: string; // default "/api/tech0-analytics/track"
successEndpoint?: string; // default "/api/tech0-succes-tracker/success"
apiKey?: string; // optional; direct mode only. Defaults from VITE_TECH0_API_KEY or NEXT_PUBLIC_TECH0_API_KEY.
mode?: TrackerMode; // default "proxy"
debug?: boolean; // default false
visitApiKeyHeader?: string; // default "x-api-key"
successApiKeyHeader?: string; // default "x-api-key"
}
export interface Tech0Tracker {
trackVisit(event: VisitEventInput): Promise<void>;
trackSuccess(event: SuccessEventInput): Promise<void>;
trackPageExit(event: VisitEventInput): Promise<void>;
/** @deprecated */
track(event: VisitEventInput): Promise<void>;
/** @deprecated */
trackEvent(event: SuccessEventInput): Promise<void>;
/** @deprecated */
trackBusinessEvent(event: SuccessEventInput): Promise<void>;
}
export declare function createTech0Tracker(options?: TrackerOptions): Tech0Tracker;
export declare function Tech0AnalyticsRouterTracker(props: {
options?: TrackerOptions;
}): null;
export declare function Tech0AnalyticsNextTracker(props: {
currentPath: string;
options?: TrackerOptions;
}): null;Install
npm install tech0-statisticsCore Usage (Framework-agnostic)
import { createTech0Tracker } from "tech0-statistics";
const tracker = createTech0Tracker({
mode: "proxy", // default
// apiKey defaults from env in direct mode:
// VITE_TECH0_API_KEY or NEXT_PUBLIC_TECH0_API_KEY
});
void tracker.trackVisit({
session_id: "session-1",
path: "/pricing",
event_type: "page_view",
timestamp: new Date().toISOString()
});
void tracker.trackSuccess({
event_type: "business_success",
event_name: "checkout_complete",
metadata: { plan: "pro" }
});React Router Usage
import { BrowserRouter } from "react-router-dom";
import { Tech0AnalyticsRouterTracker } from "tech0-statistics/react-router";
export function App() {
return (
<BrowserRouter>
<Tech0AnalyticsRouterTracker
options={{
mode: "proxy",
visitEndpoint: "/api/tech0-analytics/track",
successEndpoint: "/api/tech0-succes-tracker/success"
}}
/>
{/* routes */}
</BrowserRouter>
);
}Behavior:
- first mount => sends
event_type = "page_view" - route change => sends
event_type = "navigation"withreferrer_pathandduration_seconds - pagehide/unload => sends
event_type = "page_exit"usingsendBeaconwhen available - session id managed in
sessionStorage
Next.js Usage
"use client";
import { usePathname } from "next/navigation";
import { Tech0AnalyticsNextTracker } from "tech0-statistics/next";
export function AnalyticsTracker() {
const pathname = usePathname();
return (
<Tech0AnalyticsNextTracker
currentPath={pathname}
options={{ mode: "proxy" }}
/>
);
}If NEXT_PUBLIC_TECH0_API_KEY exists and you use mode: "direct", tracking works immediately after install.
For secure production, keep mode: "proxy" and forward server-side.
Success Event On Button Click (React/Next)
import { Tech0SuccessButton } from "tech0-statistics";
<Tech0SuccessButton
event={{
event_type: "success",
event_name: "book_demo_click",
path: "/pricing"
}}
>
Book demo
</Tech0SuccessButton>;Or wrap any existing click handler:
import { withTech0SuccessOnClick } from "tech0-statistics";
const onBuy = withTech0SuccessOnClick(
() => {
// your action
},
{ event_type: "success", event_name: "buy_now_click" }
);Proxy vs Direct Mode
proxy(default, recommended):- frontend calls same-origin endpoints only
- no client secret required
direct:- frontend sends key headers
- visits header:
x-api-key - success header:
x-api-key - can override header names with
visitApiKeyHeader/successApiKeyHeader - key resolution order:
options.apiKey, thenVITE_TECH0_API_KEY, thenNEXT_PUBLIC_TECH0_API_KEY
Header note
If your upstream expects a custom key header, set:
createTech0Tracker({
mode: "direct",
successApiKeyHeader: "x-api-key",
visitApiKeyHeader: "x-site-api-key" // optional legacy override
});Event Schemas
Visit payload (snake_case)
Required:
session_idpathevent_typetimestamp
Optional:
referrer_pathduration_secondsbrowserplatform
Success payload (snake_case)
Required:
event_typeevent_name
Optional:
timestamppathsession_idmetadata(object)
Supabase Mapping (Tech0)
Recommended proxy inserts:
- visit endpoint (
/api/tech0-analytics/track) ->public.site_visits - success endpoint (
/api/tech0-succes-tracker/success) ->public.success_events - if needed for CMS/portal flows, route success endpoint to
portal.success_events
Canonical payload keys in this SDK match snake_case insert patterns:
- visits:
session_id,path,event_type,timestamp,referrer_path,duration_seconds,browser,platform - success:
event_type,event_name,timestamp,path,session_id,metadata
Accepted aliases that are auto-normalized before send:
sessionId->session_ideventType->event_typeeventName->event_namepathname/url->pathreferrer/referrerPath->referrer_pathdurationSeconds->duration_secondscreated_at/createdAt->timestampuserAgent->browser
Backward Compatibility + Migration
- camelCase input is accepted and normalized to snake_case before sending:
sessionId -> session_ideventType -> event_typeeventName -> event_namereferrerPath -> referrer_pathdurationSeconds -> duration_seconds
- legacy aliases remain:
track()-> deprecated alias oftrackVisit()trackEvent()-> deprecated alias oftrackSuccess()trackBusinessEvent()-> deprecated alias oftrackSuccess()
Security Best Practices
- Prefer
mode: "proxy"in browser apps. - Keep true secret keys server-side.
- Only use
NEXT_PUBLIC_*/VITE_*keys if intentional and risk-accepted. - Keep tracking non-blocking (
fetch keepalive,sendBeacon) so analytics never blocks UX.
Minimal Integration Test Example
import { createTech0Tracker } from "tech0-statistics";
const tracker = createTech0Tracker({ mode: "proxy" });
await tracker.trackSuccess({
event_type: "business_success",
event_name: "order_placed"
});