<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luke Hoang</title>
    <description>The latest articles on DEV Community by Luke Hoang (@lukehoang_ab).</description>
    <link>https://dev.to/lukehoang_ab</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4151244%2Fe9f3a825-5f93-486a-becb-de5ca2109f24.png</url>
      <title>DEV Community: Luke Hoang</title>
      <link>https://dev.to/lukehoang_ab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lukehoang_ab"/>
    <language>en</language>
    <item>
      <title>RevenueCat + Meta Ads: why your trial starts don't show up (a debugging checklist)</title>
      <dc:creator>Luke Hoang</dc:creator>
      <pubDate>Wed, 11 Nov 2026 03:49:01 +0000</pubDate>
      <link>https://dev.to/lukehoang_ab/revenuecat-meta-ads-why-your-trial-starts-dont-show-up-a-debugging-checklist-51kg</link>
      <guid>https://dev.to/lukehoang_ab/revenuecat-meta-ads-why-your-trial-starts-dont-show-up-a-debugging-checklist-51kg</guid>
      <description>&lt;p&gt;RevenueCat shows 40 trial starts this week. Meta Ads Manager shows 3. Both tools are working. They just aren't counting the same thing. This is a debugging checklist for the RevenueCat Meta Ads integration, written for the engineer who gets pinged when those two numbers don't match.&lt;/p&gt;

&lt;p&gt;Quick disclosure: I work in product marketing at Airbridge, a mobile measurement company, and this question comes up often in our conversations with app teams. I drafted this post with help from an AI assistant and checked each step against RevenueCat's and Meta's own docs. The numbers in the examples are illustrative.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When trial starts are missing, check the setup first: device identifiers, the iOS ATT setting, and the dataset and token.&lt;/li&gt;
&lt;li&gt;"Delivered" in RevenueCat means Meta received the event. Matching and attribution happen on Meta's side, and Events Manager can take up to 24 hours to show it.&lt;/li&gt;
&lt;li&gt;If Meta shows &lt;em&gt;more&lt;/em&gt; purchases than RevenueCat, turn off the Meta SDK's automatic purchase logging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How RevenueCat sends trial starts to Meta Ads
&lt;/h2&gt;

&lt;p&gt;Two things talk to Meta, and they do different jobs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Meta SDK in your app&lt;/strong&gt; still handles installs, app opens and on-device iOS measurement (SKAdNetwork and Aggregated Event Measurement).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RevenueCat&lt;/strong&gt; sends subscription events &lt;strong&gt;server-to-server&lt;/strong&gt;, from its backend to Meta. The recommended path is Meta's &lt;a href="https://www.revenuecat.com/docs/integrations/attribution/meta-ads" rel="noopener noreferrer"&gt;Conversions API&lt;/a&gt;, which needs a Dataset ID and a Conversions API access token from Events Manager. An older path, the App Events API, uses a Meta App ID and client token instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flhixrlmd5j9j3qxypnuc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flhixrlmd5j9j3qxypnuc.png" alt="How a trial start reaches Meta Ads: the Meta SDK sends installs, app opens and SKAN/AEM from the device, while RevenueCat sends StartTrial and Subscribe server-to-server through the Conversions API" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The two paths into Meta. Steps 1–3 below cover the server-to-server path; step 4 covers the last step, where Meta matches and attributes. Diagram by the author, made with AI assistance.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By default, RevenueCat maps its events to Meta events like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;RevenueCat event&lt;/th&gt;
&lt;th&gt;Meta event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Trial started&lt;/td&gt;
&lt;td&gt;&lt;code&gt;StartTrial&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trial converted&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Subscribe&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Initial purchase (no trial)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Subscribe&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Renewal&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Subscribe&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-renewing purchase&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fb_mobile_purchase&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So the trial start and the payment that follows it are two separate Meta events, sent at two different times. Keep that in mind for step 6.&lt;/p&gt;

&lt;p&gt;Work through the steps in order. Each one tells you where to go next.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Did RevenueCat send the event at all?
&lt;/h2&gt;

&lt;p&gt;Open a customer who started a trial, then open their &lt;strong&gt;Customer History&lt;/strong&gt;. Look for a &lt;strong&gt;"Meta Ads delivery"&lt;/strong&gt; row on the trial event. The Request and Response tabs show exactly what RevenueCat sent and what Meta answered. Meta's responses can include an &lt;code&gt;fbtrace_id&lt;/code&gt;, which is useful if you ever need to ask Meta support about a specific event.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No delivery row: go to step 2.&lt;/li&gt;
&lt;li&gt;A row with an error: go to step 3.&lt;/li&gt;
&lt;li&gt;A row that succeeded: go to step 4.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  2. Does the customer have the identifiers Meta needs?
&lt;/h2&gt;

&lt;p&gt;RevenueCat only tries to deliver an event when the customer has the required attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;App Store, via Conversions API:&lt;/strong&gt; &lt;code&gt;$fbAnonId&lt;/code&gt; or &lt;code&gt;$idfa&lt;/code&gt;, &lt;strong&gt;plus&lt;/strong&gt; an ATT consent status of &lt;code&gt;authorized&lt;/code&gt;, unless you turn on &lt;strong&gt;"Send events when ATT consent is not authorized"&lt;/strong&gt; in the integration settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Play:&lt;/strong&gt; &lt;code&gt;$fbAnonId&lt;/code&gt; or &lt;code&gt;$gpsAdId&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;An all-zeros IDFA or GAID counts as missing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see these on the customer's profile under Attributes. If they're empty, the app isn't collecting them. RevenueCat's recommended flow on iOS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nc"&gt;RevenueCat&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nc"&gt;FBSDKCoreKit&lt;/span&gt;            &lt;span class="c1"&gt;// AppEvents&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nc"&gt;AppTrackingTransparency&lt;/span&gt;

&lt;span class="nc"&gt;Purchases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;withAPIKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;your_public_api_key&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Collect right after configure, even before the ATT prompt&lt;/span&gt;
&lt;span class="nc"&gt;Purchases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collectDeviceIdentifiers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Pass Meta's anonymous ID (RevenueCat marks this as required on iOS)&lt;/span&gt;
&lt;span class="nc"&gt;Purchases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setFBAnonymousID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AppEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;anonymousID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Collect again once the user allows tracking, so the IDFA is picked up&lt;/span&gt;
&lt;span class="nc"&gt;ATTrackingManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;requestTrackingAuthorization&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;authorized&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Purchases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collectDeviceIdentifiers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And on Android:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;facebook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;appevents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AppEventsLogger&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;revenuecat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;purchases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Purchases&lt;/span&gt;

&lt;span class="nc"&gt;Purchases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sharedInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collectDeviceIdentifiers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Meta's anonymous ID on Android&lt;/span&gt;
&lt;span class="nc"&gt;Purchases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sharedInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setFBAnonymousID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;AppEventsLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAnonymousAppDeviceGUID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;On iOS:&lt;/strong&gt; many people decline the ATT prompt. With the default setting, RevenueCat does not send their App Store events through the Conversions API, so those trial starts aren't sent to Meta. That alone can explain a large difference between the two dashboards. Whether to turn on "Send events when ATT consent is not authorized" is a privacy decision, not a debugging one. Talk to whoever owns privacy in your team and read Apple's and Meta's rules before you change it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Is the integration pointed at the right place?
&lt;/h2&gt;

&lt;p&gt;If RevenueCat tried to send the event and Meta returned an error, check the setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Is the dataset linked to your app?&lt;/strong&gt; Meta &lt;a href="https://developers.facebook.com/docs/marketing-api/conversions-api/app-events" rel="noopener noreferrer"&gt;requires a dataset to be linked to an application&lt;/a&gt; before it accepts mobile app events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production vs. sandbox.&lt;/strong&gt; RevenueCat lets you set a separate sandbox Dataset ID and token. If you set them, sandbox purchases go there instead of your production dataset.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does the token belong to that dataset?&lt;/strong&gt; Make sure the access token was generated for the dataset you entered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which path are you on?&lt;/strong&gt; The Conversions API needs a Dataset ID and access token. The older App Events API needs an App ID and client token. Make sure the fields you filled in match the path you chose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To test, make a sandbox purchase with a brand-new customer, then check that customer's attributes and Customer History.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Meta accepted the event. Why isn't it in my campaign?
&lt;/h2&gt;

&lt;p&gt;A successful delivery means Meta &lt;strong&gt;received&lt;/strong&gt; the event. Meta still decides whether it can match it to a person and credit it to an ad. A few things to check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Give it time.&lt;/strong&gt; Events Manager &lt;a href="https://www.revenuecat.com/docs/integrations/attribution/meta-ads" rel="noopener noreferrer"&gt;can take up to 24 hours&lt;/a&gt; to show accepted events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare Events Manager with Ads Manager.&lt;/strong&gt; If &lt;code&gt;StartTrial&lt;/code&gt; shows up in your dataset but not in campaign results, the pipeline works. What's left is how Meta matches the people it can identify. That's expected behavior, not a bug in your code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iOS campaigns have their own measurement.&lt;/strong&gt; For iOS 14.5+ app campaigns, Meta measures through SKAdNetwork or &lt;a href="https://developers.facebook.com/docs/app-ads/SKAdNetwork-aem-and-limitations/" rel="noopener noreferrer"&gt;Aggregated Event Measurement&lt;/a&gt;, chosen per ad set. By design, SKAN and AEM live in your app with the Meta SDK, and RevenueCat leaves SKAN conversion values to that setup. Use &lt;strong&gt;one&lt;/strong&gt; tool to update conversion values, or they will overwrite each other.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is also the point where many teams start asking how a subscription platform like RevenueCat and an attribution tool fit together. We wrote up &lt;a href="https://www.airbridge.io/en/blog/do-i-need-an-mmp-with-revenuecat?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=get_found_w46&amp;amp;utm_content=revenuecat-meta-trial-starts-missing" rel="noopener noreferrer"&gt;how the two work side by side for RevenueCat apps&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Are you counting purchases twice?
&lt;/h2&gt;

&lt;p&gt;This is the opposite case: Meta shows &lt;strong&gt;more&lt;/strong&gt; purchases or revenue than RevenueCat.&lt;/p&gt;

&lt;p&gt;The Meta SDK can log in-app purchases automatically. RevenueCat also sends &lt;code&gt;Subscribe&lt;/code&gt;. Because the two are sent separately, without a shared &lt;code&gt;event_id&lt;/code&gt;, they can be counted as two purchases. The fix is to turn off the SDK's automatic purchase logging for the events RevenueCat already sends:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Meta app dashboard:&lt;/strong&gt; on the iOS or Android platform card (Settings → Basic), set automatic in-app purchase logging to &lt;strong&gt;No&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In code:&lt;/strong&gt; &lt;code&gt;Settings.shared.isAutoLogAppEventsEnabled = false&lt;/code&gt;. Note that this turns off &lt;strong&gt;all&lt;/strong&gt; automatic logging, not only purchases, so make sure installs and app opens are still being logged.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Are you looking before the money exists?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;StartTrial&lt;/code&gt; arrives when the trial starts. The &lt;code&gt;Subscribe&lt;/code&gt; for that same user only arrives when the trial converts. Apple &lt;a href="https://developer.apple.com/documentation/storekit/handling-subscriptions-billing" rel="noopener noreferrer"&gt;doesn't bill a free trial until the trial ends&lt;/a&gt;, and the App Store starts trying to renew in the 24 hours before the period expires.&lt;/p&gt;

&lt;p&gt;With a 7-day trial, the first payment shows up about a week after the ad click, which is right where Meta's default 7-day click window ends. If your campaign optimizes for &lt;code&gt;Subscribe&lt;/code&gt; and you judge it after three days, there's very little data to judge it on yet. Many small apps optimize for &lt;code&gt;StartTrial&lt;/code&gt; instead and track trial-to-paid in their subscription data. I wrote about this timing in more detail in &lt;a href="https://medium.com/@ngoc_82606/metas-attribution-window-vs-your-free-trial-why-your-roas-looks-worse-than-it-is-3d48016c30bd" rel="noopener noreferrer"&gt;Meta's attribution window vs. your free trial&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Copy-paste checklist
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ] Customer History shows a "Meta Ads delivery" row for the trial event
[ ] Customer has $fbAnonId (iOS: setFBAnonymousID is called) and/or $idfa / $gpsAdId
[ ] collectDeviceIdentifiers() runs after configure AND after ATT is granted
[ ] Team has decided on "Send events when ATT consent is not authorized"
[ ] Dataset is linked to the app; production vs. sandbox IDs and tokens are right
[ ] Waited 24 hours before judging Events Manager
[ ] iOS: SKAN / AEM set up in Meta; only one tool updates conversion values
[ ] Meta SDK automatic purchase logging is off (no double Subscribe)
[ ] Campaign optimizes for an event that arrives in time (StartTrial vs. Subscribe)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Does RevenueCat send trial starts to Meta Ads?
&lt;/h3&gt;

&lt;p&gt;Yes. By default, a RevenueCat "Trial started" event is sent to Meta as &lt;code&gt;StartTrial&lt;/code&gt;, server-to-server, as long as the customer has the required identifiers (step 2).&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does Meta show fewer trials than RevenueCat?
&lt;/h3&gt;

&lt;p&gt;Usually because some events were never sent (missing identifiers, or iOS users who declined ATT), were sent but haven't shown up yet (up to 24 hours), or were received but not attributed to an ad.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does Meta show more purchases than RevenueCat?
&lt;/h3&gt;

&lt;p&gt;Usually double counting: the Meta SDK logs the purchase automatically and RevenueCat sends &lt;code&gt;Subscribe&lt;/code&gt; for the same purchase (step 5).&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I still need the Meta SDK if RevenueCat sends events?
&lt;/h3&gt;

&lt;p&gt;Yes. RevenueCat covers subscription events. The Meta SDK still handles installs, app opens, the anonymous ID RevenueCat passes along, and on-device iOS measurement.&lt;/p&gt;




&lt;p&gt;If you hit a failure mode that isn't on this list, tell me in the comments and I'll add it.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>android</category>
      <category>mobile</category>
      <category>analytics</category>
    </item>
  </channel>
</rss>
