Skip to content

Track events

Ferry accepts three product events: login, signup, and purchase. It is not a general-purpose analytics SDK and does not accept arbitrary event names or property objects.

Track login and signup

iOS

Ferry.track(.login)
Ferry.track(.signup, customerID: "customer_123")

Android

Ferry.track(FerryTrackEvent.Login, customerId = "customer_123")
Ferry.track(FerryTrackEvent.Signup, customerId = "customer_123")

Flutter

await Ferry.track(FerryEvents.login);
await Ferry.track(
FerryEvents.signup,
customerId: 'customer_123',
);

React Native

Ferry.track(FerryEvents.login);
Ferry.track(FerryEvents.signup, 'customer_123');

customerId is optional and applies only to that event. Use an opaque identifier from your own system. Never pass a name, email address, phone number, advertising identifier, or another directly identifying value.

Purchases

A purchase needs:

  • A transaction ID that is unique inside the Ferry project.
  • A positive, finite value.
  • A three-letter currency matching the project’s reporting currency.
  • An optional product ID.

iOS purchase

Ferry.track(
.purchase(
transactionId: "order_123",
value: 29.99,
currency: "USD",
productId: "pro_monthly"
),
customerID: "customer_123"
)

Android purchase

Ferry.track(
FerryTrackEvent.Purchase(
transactionId = "order_123",
value = 29.99,
currency = "USD",
productId = "pro_monthly"
),
customerId = "customer_123"
)

Flutter purchase

await Ferry.track(
FerryEvents.purchase(
transactionId: 'order_123',
value: 29.99,
currency: 'USD',
productId: 'pro_monthly',
),
customerId: 'customer_123',
);

React Native purchase

Ferry.track(FerryEvents.purchase('order_123', 29.99, 'USD', 'pro_monthly'), 'customer_123');

Ferry never converts currencies. A project reports revenue in one currency, and a mismatched purchase is rejected rather than mixed into its totals.

Batching and delivery

The SDK queues events and flushes automatically when:

  • The queue reaches 20 events.
  • The oldest event has waited 30 seconds.
  • The app enters the background.

Each event has a stable idempotency key. A retry does not create a second event or purchase.

Partial rejection

One invalid purchase does not hide accepted sibling events in the same batch. Register the event-delivery listener if your app needs to reconcile rejections.

accepted: 2
rejected:
- index: 2
reason: currency_mismatch

Common rejection causes include a reporting-currency mismatch or a transaction ID already used for another purchase.

When attribution is unavailable

Events can still be accepted when no link was matched. They contribute to product analytics coverage but do not invent an originating link.