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 Swift (iOS) SDK
// Package.swift
dependencies: [
.package(url: "https://github.com/respectlytics/respectlytics-swift.git", from: "3.0.0")
]
// Or via Xcode → File → Add Packages → paste the URL above.
The SDK ships only via Swift Package Manager. CocoaPods and Carthage are not published — fewer integration paths means fewer surfaces to keep audited.
▸Initialize Respectlytics in Swift (iOS)
import Respectlytics
@main
struct MyApp: App {
init() {
Respectlytics.configure(appKey: "<YOUR_APP_KEY>")
}
var body: some Scene { WindowGroup { ContentView() } }
}
Call configure once at app launch — typically in your App struct's init. No Info.plist keys are required: the SDK does not call ATTrackingManager and does not request the IDFA, so NSUserTrackingUsageDescription should NOT be added.
▸Track the event in Swift (iOS)
import Respectlytics
import AVKit
class PlayerObserver {
private var fired25 = false, fired50 = false, fired75 = false, firedComplete = false
func attach(to player: AVPlayer) {
let interval = CMTime(seconds: 1, preferredTimescale: 1)
player.addPeriodicTimeObserver(forInterval: interval, queue: .main) { time in
guard let duration = player.currentItem?.duration.seconds, duration.isFinite else { return }
let progress = time.seconds / duration
if progress >= 0.25 && !self.fired25 { self.fired25 = true; Respectlytics.track("video_25pct_reached") }
if progress >= 0.50 && !self.fired50 { self.fired50 = true; Respectlytics.track("video_50pct_reached") }
if progress >= 0.75 && !self.fired75 { self.fired75 = true; Respectlytics.track("video_75pct_reached") }
if progress >= 0.99 && !self.firedComplete { self.firedComplete = true; Respectlytics.track("video_completed") }
}
}
}
Reset the fired* flags whenever the user starts a new video, otherwise subsequent videos won't re-fire the milestones.
✦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.
Apple rejected approximately 3% of apps in 2024 for incorrectly omitting NSUserTrackingUsageDescription when ATT was required by the SDKs they shipped. Respectlytics doesn't trigger ATT. The corollary is also true: do not add the key on Respectlytics's account — its presence implies you track across apps, even if your code never calls requestTrackingAuthorization.
Internally the Swift SDK uses Swift Concurrency: events are queued in an actor-isolated buffer (RAM-only), flushed on a 30-second timer and on UIApplication.willResignActiveNotification. Force-quit before flush drops queued events — by design. There is no UserDefaults or file backing.
⇋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.