diff --git a/src/Packages/Audience/Runtime/AudienceConfig.cs b/src/Packages/Audience/Runtime/AudienceConfig.cs
index c2681509..d0dd7090 100644
--- a/src/Packages/Audience/Runtime/AudienceConfig.cs
+++ b/src/Packages/Audience/Runtime/AudienceConfig.cs
@@ -49,6 +49,40 @@ public class AudienceConfig
///
public bool Debug { get; set; } = false;
+ ///
+ /// Opts into mobile install-attribution signals (iOS ATT / IDFA /
+ /// SKAdNetwork, Android Advertising ID / Install Referrer). Default
+ /// false.
+ ///
+ ///
+ /// Two gates control attribution; both must be set for any data to
+ /// ship:
+ ///
+ /// 1. Build-time: add AUDIENCE_MOBILE_ATTRIBUTION to Player
+ /// Settings → Other Settings → Scripting Define Symbols. Controls
+ /// the AD_ID Android manifest permission, the iOS Privacy Manifest
+ /// variant (NSPrivacyTracking), and whether native
+ /// attribution code is compiled into the binary.
+ ///
+ /// 2. Runtime: this flag. Controls whether attribution data is
+ /// collected at runtime. Without the define, this setter is a
+ /// no-op.
+ ///
+ /// Studios who set neither ship a clean binary — no AD_ID permission,
+ /// no native attribution code, NSPrivacyTracking = false.
+ ///
+ public bool EnableMobileAttribution { get; set; } = false;
+
+ ///
+ /// SKAdNetwork IDs the iOS post-processor injects into Info.plist
+ /// at build time. Ignored on Android.
+ ///
+ ///
+ /// Read only when and the
+ /// AUDIENCE_MOBILE_ATTRIBUTION scripting define are both set.
+ ///
+ public string[]? SKAdNetworkIds { get; set; }
+
///
/// Interval between automatic flushes to the backend, in seconds.
///
diff --git a/src/Packages/Audience/Tests/Runtime/AudienceConfigTests.cs b/src/Packages/Audience/Tests/Runtime/AudienceConfigTests.cs
new file mode 100644
index 00000000..84a198a1
--- /dev/null
+++ b/src/Packages/Audience/Tests/Runtime/AudienceConfigTests.cs
@@ -0,0 +1,41 @@
+#nullable enable
+
+using NUnit.Framework;
+
+namespace Immutable.Audience.Tests
+{
+ [TestFixture]
+ internal class AudienceConfigTests
+ {
+ [Test]
+ public void EnableMobileAttribution_DefaultsToFalse()
+ {
+ // Default-off matters: a studio that never opts in must ship a
+ // clean binary, no AD_ID permission, NSPrivacyTracking false.
+ var config = new AudienceConfig();
+ Assert.IsFalse(config.EnableMobileAttribution);
+ }
+
+ [Test]
+ public void SKAdNetworkIds_DefaultsToNull()
+ {
+ var config = new AudienceConfig();
+ Assert.IsNull(config.SKAdNetworkIds);
+ }
+
+ [Test]
+ public void EnableMobileAttribution_RoundTrips()
+ {
+ var config = new AudienceConfig { EnableMobileAttribution = true };
+ Assert.IsTrue(config.EnableMobileAttribution);
+ }
+
+ [Test]
+ public void SKAdNetworkIds_RoundTrips()
+ {
+ var ids = new[] { "abc123.skadnetwork", "def456.skadnetwork" };
+ var config = new AudienceConfig { SKAdNetworkIds = ids };
+ Assert.AreSame(ids, config.SKAdNetworkIds);
+ }
+ }
+}
diff --git a/src/Packages/Audience/Tests/Runtime/AudienceConfigTests.cs.meta b/src/Packages/Audience/Tests/Runtime/AudienceConfigTests.cs.meta
new file mode 100644
index 00000000..ea8a7382
--- /dev/null
+++ b/src/Packages/Audience/Tests/Runtime/AudienceConfigTests.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c7a0b1d2e3f4a5b6c7d8e9f0a1b2c3d4
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: