diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 71c02333e0..ef6d0f967c 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -1010,7 +1010,7 @@ F15531922BF215ED0029ED04 /* SubscriptionTestingUtilities in Frameworks */ = {isa = PBXBuildFile; productRef = F15531912BF215ED0029ED04 /* SubscriptionTestingUtilities */; }; F15531942BF215F60029ED04 /* Subscription in Frameworks */ = {isa = PBXBuildFile; productRef = F15531932BF215F60029ED04 /* Subscription */; }; F15531962BF215F60029ED04 /* SubscriptionTestingUtilities in Frameworks */ = {isa = PBXBuildFile; productRef = F15531952BF215F60029ED04 /* SubscriptionTestingUtilities */; }; - F1564F032B7B915F00D454A6 /* AppDelegate+SKAD4.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1564F022B7B915F00D454A6 /* AppDelegate+SKAD4.swift */; }; + F1564F032B7B915F00D454A6 /* AppDelegate+Attribution.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1564F022B7B915F00D454A6 /* AppDelegate+Attribution.swift */; }; F15D43201E706CC500BF2CDC /* AutocompleteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F15D431F1E706CC500BF2CDC /* AutocompleteViewController.swift */; }; F1617C131E572E0300DEDCAF /* TabSwitcherViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1617C121E572E0300DEDCAF /* TabSwitcherViewController.swift */; }; F1617C151E57336D00DEDCAF /* TabManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1617C141E57336D00DEDCAF /* TabManager.swift */; }; @@ -2781,7 +2781,7 @@ F143C32C1E4A9A4800CFDE3A /* UIViewControllerExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UIViewControllerExtension.swift; path = ../Core/UIViewControllerExtension.swift; sourceTree = ""; }; F143C3451E4AA32D00CFDE3A /* SearchBarExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SearchBarExtension.swift; path = ../Core/SearchBarExtension.swift; sourceTree = ""; }; F14E491E1E391CE900DC037C /* URLExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLExtensionTests.swift; sourceTree = ""; }; - F1564F022B7B915F00D454A6 /* AppDelegate+SKAD4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AppDelegate+SKAD4.swift"; sourceTree = ""; }; + F1564F022B7B915F00D454A6 /* AppDelegate+Attribution.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Attribution.swift"; sourceTree = ""; }; F159BDA31F0BDB5A00B4A01D /* TabViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabViewController.swift; sourceTree = ""; }; F15D431F1E706CC500BF2CDC /* AutocompleteViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutocompleteViewController.swift; sourceTree = ""; }; F1617C121E572E0300DEDCAF /* TabSwitcherViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabSwitcherViewController.swift; sourceTree = ""; }; @@ -5818,7 +5818,7 @@ CB24F70E29A3EB15006DCC58 /* AppConfigurationURLProvider.swift */, 84E341951E2F7EFB00BDBA6F /* AppDelegate.swift */, 85DB12EC2A1FED0C000A4A72 /* AppDelegate+AppDeepLinks.swift */, - F1564F022B7B915F00D454A6 /* AppDelegate+SKAD4.swift */, + F1564F022B7B915F00D454A6 /* AppDelegate+Attribution.swift */, 98B31291218CCB8C00E54DE1 /* AppDependencyProvider.swift */, 85BA58591F3506AE00C6E8CA /* AppSettings.swift */, 85BA58541F34F49E00C6E8CA /* AppUserDefaults.swift */, @@ -7041,7 +7041,7 @@ 9F5E5AB02C3E4C6000165F54 /* ContextualOnboardingPresenter.swift in Sources */, 310D091B2799F54900DC0060 /* DownloadManager.swift in Sources */, 98D98A7425ED88D100D8E3DF /* BrowsingMenuEntryViewCell.swift in Sources */, - F1564F032B7B915F00D454A6 /* AppDelegate+SKAD4.swift in Sources */, + F1564F032B7B915F00D454A6 /* AppDelegate+Attribution.swift in Sources */, 98F3A1D8217B37010011A0D4 /* Theme.swift in Sources */, 4B2C79612C5B27AC00A240CC /* VPNSnoozeActivityAttributes.swift in Sources */, CB9B873C278C8FEA001F4906 /* WidgetEducationView.swift in Sources */, diff --git a/DuckDuckGo/AppDelegate+Attribution.swift b/DuckDuckGo/AppDelegate+Attribution.swift new file mode 100644 index 0000000000..fef1e31449 --- /dev/null +++ b/DuckDuckGo/AppDelegate+Attribution.swift @@ -0,0 +1,59 @@ +// +// AppDelegate+Attribution.swift +// DuckDuckGo +// +// Copyright © 2023 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import Common +import StoreKit +import AdAttributionKit + +extension AppDelegate { + + func updateAttribution(conversionValue: Int) { + Task { + if #available(iOS 17.4, *) { + // https://developer.apple.com/documentation/adattributionkit/adattributionkit-skadnetwork-interoperability + await updateAdAttributionKitPostback(conversionValue: conversionValue) + await updateSKANPostback(conversionValue: conversionValue) + } else if #available(iOS 16.1, *) { + await updateSKANPostback(conversionValue: conversionValue) + } + } + } + + @available(iOS 17.4, *) + private func updateAdAttributionKitPostback(conversionValue: Int) async { + do { + try await AdAttributionKit.Postback.updateConversionValue(conversionValue, coarseConversionValue: .high, lockPostback: true) + os_log("Attribution: AdAttributionKit postback succeeded", type: .debug) + } catch { + os_log("Attribution: AdAttributionKit postback failed %@", type: .error, error.localizedDescription) + } + } + + @available(iOS 16.1, *) + private func updateSKANPostback(conversionValue: Int) async { + do { + try await SKAdNetwork.updatePostbackConversionValue(conversionValue, coarseValue: .high, lockWindow: true) + os_log("Attribution: SKAN 4 postback succeeded", type: .debug) + } catch { + os_log("Attribution: SKAN 4 postback failed %@", type: .error, error.localizedDescription) + } + } + +} diff --git a/DuckDuckGo/AppDelegate+SKAD4.swift b/DuckDuckGo/AppDelegate+SKAD4.swift deleted file mode 100644 index 9f65d0eac3..0000000000 --- a/DuckDuckGo/AppDelegate+SKAD4.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// AppDelegate+SKAD4.swift -// DuckDuckGo -// -// Copyright © 2023 DuckDuckGo. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import StoreKit -import Common - -extension AppDelegate { - - func updateSKAd(conversionValue: Int) { - - if #available(iOS 16.1, *) { - SKAdNetwork.updatePostbackConversionValue(conversionValue, coarseValue: .high, lockWindow: true, completionHandler: { error in - if let error { - os_log("SKAD 4 postback failed %@", type: .error, error.localizedDescription) - } else { - os_log("SKAD 4 postback succeeded", type: .debug) - } - }) - } else { - os_log("SKAD 4 Not supported in this iOS version", type: .debug) - } - } -} diff --git a/DuckDuckGo/AppDelegate.swift b/DuckDuckGo/AppDelegate.swift index 4251b031f3..a9a5bedee3 100644 --- a/DuckDuckGo/AppDelegate.swift +++ b/DuckDuckGo/AppDelegate.swift @@ -112,8 +112,8 @@ import WebKit // swiftlint:disable:next function_body_length func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // SKAD4 support - updateSKAd(conversionValue: 1) + // Attribution support + updateAttribution(conversionValue: 1) #if targetEnvironment(simulator) if ProcessInfo.processInfo.environment["UITESTING"] == "true" {