Events

18 subscription events that can be sent to 3rd party analytics and webhook. These events will help you to better understand the behavior of your subscribers

Apple and Google send subscription events directly to the server using App Store Server Notifications and Real-time Developer Notifications (RTDN). Therefore, mobile apps can not send events to analytical systems correctly and on-time. For example, if the user subscribed and then didn't open the app, without a server developer will get zero information about subscription status.

After installing Adapty SDK and setting up App Store Server Notifications for iOS and Real-time Developer Notifications (RTDN). for Android, Adapty receives info about your customer behavior and converts it into human-readable events.

📘

Adapty processes events into human-readable format instantly as they created and enriches them with additional information, such as customer ID, consecutive payments, store commission info, and others. Besides that Apple doesn't send events about subscription renewals but we do.

Events

Event NameDescription
subscription_startedA user has activated a subscription without a trial period i.e. he was billed instantly.
subscription_renewedA subscription was renewed and the user was charged. For both trial and non-trial subscriptions, this event is sent starting from the second billing.
subscription_expiredA user has canceled a subscription and it is completely finished.
trial_startedA user has activated a trial subscription.
trial_convertedA trial period has ended and the user was billed, i.e. first purchase was made.
trial_expiredA trial has expired without converting to a subscription.
non_subscription_purchaseAny non-subscription purchase e.g. lifetime access or consumable product such as coins.
billing_issue_detectedAn attempt to charge the user was made, but a billing issue happened. Usually, it means the user doesn't have enough card balance.
entered_grace_periodThe payment was not successful and the user entered into a grace period. The user still has access to the premium features of your app until the grace period is finished.
trial_renewal_cancelledA user turned off subscription auto-renewal during the trial. A user still has access to the premium features of your app until the end of the trial period.
trial_renewal_reactivatedA user turned on subscription auto-renewal during the trial period.
subscription_renewal_cancelledA user turned off subscription auto-renewal. A user still has access to the premium features of your app until the end of the subscription period.
subscription_renewal_reactivatedA user turned on subscription auto-renewal.
subscription_refundedA subscription was refunded (e.g. by Apple support).
non_subscription_purchase_refundedNon-subscription purchase was refunded.
subscription_pausedUser activated subscription pause (Android only).
subscription_deferredA user's subscription has been deferred, ie they were granted free usage time (Android only). Usually, it happens in response to an API call from your servers.
access_level_updatedUser's access level updated (Webhook only).

📘

SUBSCRIPTION_EXPIRED(previously SUBSCRIPTION_CANCELED) event means that the subscription completely finished and the user has no longer access to the premium features of the app. When the user unsubscribes, AUTO_RENEW_OFF or AUTO_RENEW_OFF_SUBSCRIPTION is sent. The same logic applied to TRIAL_CANCELLED.

The events above fully cover the users' state in terms of purchases. Let's look at some examples.

Example 1

The user has activated a monthly subscription on April 1st with 7 days trial. On the 4th day, he unsubscribed.

In that case following events will be sent:

  1. trial_started on April 1st
  2. auto_renew_off on 4th April
  3. trial_cancelled on 7th April

Example 2

The user has activated a monthly subscription on April 1st with 7 days trial. On the 10th day, he unsubscribed.

In that case following events will be sent:

  1. trial_started on April 1st
  2. trial_converted on April 7th
  3. auto_renew_off_subscription on April 10th
  4. subscription_cancelled on May 1st

Properties

PropertyTypeDescription
profile_iduuidAdapty user ID.
currencystrLocal currency (defaults to USD).
price_usdfloatProduct price before Apple/Google cut. Revenue.
proceeds_usdfloatProduct price after Apple/Google cut. Net revenue.
price_localfloatProduct price before Apple/Google cut in local currency. Revenue.
proceeds_localfloatProduct price after Apple/Google cut in local currency. Net revenue.
transaction_idstrA unique identifier for a transaction such as a purchase or renewal.
original_transaction_idstrThe transaction identifier of the original purchase.
purchase_dateISO 8601 dateThe date and time of product purchase.
original_purchase_dateISO 8601 dateThe date and time of the original purchase.
environmentstrCan be Sandbox or Production.
vendor_product_idstrProduct id in Apple/Google store.
event_datetimeISO 8601 dateThe date and time of the event.
storestrCan be app_store or play_store.
trial_durationstrDuration of a trial period in days. Sent in a format "{} days" , for example, "7 days".
cancellation_reasonstrA reason why the user canceled a subscription.

Can be
iOS & Android
voluntarily_cancelled, billing_error, refund
iOS
price_increase, product_was_not_available, unknown
Android
new_subscription_replace, cancelled_by_developer
subscription_expires_atISO 8601 dateThe Expiration date of subscription. Usually in the future.
consecutive_paymentsintThe number of periods, that a user is subscribed without interruptions. Includes the current period.
rate_after_first_yearboolBoolean indicates that a vendor reduces cuts to 15%. Apple and Google have 30% first-year cut and 15% after it.
promotional_offer_idstrID of promotional offer as indicated in Product section of Adapty dashboard
store_offer_categorystrCan be introductory or promotional.
store_offer_discount_typestrCan be free_trial, pay_as_you_go or pay_up_front.
paywall_namestrName of the paywall where the transaction originated.
paywall_revisionintRevision of the paywall where the transaction originated. The value is set to 1.
developer_idstrDeveloper (SDK) ID of the placement where the transaction originated.
ab_test_namestrName of the A/B test where the transaction originated.
ab_test_revisionintRevision of the A/B test where the transaction originated. The value is set to 1.
cohort_namestrName of the audience to which the profile belongs to.
profile_event_iduuidUnique event ID that can be used for deduplication.
store_countrystrThe country sent to us by the store.
profile_ip_addressstrProfile IP (can be IPv4 or IPv6, with IPv4 preferred when available). It is updated each time IP of the device changes.
profile_countrystrDetermined by Adapty, based on profile IP.
profile_total_revenue_usdfloatTotal revenue for the profile, refunds included.
variation_iduuidUnique ID of the paywall where the purchase was made.
access_level_idstrPaid access level ID
is_activeboolBoolean indicating whether paid access level is active for the profile.
will_renewboolBoolean indicating whether paid access level will be renewed.
is_refundboolBoolean indicating whether transaction is refunded.
is_lifetimeboolBoolean indicating whether paid access level is lifetime.
is_in_grace_periodboolBoolean indicating whether profile is in grace period.
starts_atISO 8601 dateDate and time when paid access level starts for the user.
renewed_atISO 8601 dateDate and time when paid access will be renewed.
expires_atISO 8601 dateDate and time when paid access will expire.
activated_atISO 8601 dateDate and time when paid access was activated.
billing_issue_detected_atISO 8601 dateDate and time of billing issue.

Each event has the following properties:

transaction_id, original_transaction_id, purchase_date, original_purchase_date, environment, vendor_product_id, event_datetime, store.

In addition, some events have additional properties. For the events subscription_refunded and non_subscription_purchase_refunded, it is mandatory to provide the values of price_usd and proceeds_usd as additional properties.

Event NameProperties
subscription_initial_purchaseprice_usd, proceeds_usd, subscription_expires_at, consecutive_payments, rate_after_first_year, trial_duration
subscription_renewedprice_usd, proceeds_usd, subscription_expires_at, consecutive_payments, rate_after_first_year, trial_duration
subscription_cancelledcancellation_reason, trial_duration
trial_startedsubscription_expires_at, trial_duration
trial_convertedprice_usd, proceeds_usd, subscription_expires_at, consecutive_payments, rate_after_first_year, trial_duration
trial_cancelledcancellation_reason, trial_duration
non_subscription_purchaseprice_usd, proceeds_usd
billing_issue_detectedsubscription_expires_at, trial_duration
entered_grace_periodsubscription_expires_at, trial_duration

Event example

{
    "price_usd": 9.99,
    "proceeds_usd": 6.99,
    "transaction_id": "1000000628581600",
    "original_transaction_id": "1000000628581600",
    "purchase_date": "2020-02-18T18:40:22.000000+0000",
    "original_purchase_date": "2020-02-18T18:40:22.000000+0000",
    "environment": "Sandbox",
    "vendor_product_id": "premium",
    "event_datetime": "2020-02-18T18:40:22.000000+0000",
    "store": "app_store"
}

Adapty sends events to your server and 3rd party analytical systems.

profile_ip_address property is synchronized with the current device IP. Each time the Adapty servers receive info from the SDK, the IP will be updated if it differs from the one we have on record.

Access level updated

Adapty has a special event access_level_updated. It is sent only to webhook integration every time the access level is updated/set for a specific customer. Use this event to update a customer's subscription in your database/system. Before you had to keep track of several events to sync subscription state and some cases were not covered, like setting access level manually from Adapty CRM. Now, no matter what was the source of access level changes, you will always receive a dedicated event for that, therefore it's more precise and has more details than subscription_renewed, trial_started, entered_grace_period, etc.

Events

PropertyType
storestr
currencystr
is_activebool
is_refundbool
expires_atISO 8601 date
starts atISO 8601 date
profile_idstr
renewed_atISO 8601 date
will_renewbool
environmentstr
is_lifetimebool
activated_atISO 8601 date
purchase_dateISO 8601 date
store_countrystr
event_datetimeISO 8601 date
transaction_idstr
access_level_idstr
profile_countrystr
profile_event_idstr
vendor_product_idstr
is_in_grace_periodbool
original_purchase_dateISO 8601 date
original_transaction_idstr
subscription_expires_atISO 8601 date
profile_total_revenue_usdfloat
billing_issue_detected_atISO 8601 date
cancellation_reasonstr
active_introductory_offer_typestr
active_promotional_offer_typestr
active_promotional_offer_idstr

We don't send access_level_updated upon subscription expiration - please, refer to expires_at value to end the subscriptions on your side.

Please note that some properties can only be set using the grant Server-Side API method. You can find more information about this method in the Adapty Server-Side API documentation.

For detailed descriptions of the mentioned properties, you can refer to the API objects documentation.

Sending failed

We determine the deliverability based on HTTP status and consider everything outside the 200-399 range to be a fail.

You can see the status of certain integration events in the event list in the Adapty dashboard. The system displays the statuses of integrations that are enabled for the app, regardless of whether the event type is enabled or disabled for a specific integration. If the event type is disabled for a particular integration, it will be color-coded as gray in the event feed. If there are any issues with integration, the integration name will be highlighted in red, indicating that attention is required to resolve the problem. In addition, the system provides tooltips when you hover over the integration name. These tooltips offer more detailed information about the reasons for the non-delivery of an event.

Event feed in Adapty dashboard

Event feed in Adapty dashboard

The Event feed utilizes a limitation on the number of events displayed, showing data from the past two weeks. This implementation enhances the loading speed of the page, enabling users to navigate and analyze data more efficiently.