Upgrading to 0.1.0

What changed in the 0.1.0 LinkTrail SDKs on iOS, Android, React Native and Flutter, and what to change in your app: link domains, consent, configure, logs.

All four SDKs moved to 0.1.0 together: iOS from 0.0.12, Android from 0.0.5, React Native and Flutter from 0.0.4. It is a 0.x minor bump, so it has breaking changes. Check each one below against your integration. The install lines are on the Versions page.

Change your code

List your custom link domains

handleDeepLink now claims only https links on linktrail.io (or a subdomain) and on the hosts listed in linkDomains (or their subdomains). An empty linkDomains no longer means every host. If your links use your own domain, list it, or the app opens and never navigates. Links on *.linktrail.io need no change.

iOS

Swift
try LinkTrail.configure(apiKey: "lt_live_...",
                        options: LinkTrailOptions(linkDomains: ["go.yourbrand.com"]))

Android

Kotlin
LinkTrail.configure(context = this, apiKey = "lt_live_...",
    options = LinkTrailOptions(linkDomains = listOf("go.yourbrand.com")))

React Native

TypeScript
await LinkTrail.configure('lt_live_...', { linkDomains: ['go.yourbrand.com'] });

Flutter

Dart
await LinkTrail.configure(apiKey: 'lt_live_...',
    options: LinkTrailOptions(linkDomains: ['go.yourbrand.com']));

Any other URL (mailto:, an OAuth callback, myapp://settings) returns false (the async forms throw notALinkTrailURL / NotALinkTrailUrl; React Native resolves null). It makes no request and doesn't call onError, so route those URLs yourself. Custom-scheme LinkTrail links (myapp://slug) are no longer handled: share the https link.

Re-register callbacks after a reconfigure

On iOS and Android, configure is now a singleton. A repeat call with the same API key and equal options returns the existing instance and changes nothing (linkDomains compare as a set, so a reordered list counts as equal). A call with a different key or options shuts the previous instance down, cancels its pending work and drops its callbacks, then returns a new instance. Register onLink, onAttribution and onError again on the instance it returns, and don't keep using a reference to the old one: every call on it is ignored. Saved state (install flags, consent, device ID) is kept.

Check the paste button's consent rule

LinkTrailPasteButton (native iOS, React Native and Flutter) no longer grants consent after a denial. grantsConsent now defaults to grant only while consent is still undecided, so an earlier setConsent(false) stays. Pass true for the old behaviour, where the tap always grants, or false to never touch consent. The React Native and Flutter buttons now send the install themselves: remove any setConsent or trackInstallWithClickToken call from their callbacks.

Expect invalid options to be clamped, not thrown

Out-of-range options no longer throw. configure fixes each one and logs a WARNING: fewer than 1 attempt becomes 1, a base delay of 0 or less becomes 0.5 s, a maximum delay of 0 or less becomes 8 s, a maximum delay below the base delay is raised to it, and a request timeout of 0 or less becomes 15 s. On Android, LinkTrailRetryPolicy(maxAttempts < 1) used to throw. On iOS, LinkTrailRetryPolicy now stores the values you pass and the clamp happens at configure, so code that reads a policy's properties sees the raw values. LinkTrailRetryPolicy.disabled.baseDelay on iOS is now 0.5 (was 0); it changes nothing, because one attempt never waits.

Update log filters and alerts

Both platforms now print [LinkTrail] [LEVEL] message, with LEVEL DEBUG, INFO, WARNING (was WARN) or ERROR. A few lines changed level, and logged URLs drop their query and fragment.

Behaviour that changed

  • A denial always wins. Even with requireConsent: false, an explicit setConsent(false) sends one consent: false install with no device ID and no Idempotency-Key, and drops custom events. Before, with requireConsent: false, the install still went out counted, with the device ID.
  • The deferred link is delivered at least once. It is saved as soon as it resolves and kept until an onLink handler is registered, in that launch or a later one. It is marked routed only after the handler ran, so a crash inside the handler can mean one redelivery on the next launch. Make the handler safe to run twice. A saved link older than 7 days is dropped.
  • SDK state is no longer backed up. It moves to a device-only file on the first launch with 0.1.0, automatically. An app restored from a backup or moved to a new phone starts fresh: it counts as a new install and must ask for consent again. On Android, configure the SDK in one process only.
  • Rejected events are dropped, not queued. Only transport errors, 408, 429 and 5xx are queued and retried. Any other status (400, 401, 403, 404, 409, 422, …) still reaches onError, but the event isn't retried on a later launch.
  • Nested `customData` values arrive as JSON strings. customData stays a string-to-string map; decode nested objects and arrays yourself.
  • Stricter clipboard token on iOS. The pasteboard is used (and cleared) only when its whole content is lt_click=<32 hex>. Text that merely contains a token is ignored.

New in 0.1.0

  • Every request sends `X-LinkTrail-SDK`. The native SDKs send ios/<version> and android/<version>; on Android the wrappers send react-native/<version> and flutter/<version>. Known gap: on iOS the wrappers report ios/<version> until iOS 0.1.1.
  • `LinkTrail.version` on iOS (Android: LinkTrail.VERSION) is the SDK version as a public constant.

Each release's full notes are in the changelogs linked from Versions. The consent model all four SDKs share is in Consent & privacy.