Respectlytics Respect lytics
Menu
Swift (iOS) Content shared Privacy-first

How to track content share events in Swift (iOS) without personal data

Content share — "share to Messages", "share to Twitter", "copy link" — is a viral-loop signal in social and content apps. Most analytics SDKs default to logging the destination app, the shared content ID, and sometimes the recipient. Respectlytics helps developers avoid collecting personal data in the first place: in Swift (iOS), share is one named event per channel, with no payload. Below: the Swift (iOS) share-sheet integration, why channel goes in the event name, and what stays out.

Fire the call inside the share-sheet completion callback when the user has actually completed the share (not when they open the sheet — abandonment is common). Encode the chosen channel into the event name.

Install the Swift (iOS) SDK

swift Respectlytics
// 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)

swift Respectlytics
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)

swift Respectlytics
import Respectlytics
import UIKit

func presentShare(content: String, from vc: UIViewController) {
    let activity = UIActivityViewController(activityItems: [content], applicationActivities: nil)
    activity.completionWithItemsHandler = { type, completed, _, _ in
        guard completed else {
            Respectlytics.track("share_cancelled")
            return
        }
        // Map ActivityType to a distinct event_name:
        switch type {
        case UIActivity.ActivityType.message:    Respectlytics.track("share_imessage")
        case UIActivity.ActivityType.mail:       Respectlytics.track("share_email")
        case UIActivity.ActivityType.copyToPasteboard: Respectlytics.track("share_copy_link")
        default:                                  Respectlytics.track("share_other")
        }
    }
    vc.present(activity, animated: true)
}

The completionWithItemsHandler's completed flag is true only when the user actually completed the share — abandonment fires the cancellation arm.

Privacy & implementation notes

Putting the channel as a parameter ({ channel: 'twitter' }) is the natural first instinct and is exactly what Respectlytics's API rejects. Encode it as the event name — share_twitter — and you get the same downstream queryability without storing parameters.

Fire on share completion, not on share-sheet presentation. Share-sheet presentation is fairly common (the user is just exploring); actual completion is much rarer and is the meaningful signal. The two rates differ by 5–10× in most apps.

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

Share eventFirebase AnalyticsMixpanelRespectlytics
Share channel as parameterRecommendedRecommendedUse distinct event_name
Shared content IDRecommendedRecommendedOut of scope (use content backend)
Recipient data (when accessible)PossiblePossibleForbidden (PII)
Per-user share countYesYesOut of scope
Share rate by content / channelPer-userPer-userUse distinct event_names + content backend

Frequently asked questions

How do we know which channels are most popular?

Distinct event names per channel: share_imessage, share_email, share_twitter, share_copy_link. Aggregation gives per-channel rate. iOS's UIActivityViewController and Android's Intent chooser deliver the selected channel in the completion callback — encode it into the event name.

What about shared content metadata?

Stays in your content backend. The CMS or content database knows what was shared. Respectlytics tells you that a share happened in this session — the join to specific content is a backend concern.

Can we measure share-induced installs?

Server-side via deferred deep links and install attribution. App Store Connect / Play Console deliver the attribution; your backend correlates the shared link's tracking parameter with the resulting install. Respectlytics doesn't ingest install attribution — it's not the right system for that.

What if the share sheet completes but the user cancels?

iOS's UIActivityViewController and Android's Intent chooser both call back with a cancellation flag. Don't fire share_* on cancel — fire share_cancelled (a single event regardless of channel) if you want to track abandonment.

Related guides

Track what matters. Collect nothing you don't.

Five-field event schema, RAM-only event queue, no IDFA, no AAID, no persistent user IDs. Helps developers avoid collecting personal data in the first place.