Fire the call at meaningful playback milestones: video_play_started, video_25pct_reached, video_50pct_reached, video_75pct_reached, video_completed. Don't pass video ID, content title, or duration.
▸Install the React Native SDK
npm install @respectlytics/react-native
# or
yarn add @respectlytics/react-native
JavaScript-only — no native modules, no auto-linking, no New Architecture migration concerns. Bundle size: ~14KB minified+gzipped. Works in any Expo project (managed or bare) without expo prebuild.
▸Initialize Respectlytics in React Native
// App.tsx (or App.js)
import { useEffect } from 'react';
import Respectlytics from '@respectlytics/react-native';
export default function App() {
useEffect(() => {
Respectlytics.configure({ appKey: '<YOUR_APP_KEY>' });
}, []);
return <YourApp />;
}
Initialize once in your top-level component. No native config; no Info.plist or AndroidManifest changes. The SDK is Hermes- and JSC-compatible.
▸Track the event in React Native
import Respectlytics from '@respectlytics/react-native';
import { useState } from 'react';
import Video from 'react-native-video';
export function TrackedVideo({ source }) {
const [milestones, setMilestones] = useState({});
return (
<Video
source={source}
onProgress={({ currentTime, playableDuration }) => {
const p = currentTime / playableDuration;
const next = { ...milestones };
if (p >= 0.25 && !milestones.m25) { Respectlytics.track('video_25pct_reached'); next.m25 = true; }
if (p >= 0.50 && !milestones.m50) { Respectlytics.track('video_50pct_reached'); next.m50 = true; }
if (p >= 0.75 && !milestones.m75) { Respectlytics.track('video_75pct_reached'); next.m75 = true; }
if (p >= 0.99 && !milestones.complete) { Respectlytics.track('video_completed'); next.complete = true; }
if (Object.keys(next).length !== Object.keys(milestones).length) setMilestones(next);
}}
/>
);
}
Reset milestones to {} when the source changes via the source prop. onProgress fires several times per second — the gating logic is essential.
✦Privacy & implementation notes
Tracking exact playback position generates 30+ events per minute of viewing and dilutes every other signal in your analytics pipeline. Four milestones (25, 50, 75, 100%) per video carry essentially the same product signal at 1/100th the volume.
Your CMS already stores video titles, descriptions, durations, and content categories. Joining video_completed_movie events to your CMS's view-count-per-video data answers most product questions; storing the title as analytics metadata duplicates a system of record without adding signal.
The React Native SDK is JavaScript-only — no Objective-C/Swift bridging on iOS, no Java/Kotlin bridging on Android. Side effects: no react-native link, no auto-linking, no New Architecture migration concerns, no platform-channel exception surfaces. Trade-off: no access to platform-only metadata (which we don't want to collect anyway).
Works in Expo managed workflow without expo prebuild. No config plugin is required. EAS Build users: nothing to configure. This is the smoothest integration path on RN — most analytics SDKs require ejecting from managed.
⇋How this compares to other analytics SDKs
| Video completion event | Firebase Analytics | Mixpanel | Respectlytics |
|---|---|---|---|
| Video ID as parameter | Recommended | Recommended | Forbidden (use top-N event_names) |
| Content category / genre | Recommended | Recommended | Use distinct event_name (top-N) |
| Watch duration in seconds | Recommended | Recommended | Out of scope (use milestones) |
| Per-user watch history | Yes | Yes | Out of scope (use content backend) |
| Completion *rate* by country / platform | Yes | Yes | Yes (default) |
❓Frequently asked questions
How do we know which videos are most-watched?
Your content backend already has play counts per video — that's where video-level engagement lives. Respectlytics is for product engagement at the feature level ("is the video player surface working?"). Conflating them duplicates a system of record.
Should we track exact playback position?
No — milestones (25 / 50 / 75 / 100%) carry the signal. Exact position produces a flood of low-value events that drown the milestone signal. Player-side analytics (your video player vendor's SDK) has its own per-second tracking if you genuinely need it.
What about content category breakdowns (movies, shows, shorts)?
If you have a small fixed set, distinct event names: video_completed_movie, video_completed_show. For high-cardinality categorization, use your content backend's analytics — it has the metadata you need.
Does this work for live streams?
Conceptually different. Use distinct event names — livestream_joined, livestream_left — and fire on join and leave. Milestones don't apply to live; duration is computed from join → leave timestamp difference.