From f85e23ed0894e11914f9d85556329a9aa64f1fb8 Mon Sep 17 00:00:00 2001 From: Jean-Emmanuel BAILLAT Date: Wed, 28 Oct 2026 12:42:10 +0100 Subject: [PATCH 1/2] docs(appevents): state that app opens need automatic logging facebook-core 19.0.0 logs fb_mobile_activate_app and the deactivation event through InternalAppEventsLogger.logEvent, which returns early while FacebookSdk.getAutoLogAppEventsEnabled() is false. ActivateApp() with automatic logging off therefore sends only the install ping. Document the supported recipe (enable automatic logging after consent, turn automatic purchase logging off on the App Dashboard Android card when a server reports purchases), that the flag persists across launches, that the effective value also needs Events Manager not to disable it, and that turning it off stops automatic events at once. Co-Authored-By: Claude Opus 5.5 --- Docs/Integration.md | 55 +++++++++++++------ .../Facebook/FacebookAppEvents.cs | 43 +++++++++------ 2 files changed, 63 insertions(+), 35 deletions(-) diff --git a/Docs/Integration.md b/Docs/Integration.md index 87589ea..2830dfb 100644 --- a/Docs/Integration.md +++ b/Docs/Integration.md @@ -112,7 +112,7 @@ value, and a persisted value wins over the manifest on later launches. | Manifest `meta-data` (`com.facebook.sdk.`) | Runtime API | Effect | | --- | --- | --- | | `AutoInitEnabled` | `SetAutoInitEnabled`, `IsAutoInitEnabled` | `false` keeps the SDK from fully initializing; the SDK does not process Graph API responses until then. | -| `AutoLogAppEventsEnabled` | `SetAutoLogAppEventsEnabled`, `IsAutoLogAppEventsEnabled` | Automatic install ping, app activation and, when Events Manager allows it, Google Play purchase and subscription events. Since 19.0.0 a local `false` wins over Events Manager. | +| `AutoLogAppEventsEnabled` | `SetAutoLogAppEventsEnabled`, `IsAutoLogAppEventsEnabled` | The SDK's automatic events: app activation and deactivation (`fb_mobile_activate_app`, `fb_mobile_deactivate_app`, even when `ActivateApp()` started tracking) and, when the App Dashboard allows it, Google Play purchase and subscription events. It does not cover the install ping, which only `ActivateApp()` sends. The effective value is the local value and the Events Manager value: since 19.0.0 a local `false` always wins, and disabling automatic SDK event logging in Events Manager overrides a local `true`. | | `AdvertiserIDCollectionEnabled` | `SetAdvertiserIdCollectionEnabled`, `IsAdvertiserIdCollectionEnabled` | Advertising ID collection. | | `AutoLogMetaDataEnabled` | `SetMetadataCollectionEnabled`, `IsMetadataCollectionEnabled` | SDK 19.0.0+: attaches the screen title and AppLink URL to events. `false` also discards what was collected. | | `AutoLogProductImprovementEnabled` | `SetAutoLogProductImprovementEnabled`, `IsAutoLogProductImprovementEnabled` | SDK 19.0.0+: control for product-improvement data. The 19.0.0 changelog says the SDK does not collect such data yet. | @@ -143,17 +143,34 @@ SDK (see the strictest setup below). { FacebookAppEvents.SetAutoInitEnabled(true); FacebookAppEvents.SetAdvertiserIdCollectionEnabled(true); - // Either let the SDK log automatically ... - // FacebookAppEvents.SetAutoLogAppEventsEnabled(true); - // ... or keep automatic logging off and log activation yourself. ActivateApp() - // sends the one-time install ping and starts activation tracking, which logs - // fb_mobile_activate_app from the next activity resume on. Call it after - // auto-init is enabled, or the SDK discards the ping response. - FacebookAppEvents.SetAutoLogAppEventsEnabled(false); + // App opens (fb_mobile_activate_app) are automatic events: they need + // automatic logging on. + FacebookAppEvents.SetAutoLogAppEventsEnabled(true); + // One-time install ping, and activity tracking. Call it after auto-init + // is enabled, or the SDK discards the ping response. FacebookAppEvents.ActivateApp(); } ``` + `ActivateApp()` alone does not measure app opens. It sends the install ping + and starts activity tracking, but facebook-core 19.0.0 logs the activation + and deactivation events through its automatic-event path, which drops them + while automatic logging is off. With `SetAutoLogAppEventsEnabled(false)`, + the app reports the install and nothing else. + + Automatic logging also turns on automatic Google Play purchase and + subscription logging. When a server already reports purchases (see + [Avoid double counting](#avoid-double-counting-with-server-side-events)), + set "Log In-App Purchases Automatically" and "Log In-App Subscriptions + Automatically" to "No" on the Android card of the Meta App Dashboard + (Settings > Basic) before you enable it. In Events Manager, leave the + dataset's automatic SDK event logging setting unspecified so the app + decides: disabling it there overrides a local `true` once the SDK cached + the app settings, and app opens stop. + + `SetAutoLogAppEventsEnabled` persists its value across launches, so the + withdrawal branch must set it back to `false` (step 3). + When consent is first granted from a dialog, the activity is already resumed, so that session's activation is only counted from the next resume. Do not log `fb_mobile_activate_app` yourself to make up for it: the SDK owns @@ -172,18 +189,17 @@ SDK (see the strictest setup below). ``` Withdrawal fully takes effect on the next process start. Until then the - SDK stays fully initialized: it keeps flushing queued events and, once - `ActivateApp()` or automatic logging started activity tracking, keeps - logging `fb_mobile_activate_app` and deactivation on every resume; none of - the switches above stops that. So: + SDK stays fully initialized and keeps flushing queued events. Activity + tracking keeps running too, but `SetAutoLogAppEventsEnabled(false)` stops + the activation, deactivation and automatic purchase events at once: the SDK + checks the flag for every automatic event. So: - gate your own `Log*` calls on the consent state, so manual events stop at once; - set `ExplicitOnly` and do not call `Flush()` until the process restarts, so nothing more is sent in this process; - - events already queued (including the activation events logged meanwhile) - stay in the SDK's disk queue, and a later fully initialized session (after - consent is granted again) sends them. + - events already queued stay in the SDK's disk queue, and a later fully + initialized session (after consent is granted again) sends them. The SDK cannot delete events it already sent; that goes through Meta's data deletion process. @@ -247,9 +263,12 @@ event ID shared by both sides, and such integrations do not coordinate one with the SDK. When a server already sends trial, subscription or purchase events: - do not log those events from the app as well; -- disable automatic purchase logging: keep `AutoLogAppEventsEnabled=false` and - call `ActivateApp()` (install and activation are still measured), and/or set - "Log In-App Events Automatically" to "No" in the Meta App Dashboard. +- disable automatic purchase logging on the Android card of the Meta App + Dashboard (Settings > Basic): "Log In-App Purchases Automatically" and "Log + In-App Subscriptions Automatically" on "No". Keep `AutoLogAppEventsEnabled` + on after consent if you measure app opens: they are automatic events too. + With `AutoLogAppEventsEnabled=false`, `ActivateApp()` only measures the + install. ### Identity diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Facebook/FacebookAppEvents.cs b/src/Kapusch.FacebookApisForAndroidComponents/Facebook/FacebookAppEvents.cs index 69942a7..4733211 100644 --- a/src/Kapusch.FacebookApisForAndroidComponents/Facebook/FacebookAppEvents.cs +++ b/src/Kapusch.FacebookApisForAndroidComponents/Facebook/FacebookAppEvents.cs @@ -19,10 +19,11 @@ namespace Kapusch.Facebook.Android; /// /// /// Turning switches off does not stop the SDK for the current process: it stays fully initialized, -/// keeps flushing queued events and, once or automatic logging started -/// activity tracking, keeps logging activation on every activity resume. Withdrawal fully applies -/// on the next process start. Until then, stop calling the Log* methods and set -/// without calling . +/// keeps flushing queued events and keeps activity tracking running. +/// with stops the automatic events +/// (activation, deactivation, purchases) at once. Withdrawal fully applies on the next process start. Until then, stop calling the +/// Log* methods and set without +/// calling . /// /// /// Every setter, the identity methods and the event methods throw @@ -129,11 +130,18 @@ public static void InitializeSdk( /// /// Sets the persisted automatic App Events logging flag. starts activity - /// tracking, which requires an initialized SDK. Automatic logging covers the install ping, app - /// activation and, when enabled in Events Manager, in-app purchases and subscriptions. - /// does not stop activity tracking already started in this process; it - /// applies from the next process start. + /// tracking, which requires an initialized SDK. Automatic logging covers the SDK's automatic + /// events: app activation and deactivation (also when started + /// tracking) and, when enabled on the Android card of the Meta App Dashboard, in-app purchases and + /// subscriptions. It does not send the install ping; does. + /// stops automatic events at once (the SDK checks the flag for each one) + /// but leaves activity tracking running until the process ends. /// + /// + /// The value persists across launches. The effective value () + /// is when either this value or the Events Manager setting cached by the SDK + /// is disabled. + /// public static void SetAutoLogAppEventsEnabled(bool enabled) => CallVoid("setAutoLogAppEventsEnabled", "(Z)V", new JValue(enabled)); @@ -198,16 +206,17 @@ public static void SetFlushBehavior(FacebookAppEventsFlushBehavior behavior) } /// - /// Sends the one-time install ping and starts activation tracking - /// (AppEventsLogger.activateApp): the SDK logs fb_mobile_activate_app and - /// deactivation from the next activity resume on. An activity already resumed when this runs is - /// not counted, so call it on every launch before the first activity resumes, for example from + /// Sends the one-time install ping and starts activity tracking + /// (AppEventsLogger.activateApp). App opens (fb_mobile_activate_app) and + /// deactivation are automatic events: the SDK logs them from the next activity resume on only + /// while is . With automatic + /// logging off, this measures the install only. An activity already resumed when this runs is not + /// counted, so call it on every launch before the first activity resumes, for example from /// Application.OnCreate or MainActivity.OnCreate. When it runs right after a consent - /// dialog, that session is only counted from the next resume. Use it when automatic logging is - /// disabled and the consumer still wants install and launch measurement. Call it once the SDK is - /// fully initialized ( or ); before - /// that the SDK discards the install ping response and only retries on a later activation. - /// Tracking cannot be stopped until the process ends. + /// dialog, that session is only counted from the next resume. Call it once the SDK is fully + /// initialized ( or ); before that the + /// SDK discards the install ping response and only retries on a later activation. Tracking cannot + /// be stopped until the process ends. /// public static void ActivateApp(Context? context = null) => CallVoid("activateApp", "(Landroid/content/Context;)V", new JValue(ResolveContext(context))); From 811fa3239ce06343804bbefca51709c66067fd8f Mon Sep 17 00:00:00 2001 From: Jean-Emmanuel BAILLAT Date: Wed, 28 Oct 2026 12:42:11 +0100 Subject: [PATCH 2/2] docs(sample): enable automatic logging when ads consent is granted The sample kept automatic logging off and relied on ActivateApp() for app opens, which the bundled SDK does not log in that mode. Co-Authored-By: Claude Opus 5.5 --- samples/Kapusch.Facebook.Android.Sample/README.md | 15 +++++++++------ .../src/MainActivity.cs | 14 ++++++++------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/samples/Kapusch.Facebook.Android.Sample/README.md b/samples/Kapusch.Facebook.Android.Sample/README.md index c9dc5b2..7d4af70 100644 --- a/samples/Kapusch.Facebook.Android.Sample/README.md +++ b/samples/Kapusch.Facebook.Android.Sample/README.md @@ -44,12 +44,15 @@ the untracked `strings.xml` only; never commit them. The manifest template sets every automatic collection switch to `false` (`AutoInitEnabled`, `AutoLogAppEventsEnabled`, `AdvertiserIDCollectionEnabled`, `AutoLogMetaDataEnabled`, `AutoLogProductImprovementEnabled`). The sample's -"Grant ads consent" button enables auto-init and advertiser ID collection, then -calls `ActivateApp()` with automatic logging still off (activation is logged -from the next resume on); "Withdraw ads consent" reverts them and sets the -flush behavior to `ExplicitOnly`, because the SDK keeps tracking activation -until the process restarts. Debug builds enable `SetDebugLoggingEnabled(true)`, so logged and -flushed events appear in `adb logcat`. Use Meta Events Manager > Test events to +"Grant ads consent" button enables auto-init, advertiser ID collection and +automatic logging, then calls `ActivateApp()` (install ping; activation is +logged from the next resume on, and only while automatic logging is on); +"Withdraw ads consent" reverts them and sets the flush behavior to +`ExplicitOnly`, because the SDK keeps flushing queued events until the process +restarts. Automatic logging also enables automatic purchase logging: turn it +off on the Android card of the Meta App Dashboard if you test purchases. Debug +builds enable `SetDebugLoggingEnabled(true)`, so logged and flushed events +appear in `adb logcat`. Use Meta Events Manager > Test events to confirm delivery. ### Access token attribution check diff --git a/samples/Kapusch.Facebook.Android.Sample/src/MainActivity.cs b/samples/Kapusch.Facebook.Android.Sample/src/MainActivity.cs index a5ffbd0..ccee8ca 100644 --- a/samples/Kapusch.Facebook.Android.Sample/src/MainActivity.cs +++ b/samples/Kapusch.Facebook.Android.Sample/src/MainActivity.cs @@ -86,11 +86,12 @@ private static void GrantConsent() FacebookAppEvents.SetFlushBehavior(FacebookAppEventsFlushBehavior.Auto); FacebookAppEvents.SetAutoInitEnabled(true); FacebookAppEvents.SetAdvertiserIdCollectionEnabled(true); - // Keep automatic logging off (no purchase auto-logging) and log activation explicitly. - // ActivateApp sends the one-time install ping and logs activation from the next activity - // resume on; this screen is already resumed, so the current session is not counted. A real + // App opens are automatic events, so they need automatic logging on. Turn automatic purchase + // logging off in the Meta App Dashboard when a server reports purchases. + FacebookAppEvents.SetAutoLogAppEventsEnabled(true); + // ActivateApp sends the one-time install ping; activations are logged from the next activity + // resume on. This screen is already resumed, so the current session is not counted. A real // app calls it on every launch with consent, before the first activity resumes. - FacebookAppEvents.SetAutoLogAppEventsEnabled(false); FacebookAppEvents.ActivateApp(); } @@ -101,8 +102,9 @@ private static void WithdrawConsent() FacebookAppEvents.SetAutoInitEnabled(false); FacebookAppEvents.ClearUserId(); FacebookAppEvents.ClearUserData(); - // The SDK stays fully initialized and keeps tracking activation until the process restarts. - // Stop sending for this process; a real app also stops calling the Log* methods. + // Automatic events stop at once, but the SDK stays fully initialized and keeps flushing queued + // events until the process restarts. Stop sending for this process; a real app also stops + // calling the Log* methods. FacebookAppEvents.SetFlushBehavior(FacebookAppEventsFlushBehavior.ExplicitOnly); }