Skip to content
ABTO Guide

Integration guide

iOS / Swift

Collects user behavior and Custom Events in iOS and macOS apps. Installed with Swift Package Manager.

Client SDKRuns in the browser or a mobile app (Event Key)

The iOS/macOS SDK is available from the public Swift Package Manager repository. It supports iOS 14 or later and macOS 12 or later. In Xcode, open Add Package Dependencies… from the File menu and add https://github.com/greedy-co/abto-sdk.

In another Swift package, use the current .package(...) command shown above.

import AbtoApp
let abto = try AbtoClient(
projectKey: "ek-abto-…",
endpoint: "https://api.abto.app/v1/collect/events",
environment: .production,
)
abto.identify(userId: "user-123", tenantId: "tenant-123")
abto.capture("checkout_completed", properties: ["order_id": "order-123"])
abto.flush()

Use only an Event Key (ek-abto-…) in the client. Never put a Calling Key or provider key in the app. The second tenantId is optional; call abto.reset() on sign-out to clear the user and tenant context and create a new device_id and session.

The default UserDefaults store preserves the current device_id across ordinary app restarts and replaces it after reset. Pass an AbtoKeyValueStore implementation when the app must use its existing storage. Forward abto.deviceId as x-abto-device-id with the related server request to connect app events with Gateway calls.

The Mobile SDK does not call a model or the Gateway directly. Send deviceId and featureId to your application backend. The backend must validate them, pass them through Server SDK context, and expose the resulting x-abto-request-id in its response. The backend side is covered in Node / Server JavaScript and Python.

let trace = abto.startLlmTrace(
featureId: "resume.make",
taskType: "draft_generation",
surface: "editor"
)
trace.submitPrompt(prompt: promptText, language: "en")
let backendResponse = try await callBackend(
deviceId: abto.deviceId,
featureId: trace.featureId,
prompt: promptText
)
trace.attachRequestId(fromHeaders: backendResponse.allHeaderFields)
trace.markResponseVisible(responseId: "resp-123", timeToVisibleMs: 1_200)
trace.captureOutcome(.copied, responseId: "resp-123")

AbtoResponseInteraction exposes the 12 canonical response actions. The legacy string overload remains source-compatible during the 0.x line, but is deprecated and validates at runtime. Unsupported strings are warned and dropped before enqueueing; use a Custom Event for product-specific actions.

callBackend stands for your application’s existing networking function. Response events captured after attachRequestId() carry the same $request_id as the Gateway call.

  • Custom Properties passed to capture() do not go through Browser DOM masking. Do not put secrets or raw personal data in properties.
  • LLM trace prompt and response helpers record metadata_only information such as content length instead of the raw text.
  • Event names cannot be empty, start with $, or exceed 200 UTF-16 code units. Custom Properties starting with $ are omitted.
  • batchSize accepts 1...100, defaults to 20, and the default flush interval is 5 seconds.
  • Metric value must be finite with at most 38 integer digits and 12 fractional digits; scale is limited to 16 characters. An invalid metric is omitted while the event is still sent.
  • The in-memory delivery buffer holds at most 1,000 events and drops the oldest on overflow. It retries 408, 429, 5xx, and per-event retry results up to 5 attempts or 30 minutes after first enqueueing, with jittered exponential backoff capped at 2 minutes.
  • Delivery failures are not thrown into the app. The memory buffer does not survive process termination, so call flush() before the app enters the background.

How to name events and design Custom Properties is in Event design.