Documentation Index
Fetch the complete documentation index at: https://docs.tell.rs/llms.txt
Use this file to discover all available pages before exploring further.
The Swift SDK tracks events and structured logs from your Apple apps. It’s a client SDK — you configure a singleton once at launch, and it handles device IDs, sessions, and delivery automatically.
Events called before initialization completes are queued and replayed. Your app never blocks on network I/O.
Installation
Add the package in Xcode: File > Add Package Dependencies and enter:
https://github.com/tell-rs/tell-swift.git
Or in your Package.swift:
dependencies: [
.package(url: "https://github.com/tell-rs/tell-swift.git", from: "1.0.0")
]
Requires iOS 16.0+, macOS 13.0+, or visionOS 1.0+, with Swift 6.0+ and Xcode 16.0+.
Quick start
import Tell
// Configure once at app startup
Tell.shared.configure(apiKey: "a1b2c3d4e5f60718293a4b5c6d7e8f90", preset: .production)
// Track events
Tell.shared.track(.pageViewed, properties: ["url": "/home"])
// Identify users
Tell.shared.identify("user_123", traits: ["name": "Jane", "plan": "pro"])
That’s it. The SDK generates a device ID, starts a session, collects device context, and batches events over TCP. Events fired before configure completes are queued (up to 1,000) and sent once ready.
Configuration
Use a preset for one-line setup, or pass individual parameters.
// Production — collect.tell.rs:50000, batch 100, flush 10s
Tell.shared.configure(apiKey: "YOUR_API_KEY", preset: .production)
// Development — localhost:50000, batch 10, flush 2s
Tell.shared.configure(apiKey: "YOUR_API_KEY", preset: .development)
For fire-and-forget initialization (returns immediately, connects in the background):
Tell.shared.configureAsync(
apiKey: "YOUR_API_KEY",
endpoint: "collect.tell.rs:50000",
batchSize: 100,
flushInterval: 10,
logLevel: .debug
)
For async initialization with error handling:
try await Tell.shared.configure(
apiKey: "YOUR_API_KEY",
sessionTimeout: 30 * 60,
defaultOptOut: false,
onError: { error in print("Tell: \(error)") }
)
The API key must be a 32-character hex string.
Tracking events
No user ID needed — the SDK tracks the current user automatically (anonymous until you call identify).
// Typed event names
Tell.shared.track(.featureUsed, properties: [
"feature": "dark_mode",
"enabled": true
])
// String event names
Tell.shared.track("Custom Event", properties: ["key": "value"])
// No properties
Tell.shared.track(.pageViewed)
Standard event names
The SDK provides strongly typed constants for common events:
Tell.shared.track(.pageViewed, properties: ["url": "/pricing"])
Tell.shared.track(.userSignedUp, properties: ["source": "organic"])
Tell.shared.track(.orderCompleted, properties: ["total": 99.00])
Tell.shared.track(.featureUsed, properties: ["feature": "export"])
Tell.shared.track(.subscriptionStarted, properties: ["plan": "pro"])
Constants cover user lifecycle, revenue, subscriptions, trials, shopping, engagement, communication, and session events. Custom string names always work too.
Revenue
Track purchases with typed currency codes:
Tell.shared.revenue(
amount: 49.99,
currency: .usd,
orderID: "order_456",
properties: ["product": "annual_plan"]
)
The SDK includes constants for 60+ currencies (.usd, .eur, .gbp, .jpy, .btc, etc.) and accepts custom currency strings via Currency("XYZ").
User identity
// Identify a known user — stores the ID for all subsequent events
Tell.shared.identify("user_123", traits: [
"name": "Jane",
"email": "jane@example.com",
"plan": "pro"
])
// Associate user with a group
Tell.shared.group("company_456", properties: [
"name": "Acme Corp",
"plan": "enterprise"
])
// Link two identities
Tell.shared.alias("anon_visitor_abc", userId: "user_123")
Super properties
Register properties that get merged into every track, group, and revenue call:
Tell.shared.register(["app_version": "2.1.0", "env": "production"])
// This track call automatically includes app_version and env
Tell.shared.track(.featureUsed, properties: ["feature": "export"])
// Remove a super property
Tell.shared.unregister("env")
Event-specific properties override super properties when keys conflict.
Structured logging
Send logs alongside events through the same pipeline:
Tell.shared.logError("Payment failed", service: "billing", data: [
"error": "card_declined",
"amount": 9.99
])
Tell.shared.logInfo("User signed in", service: "auth", data: [
"method": "oauth"
])
Tell.shared.logWarning("High memory usage", service: "app")
The service parameter defaults to "app". Convenience methods are available for all nine RFC 5424 levels: logEmergency, logAlert, logCritical, logError, logWarning, logNotice, logInfo, logDebug, and logTrace.
Sessions
Sessions are managed automatically. The SDK:
- Generates a persistent device ID (stored in UserDefaults)
- Creates a new session on launch with a device context snapshot
- Tracks app background/foreground transitions
- Starts a new session if the app was backgrounded longer than
sessionTimeout (default: 30 minutes)
Device context collected automatically includes device model, OS version, app version, screen dimensions, locale, timezone, and battery state (iOS).
Privacy
// Stop all data collection — events are dropped locally
Tell.shared.optOut()
// Resume data collection
Tell.shared.optIn()
// Check current state
if Tell.shared.isOptedOut() {
// Show consent prompt
}
Opt-out state is persisted across sessions. For privacy-first apps, set defaultOptOut: true during configuration so new users start opted out.
When opted out, all tracking and logging calls silently drop. flush() and close() still work.
Lifecycle
// Force-send all queued events
try await Tell.shared.flush()
// Reset user — generates new anonymous ID, clears super properties
Tell.shared.reset()
// Graceful shutdown
try await Tell.shared.close()
Call reset() on logout to start a fresh anonymous session for the next user.
Advanced
Configuration reference
| Parameter | Default | Description |
|---|
endpoint | collect.tell.rs:50000 | TCP collector address |
batchSize | 100 | Events per batch before auto-flush |
flushInterval | 10s | Time between auto-flushes |
sessionTimeout | 30 min | Background time before new session |
defaultOptOut | false | Initial opt-out state for new users |
generateEventIds | false | Client-side event deduplication IDs |
logLevel | .info | SDK internal log verbosity |
Validation rules
| Field | Rule |
|---|
| API key | 32-character hex string |
| Event name | 1–256 characters |
| Log message | 1–65,536 characters |
| User ID | Non-empty |
| Group ID | Non-empty |
| Order ID | Non-empty |
| Revenue amount | Positive number |
Pre-initialization queue
Events called before configure completes are buffered (up to 1,000 items). On overflow, the oldest event is dropped. Once initialization succeeds, all queued events are replayed in order.