Skip to main content
Answer

RevenueCat Adjust integration: Trial started event is not emitted for App Store offer codes

  • November 24, 2025
  • 3 replies
  • 44 views

Forum|alt.badge.img

We have a working Adjust integration in RevenueCat, but we noticed a large discrepancy in the amount of “active trials” visible in RevenueCat and the amount of tracked “Trial started“ events in Adjust. Currently, there are more than double active trials in RevenueCat than the corresponding events tracked in Adjust.

We think it’s because our marketing is relying heavily on App Store’s “Offer codes”. Currently we recommend the user to redeem the discounts via the App Store, as is also recommended by RevenueCat due to Apple’s buggy implementation of the offer code redeem screen in iOS.

We suspect that RevenueCat is not sending “Trial Started” events to Adjust if a user starts a 3 months free trial via an offer code. Can you confirm this? Is this a bug or is this intentional? What alternative do you suggest to have more reliable stats on the total amount of trials started on Adjust’s side?

Best answer by hussain

Hi ​@tiziano-coroneo-social-army,

Thanks for reaching out. I’m happy to help.

RevenueCat does not exclude App Store offer-code trials from Adjust. An event is sent to Adjust so long as the required Adjust device identifier is present on the customer profile at the moment the event is processed. In other words, offer codes aren’t treated specially; the gating factor is whether the $adjustId was already set when the trial began/was ingested.

What I am seeing in your project lines up with a timing issue rather than an offer-code bug. In all the profiles I checked where a trial start occurred but an event was not forwarded to Adjust, the $adjustId wasn’t set at the time the event occurred. As an example for one of the profiles the trial started at 11:29 but the $adjustId wasn’t set until 11:34. Because the Adjust ID didn’t exist on the customer when the trial event reached RevenueCat, there was no Adjust payload to send for that event. This behavior matches the integration’s requirement that the Adjust-specific customer attribute be present for events to be forwarded.

Two things can make this more likely to happen:

  1. By default, subscriber attributes (like $adjustId) sync on configure/background/purchase, which means there can be a short window where a trial is recorded before the attribute reaches our servers. We provide a helper function (syncAttributesAndOfferingsIfNeeded) to force an immediate attribute sync in those cases.

  2. You currently have “Track new purchases from server-to-server notifications” enabled. That setting lets RevenueCat record purchases directly from Apple’s server notifications before the device SDK sends anything. If Apple’s notification arrives first, the trial can be ingested before your app has posted the $adjustId, and the Adjust event won’t be sent.

In this case I’d recommend the following approach to mitigate this issue:

  • Set the $adjustId as early as possible in the session, ideally immediately after initializing the SDK and before any paywall is shown. (This attribute is required for Adjust forwarding.)

  • Force an immediate attribute sync right after setting $adjustId and before fetching/showing offerings or presenting a paywall: call syncAttributesAndOfferingsIfNeeded() once you’ve set the attribute. This reduces the chance of an event being processed without the Adjust ID on file.

  • Consider disabling “Track new purchases from server-to-server notifications.” With this off, the device SDK’s post (which includes your $adjustId) is more likely to reach RevenueCat before we ingest Apple’s notification, reducing these race conditions. You can still keep store notifications enabled for renewals and status updates; this suggestion targets only the “track new purchases” option.

Hope this helps, let me know if you have any other questions.

Best,

Hussain

3 replies

hussain
RevenueCat Staff
Forum|alt.badge.img+6
  • RevenueCat Staff
  • Answer
  • November 28, 2025

Hi ​@tiziano-coroneo-social-army,

Thanks for reaching out. I’m happy to help.

RevenueCat does not exclude App Store offer-code trials from Adjust. An event is sent to Adjust so long as the required Adjust device identifier is present on the customer profile at the moment the event is processed. In other words, offer codes aren’t treated specially; the gating factor is whether the $adjustId was already set when the trial began/was ingested.

What I am seeing in your project lines up with a timing issue rather than an offer-code bug. In all the profiles I checked where a trial start occurred but an event was not forwarded to Adjust, the $adjustId wasn’t set at the time the event occurred. As an example for one of the profiles the trial started at 11:29 but the $adjustId wasn’t set until 11:34. Because the Adjust ID didn’t exist on the customer when the trial event reached RevenueCat, there was no Adjust payload to send for that event. This behavior matches the integration’s requirement that the Adjust-specific customer attribute be present for events to be forwarded.

Two things can make this more likely to happen:

  1. By default, subscriber attributes (like $adjustId) sync on configure/background/purchase, which means there can be a short window where a trial is recorded before the attribute reaches our servers. We provide a helper function (syncAttributesAndOfferingsIfNeeded) to force an immediate attribute sync in those cases.

  2. You currently have “Track new purchases from server-to-server notifications” enabled. That setting lets RevenueCat record purchases directly from Apple’s server notifications before the device SDK sends anything. If Apple’s notification arrives first, the trial can be ingested before your app has posted the $adjustId, and the Adjust event won’t be sent.

In this case I’d recommend the following approach to mitigate this issue:

  • Set the $adjustId as early as possible in the session, ideally immediately after initializing the SDK and before any paywall is shown. (This attribute is required for Adjust forwarding.)

  • Force an immediate attribute sync right after setting $adjustId and before fetching/showing offerings or presenting a paywall: call syncAttributesAndOfferingsIfNeeded() once you’ve set the attribute. This reduces the chance of an event being processed without the Adjust ID on file.

  • Consider disabling “Track new purchases from server-to-server notifications.” With this off, the device SDK’s post (which includes your $adjustId) is more likely to reach RevenueCat before we ingest Apple’s notification, reducing these race conditions. You can still keep store notifications enabled for renewals and status updates; this suggestion targets only the “track new purchases” option.

Hope this helps, let me know if you have any other questions.

Best,

Hussain


Forum|alt.badge.img

Thank you for this fantastic answer! This probably also explains some other data issues we have. I implemented both your suggestions, and I’ll be back to bother you if something still looks off 😅

 


hussain
RevenueCat Staff
Forum|alt.badge.img+6
  • RevenueCat Staff
  • December 1, 2025

Hi ​@tiziano-coroneo-social-army ,

Thanks for following up. I’m happy I was able to help.

Feel free to reach out if you have any other questions. I’m always happy to assist.

Best,

Hussain