Fire the call when the user submits a search — Enter key, Search button, suggestion tap. Don't pass the query string, the result count, or any normalized form of the query.
▸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 SwiftUI
struct SearchBar: View {
@State private var query = ""
var body: some View {
TextField("Search", text: $query)
.onSubmit {
Respectlytics.track("search_query")
api.search(query) { results in
if results.isEmpty {
Respectlytics.track("search_zero_results")
}
}
}
}
}
The query string stays in api.search, never in the analytics call. Zero-result rate is its own event.
✦Privacy & implementation notes
Search queries are some of the most sensitive content in your app — users type personal questions, medical concerns, addresses, names. The European Court of Justice has ruled IP + search-query combinations are personal data in multiple cases. Respectlytics's API rejects free-text payloads at the boundary; the query never gets that far.
Your search backend stores queries for ranking and quality work — that's its job, with proper retention and access controls. Mirroring those queries into analytics gives you a second store with weaker controls and no clear purpose. Respectlytics's role is the product-engagement layer above search, not the search-content layer itself.
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
| Search event | Firebase Analytics | Mixpanel | Respectlytics |
|---|---|---|---|
| Query string stored | Common (free-text param) | Common | Forbidden (PII) |
| Result count as parameter | Recommended | Recommended | Out of scope |
| Per-user search history | Yes | Yes | Out of scope |
| Search → result-clicked funnel | Per-user | Per-user | Session-scoped |
| Zero-result rate | Per-user from query property | Per-user | Use distinct event_name |
❓Frequently asked questions
How do we know what users search for if we don't store queries?
Your search backend (Algolia, Elastic, your own) already has the query data with appropriate retention and access controls. That's where query analytics lives. Respectlytics is for the product surface — "is search getting used and is it converting?" — not the content of queries.
What about zero-result queries?
Distinct event name: search_zero_results. Fire it instead of (or in addition to) search_query when the result set is empty. The rate of zero-result over total search is a UX-quality signal you can read directly.
Can we still measure search-driven conversion?
Yes, per-session. A session with search_query followed by product_viewed (or whatever your conversion event is) is a converting session. The funnel auto-discovery surfaces this without manual config.
What about voice search vs typed search?
Distinct event names: search_query_typed, search_query_voice. Their completion rates and result-click patterns differ enough to be worth splitting.