SDKs
Web (JavaScript / TypeScript)
The Tapemetric web SDK works in any modern browser, in Node 18+, and inside webviews on iOS and Android. ~6 KB gzipped, zero dependencies.
Install
npm / yarn / pnpm
npm install @tapemetric/analytics
yarn add @tapemetric/analytics
pnpm add @tapemetric/analyticsCDN — <script> tag
For static HTML pages or sites without a bundler, drop in the global build from jsDelivr:
<style="color:#f472b6">script src="https://cdn.jsdelivr.net/npm/@tapemetric/analytics@1.0.0/dist/tapemetric.min.js"></style="color:#f472b6">script>
<style="color:#f472b6">script>
const tm = Tapemetric.init({ apiKey: 'tm_live_yourkey' });
</style="color:#f472b6">script>unpkg works too: https://unpkg.com/@tapemetric/analytics@1.0.0/dist/tapemetric.min.js
@1.0.0) in production. Both jsDelivr and unpkg accept floating versions like @1 or @latest, but those introduce a coupling between us pushing a release and your site’s behavior changing without warning.Initialize
import Tapemetric from '@tapemetric/analytics';
const tm = Tapemetric.init({
apiKey: process.env.NEXT_PUBLIC_TAPEMETRIC_KEY!,
// optional config:
apiUrl: 'https://ingest.tapemetric.com', // override for self-hosted
flushIntervalMs: 10_000, // how often to send batches
maxBatchSize: 50, // max events per request
debug: false, // log every event to console
disableAutoFlush: false, // turn off the unload handlers
});Tapemetric.init is idempotent — calling it twice returns the same instance.
Identify users
// After login
tm.identify('user_123', {
plan: 'svod', // 'svod' | 'avod' | 'tvod' | 'free'
country: 'IN',
// any custom traits
});
// On logout
tm.reset();Track playback
// On play
tm.trackPlayStart(
{
contentId: 'aashiqana_s04e12',
contentType: 'series', // 'series' | 'movie' | 'short' | 'live' | 'trailer'
contentTitle: 'Aashiqana',
season: 4,
episode: 12,
},
{ positionSec: 0 }
);
// On pause / resume
tm.trackPause({ positionSec: 124.5 });
tm.trackResume({ positionSec: 124.5 });
// On bitrate change
tm.trackBitrateChange(2400, { positionSec: 200, bitrateKbps: 2400 });
// On seek
tm.trackSeek(200, 350, { positionSec: 350 });
// On buffer event ended (after the user resumes)
tm.trackBuffer(1200, { positionSec: 400 }); // 1.2s buffer
// On end / completion
tm.trackComplete({ positionSec: 1320, durationSec: 1320 });
// On error
tm.trackError('NETWORK_ERROR', 'Manifest fetch failed', /* fatal */ true);Track revenue
// After a Razorpay or Stripe charge succeeds
tm.trackPurchase({
amountInr: 199,
plan: 'svod',
orderId: 'order_xyz',
contentId: 'pvr_premiere_2026', // optional — for TVOD rentals
});HLS.js integration
import Hls from 'hls.js';
import Tapemetric from '@tapemetric/analytics';
const tm = Tapemetric.init({ apiKey: '...' });
const video = document.querySelector<HTMLVideoElement>('#video')!;
const hls = new Hls();
let bufferStartedAt: number | null = null;
hls.on(Hls.Events.BUFFER_APPENDED, () => {
if (bufferStartedAt) {
tm.trackBuffer(performance.now() - bufferStartedAt, {
positionSec: video.currentTime,
});
bufferStartedAt = null;
}
});
video.addEventListener('waiting', () => { bufferStartedAt = performance.now(); });
video.addEventListener('play', () => tm.trackPlayStart(
{ contentId: 'aashiqana_s04e12', contentType: 'series' },
{ positionSec: video.currentTime }
));
video.addEventListener('pause', () => tm.trackPause({ positionSec: video.currentTime }));
video.addEventListener('ended', () => tm.trackComplete({ positionSec: video.duration }));Reliability
The SDK does the right thing automatically:
- Batching — events queue up and ship every 10 seconds (configurable) or when the batch hits 50 events
- Unload reliability — when the page hides or unloads, the SDK uses
navigator.sendBeaconto flush remaining events even after the page closes - Failure retry — failed sends are re-queued (up to 1000 events) so a transient network glitch doesn’t lose data
- Anonymous tracking — anonymous_id is generated client-side and stored in localStorage; it’s the only thing stored
Privacy
The SDK never touches IPs, cookies, advertising IDs, or any identifier beyond what you pass it. See the full Privacy & DPDP guide for what gets collected and what doesn’t.
TypeScript
Types ship with the package — no @types/... install needed.
Bundle size
~6 KB gzipped, zero runtime dependencies. Tree-shakeable — if you only call trackPageView, the rest is dead code.