Documentation · Analytics
Breakdown your app's AI usage
These advanced analytic features are available on the Pro plan.
What's captured on each request
The SDK adds these headers to every authenticated request. Gate/AI records them and strips them before forwarding to the provider.
| Field | Header | Source | Notes |
|---|---|---|---|
| Locale | X-Client-Locale | Automatic | Language and region, e.g. en-US. |
| App version | X-App-Version | Automatic | From the app bundle / build config. |
| OS | X-OS-Version | Automatic | e.g. 18.6 or Android 15. |
| Type | X-Device-Type | Automatic | iPhone, iPad, Android. |
| Device model | X-Device-Model | Automatic | Hardware identifier, e.g. iPhone16,1. |
| Environment | X-Environment | Automatic | development, testflight, or production. |
| SDK version | X-SDK-Version | Automatic | Which Gate/AI SDK release made the request. |
| Identifier | X-Device-Identifier | Automatic on iOS; opt-in on Android | Vendor identifier (iOS) or ANDROID_ID (Android, deviceIdentifierEnabled). Falls back to IP when absent. |
| Country | — | Network edge | Derived server-side from the request; no location permission involved. |
| Status (user) | X-User-Status | You | Free-form segment for analytics, e.g. trial, premium. |
| User identifier | X-User-Identifier | You | Opaque account ID from your system — never an email or name. |
| Feature | X-App-Feature | You | Which in-app feature made the call, for per-feature cost. |
| Tier | X-User-Tier | You | Plan tier; required to enable per-tier usage limits. |
The four fields you set
Everything else is automatic. Set these on the client once (they can change at any time, e.g. after a purchase) and they ride along on every request.
Swift
gateAIClient.userIdentifier = account.analyticsId // opaque ID
gateAIClient.userTier = "pro" // limits key
gateAIClient.userStatus = "trial" // free-form segment
gateAIClient.appFeature = "chat" // per-feature cost
Kotlin
gateAIClient.userIdentifier = account.analyticsId // opaque ID
gateAIClient.userTier = "pro" // limits key
gateAIClient.userStatus = "trial" // free-form segment
gateAIClient.appFeature = "chat" // per-feature cost
Tier vs. status.
They look similar but do different jobs. userTier is an enforcement key — per-tier usage limits match it exactly, case-sensitively. userStatus is only ever a label for breaking down analytics. Keep tier names stable and short (free, pro, team) and put anything experimental or descriptive in status — trial, churn-risk, beta-cohort, onboarding-day-1, or a lifecycle stage like active / lapsed.
Privacy.
Use an opaque identifier for userIdentifier — a UUID or hash from your own system, not an email address or name. On Android the persistent device identifier is off by default because it carries a data-collection disclosure obligation; enable it with deviceIdentifierEnabled only if you've covered it in your privacy disclosure.
How token cost is calculated
Cost is derived, not reported by the provider. Shortly after a request completes, Gate/AI prices it from available public pricing. Spend shows on the gate page and in the Analytics tab as a daily series like this:
A request is priced from its input and output token counts. When the provider only reports a total, an assumed input/output split is applied and the cost is marked "(estimated)" in the request detail; requests with no token data, or a model that isn't priced yet, show a dash and are excluded from totals.
Consider cost figures as estimates for budgeting. Because of advanced model features like caching and varying context size, they cannot be exact.
OpenAI Realtime sessions are recorded as one request per model response, with audio, text and cached tokens priced at their own rates. See the realtime guide for how sessions appear in Logs and Analytics.
Using a cross-platform SDK
React Native, Capacitor, and Flutter use the same native analytics headers and usage limits. Pass context with each request instead of setting properties on the native client.
React Native & Capacitor
context: {
userIdentifier: 'user_8f2a',
userTier: 'pro',
appFeature: 'chat',
quotaAnchorDay: 15,
}
Flutter
context: const GateAIContext(
userIdentifier: 'user_8f2a',
userTier: 'pro',
appFeature: 'chat',
quotaAnchorDay: 15,
)
The framework SDKs preserve X-Quota-* and Retry-After headers on responses and HTTP errors. They do not expose the Swift/Kotlin quota model types. X-SDK-Version reports the underlying native SDK version.