From 5915843c4831127d308f43b49b781c44a9f76ea0 Mon Sep 17 00:00:00 2001 From: Dmitrii Feshchenko Date: Thu, 19 Mar 2026 13:56:24 +0100 Subject: [PATCH] feat: add AdAttributionKit ids support for iOS --- Editor/PluginSettings/AppodealSettings.cs | 17 +++++ Editor/PostProcess/iOSPostprocessUtils.cs | 59 ++++++++++++++++++ .../SettingsWindow/AppodealSettingsWindow.cs | 62 +++++++++++++++++-- Editor/Utils/AppodealUnityUtils.cs | 1 + 4 files changed, 134 insertions(+), 5 deletions(-) diff --git a/Editor/PluginSettings/AppodealSettings.cs b/Editor/PluginSettings/AppodealSettings.cs index 6fbeddd8..25e0bef8 100644 --- a/Editor/PluginSettings/AppodealSettings.cs +++ b/Editor/PluginSettings/AppodealSettings.cs @@ -43,6 +43,11 @@ public class AppodealSettings : ScriptableObject [SerializeField] private bool iosSkAdNetworkItems = true; [SerializeField] private List iosSkAdNetworkItemsList = new(); + [Space(SpaceHeight)] + [Header("iOS AdAttributionKit IDs")] + [SerializeField] private bool iosAakIds = true; + [SerializeField] private List iosAakIdsList = new(); + [Space(SpaceHeight)] [Header("Facebook Service")] [SerializeField] private bool facebookAutoConfiguration; @@ -196,6 +201,18 @@ public List IosSkAdNetworkItemsList set => iosSkAdNetworkItemsList = value; } + public bool IosAakIds + { + get => iosAakIds; + set => iosAakIds = value; + } + + public List IosAakIdsList + { + get => iosAakIdsList; + set => iosAakIdsList = value; + } + public bool FirebaseAutoConfiguration { get => firebaseAutoConfiguration; diff --git a/Editor/PostProcess/iOSPostprocessUtils.cs b/Editor/PostProcess/iOSPostprocessUtils.cs index abbdfbef..7d1a785b 100644 --- a/Editor/PostProcess/iOSPostprocessUtils.cs +++ b/Editor/PostProcess/iOSPostprocessUtils.cs @@ -34,6 +34,7 @@ public static void UpdateInfoPlist(BuildTarget buildTarget, string buildPath) AddNsLocationWhenInUseUsageDescription(path); AddNsCalendarsUsageDescription(path); AddSkAdNetworkIds(buildTarget, buildPath); + AddAdNetworkIdentifiers(buildTarget, buildPath); IosPostProcessServices.AddFacebookKeys(path); } @@ -82,6 +83,64 @@ private static void AddSkAdNetworkIds(BuildTarget buildTarget, string buildPath) File.WriteAllText(plistPath, plist.WriteToString()); } + private static void AddAdNetworkIdentifiers(BuildTarget buildTarget, string buildPath) + { + if (String.IsNullOrEmpty(PlayerSettings.iOS.targetOSVersionString)) return; + + if (!AppodealSettings.Instance.IosAakIds || (AppodealSettings.Instance.IosAakIdsList?.Count ?? 0) <= 0) return; + + if (buildTarget != BuildTarget.iOS) return; + + string plistPath = buildPath + "/Info.plist"; + var plist = new PlistDocument(); + plist.ReadFromString(File.ReadAllText(plistPath)); + + PlistElementArray array = null; + if (plist.root.values.ContainsKey(AppodealUnityUtils.KeyAdNetworkIdentifiers)) + { + try + { + plist.root.values.TryGetValue(AppodealUnityUtils.KeyAdNetworkIdentifiers, out var element); + if (element != null) array = element.AsArray(); + } + catch (Exception e) + { + Debug.LogError(e.Message); + array = null; + } + } + else + { + array = plist.root.CreateArray(AppodealUnityUtils.KeyAdNetworkIdentifiers); + } + + if (array != null) + { + var existing = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (var elem in array.values) + { + try + { + string val = elem.AsString(); + if (!String.IsNullOrEmpty(val)) existing.Add(val); + } + catch (Exception e) + { + Debug.LogError(e.Message); + } + } + + foreach (string id in AppodealSettings.Instance.IosAakIdsList) + { + if (existing.Contains(id)) continue; + array.AddString(id); + existing.Add(id); + } + } + + File.WriteAllText(plistPath, plist.WriteToString()); + } + private static void AddKeyToPlist(string path, string key, string value) { var plist = new PlistDocument(); diff --git a/Editor/SettingsWindow/AppodealSettingsWindow.cs b/Editor/SettingsWindow/AppodealSettingsWindow.cs index fc391607..25c95f35 100644 --- a/Editor/SettingsWindow/AppodealSettingsWindow.cs +++ b/Editor/SettingsWindow/AppodealSettingsWindow.cs @@ -27,7 +27,10 @@ public static void ShowAppodealSettingsWindow() private async void OnEnable() { - var ids = await GetSkAdNetworkIds(); + var skAdNetworkTask = GetSkAdNetworkIds(); + var aakTask = GetAakIds(); + + var ids = await skAdNetworkTask; if (AppodealSettings.Instance == null) return; @@ -35,6 +38,15 @@ private async void OnEnable() { AppodealSettings.Instance.IosSkAdNetworkItemsList = ids; } + + var aakIds = await aakTask; + + if (AppodealSettings.Instance == null) return; + + if (aakIds?.Count > 0 && !aakIds.SequenceEqual(AppodealSettings.Instance.IosAakIdsList)) + { + AppodealSettings.Instance.IosAakIdsList = aakIds; + } } private static async Task> GetSkAdNetworkIds() @@ -69,6 +81,43 @@ private static async Task> GetSkAdNetworkIds() } } + private static async Task> GetAakIds() + { + try + { + var request = UnityWebRequest.Get("https://neo-mw-backend.appodeal.com/v4/aak/ids"); + _ = request.SendWebRequest(); + while (!request.isDone) await Task.Yield(); + + if (request.result != UnityWebRequest.Result.Success) + { + request.Dispose(); + return new List(); + } + + string json = request.downloadHandler.text; + request.Dispose(); + + if (String.IsNullOrWhiteSpace(json) || !json.StartsWith('[') || !json.EndsWith(']')) return new List(); + + string[] ids = JsonHelper.FromJson(JsonHelper.FixJson(json)); + if ((ids?.Length ?? 0) < 1) return new List(); + + var regex = new Regex(@"^[a-z0-9]+\.[a-z]+$"); + return ids! + .Select(id => id?.ToLowerInvariant()) + .Where(id => !String.IsNullOrEmpty(id) && regex.IsMatch(id)) + .Distinct() + .OrderBy(id => id) + .ToList(); + } + catch (Exception e) + { + Debug.LogException(e); + return new List(); + } + } + private void OnDestroy() { AnalyticsService.TrackClickEvent(ActionType.CloseAppodealSettings); @@ -158,21 +207,24 @@ private void OnGUI() AppodealSettings.Instance.NsAppTransportSecurity = KeyRow("NSAppTransportSecurity", AppodealSettings.Instance.NsAppTransportSecurity); - GUILayout.Space(35); - if (GUILayout.Button("SKAdNetwork", new GUIStyle(EditorStyles.label) + GUILayout.Space(15); + if (GUILayout.Button("Attribution", new GUIStyle(EditorStyles.label) { fontSize = 12, fontStyle = FontStyle.Bold, fixedHeight = 18 }, GUILayout.ExpandWidth(true))) { - Application.OpenURL("https://developer.apple.com/documentation/storekit/skadnetwork"); + Application.OpenURL("https://developer.apple.com/documentation/AdAttributionKit/adattributionkit-skadnetwork-interoperability"); } AppodealSettings.Instance.IosSkAdNetworkItems = KeyRow("Add SKAdNetworkItems", AppodealSettings.Instance.IosSkAdNetworkItems); - GUILayout.Space(12); + AppodealSettings.Instance.IosAakIds = KeyRow("Add AdNetworkIdentifiers", + AppodealSettings.Instance.IosAakIds); + + GUILayout.Space(7); } GUILayout.EndHorizontal(); diff --git a/Editor/Utils/AppodealUnityUtils.cs b/Editor/Utils/AppodealUnityUtils.cs index 5dfa9a27..a2549b44 100644 --- a/Editor/Utils/AppodealUnityUtils.cs +++ b/Editor/Utils/AppodealUnityUtils.cs @@ -22,6 +22,7 @@ public static class AppodealUnityUtils private const BindingFlags PublicStaticFlags = BindingFlags.Public | BindingFlags.Static; public const string KeySkAdNetworkItems = "SKAdNetworkItems"; public const string KeySkAdNetworkID = "SKAdNetworkIdentifier"; + public const string KeyAdNetworkIdentifiers = "AdNetworkIdentifiers"; public const string GadApplicationIdentifier = "GADApplicationIdentifier"; public const string NsUserTrackingUsageDescriptionKey = "NSUserTrackingUsageDescription"; public const string NsUserTrackingUsageDescription = "This identifier will be used to deliver personalized ads to you";