From b911a2a6251b03dfccbd197c1ca905fb94557ece Mon Sep 17 00:00:00 2001 From: uerceg Date: Thu, 18 Jul 2024 22:57:43 +0200 Subject: [PATCH] feat: add handling of deeplink referrer url --- Adjust.xcodeproj/project.pbxproj | 40 +++++++++++++++++ Adjust/ADJDeeplink.h | 19 ++++++++ Adjust/ADJDeeplink.m | 24 +++++++++++ Adjust/Adjust.h | 7 +-- Adjust/Adjust.m | 23 ++++++---- Adjust/Internal/ADJActivityHandler.h | 4 +- Adjust/Internal/ADJActivityHandler.m | 43 +++++++++++++------ Adjust/Internal/ADJPackageBuilder.h | 2 + Adjust/Internal/ADJPackageBuilder.m | 1 + Adjust/Internal/ADJUserDefaults.h | 5 ++- Adjust/Internal/ADJUserDefaults.m | 14 +++++- .../AdjustTestApp/ATAAdjustCommandExecutor.m | 8 +++- UmbrellaHeaders/sdk/AdjustSdk.h | 1 + UmbrellaHeaders/webbridge/AdjustSdk.h | 1 + 14 files changed, 161 insertions(+), 31 deletions(-) create mode 100644 Adjust/ADJDeeplink.h create mode 100644 Adjust/ADJDeeplink.m diff --git a/Adjust.xcodeproj/project.pbxproj b/Adjust.xcodeproj/project.pbxproj index 19e0a553d..c2f1a4d02 100644 --- a/Adjust.xcodeproj/project.pbxproj +++ b/Adjust.xcodeproj/project.pbxproj @@ -727,6 +727,24 @@ 9D775B642A1F9CCE009D0BE8 /* ADJPurchaseVerificationHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D775B602A1F9CC5009D0BE8 /* ADJPurchaseVerificationHandler.m */; }; 9D775B652A1F9CCF009D0BE8 /* ADJPurchaseVerificationHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D775B602A1F9CC5009D0BE8 /* ADJPurchaseVerificationHandler.m */; }; 9D775B662A1F9CD0009D0BE8 /* ADJPurchaseVerificationHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D775B602A1F9CC5009D0BE8 /* ADJPurchaseVerificationHandler.m */; }; + 9D7D3DEC2C49A8B200FACB18 /* ADJDeeplink.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D7D3DEA2C49A8B200FACB18 /* ADJDeeplink.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D7D3DED2C49A8B200FACB18 /* ADJDeeplink.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7D3DEB2C49A8B200FACB18 /* ADJDeeplink.m */; }; + 9D7D3DEE2C49A8B200FACB18 /* ADJDeeplink.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D7D3DEA2C49A8B200FACB18 /* ADJDeeplink.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D7D3DEF2C49A8B200FACB18 /* ADJDeeplink.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7D3DEB2C49A8B200FACB18 /* ADJDeeplink.m */; }; + 9D7D3DF02C49A8B200FACB18 /* ADJDeeplink.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7D3DEB2C49A8B200FACB18 /* ADJDeeplink.m */; }; + 9D7D3DF12C49A8B200FACB18 /* ADJDeeplink.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D7D3DEA2C49A8B200FACB18 /* ADJDeeplink.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D7D3DF22C49A8B200FACB18 /* ADJDeeplink.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D7D3DEA2C49A8B200FACB18 /* ADJDeeplink.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D7D3DF32C49A8B200FACB18 /* ADJDeeplink.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7D3DEB2C49A8B200FACB18 /* ADJDeeplink.m */; }; + 9D7D3DF42C49A8B200FACB18 /* ADJDeeplink.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D7D3DEA2C49A8B200FACB18 /* ADJDeeplink.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D7D3DF52C49A8B200FACB18 /* ADJDeeplink.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7D3DEB2C49A8B200FACB18 /* ADJDeeplink.m */; }; + 9D7D3DF62C49A8B200FACB18 /* ADJDeeplink.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D7D3DEA2C49A8B200FACB18 /* ADJDeeplink.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D7D3DF72C49A8B200FACB18 /* ADJDeeplink.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7D3DEB2C49A8B200FACB18 /* ADJDeeplink.m */; }; + 9D7D3DF82C49A8B200FACB18 /* ADJDeeplink.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7D3DEB2C49A8B200FACB18 /* ADJDeeplink.m */; }; + 9D7D3DF92C49A8B200FACB18 /* ADJDeeplink.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D7D3DEA2C49A8B200FACB18 /* ADJDeeplink.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D7D3DFA2C49A8B200FACB18 /* ADJDeeplink.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D7D3DEA2C49A8B200FACB18 /* ADJDeeplink.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D7D3DFB2C49A8B200FACB18 /* ADJDeeplink.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7D3DEB2C49A8B200FACB18 /* ADJDeeplink.m */; }; + 9D7D3DFC2C49A8B200FACB18 /* ADJDeeplink.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D7D3DEA2C49A8B200FACB18 /* ADJDeeplink.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D7D3DFD2C49A8B200FACB18 /* ADJDeeplink.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7D3DEB2C49A8B200FACB18 /* ADJDeeplink.m */; }; 9DB561852C072BA10004CCAD /* ADJUrlStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FBEE8F124E2C26F00FEF3F1 /* ADJUrlStrategy.h */; }; 9DB561862C072BAF0004CCAD /* ADJUrlStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FBEE8F224E2C26F00FEF3F1 /* ADJUrlStrategy.m */; }; 9DD0E9AE1F44690B00B2A759 /* ADJUserDefaults.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DD0E9AC1F44690B00B2A759 /* ADJUserDefaults.h */; }; @@ -987,6 +1005,8 @@ 9D775B582A1F7C7A009D0BE8 /* ADJPurchaseVerificationResult.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ADJPurchaseVerificationResult.m; sourceTree = ""; }; 9D775B5F2A1F9CC5009D0BE8 /* ADJPurchaseVerificationHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ADJPurchaseVerificationHandler.h; sourceTree = ""; }; 9D775B602A1F9CC5009D0BE8 /* ADJPurchaseVerificationHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ADJPurchaseVerificationHandler.m; sourceTree = ""; }; + 9D7D3DEA2C49A8B200FACB18 /* ADJDeeplink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ADJDeeplink.h; sourceTree = ""; }; + 9D7D3DEB2C49A8B200FACB18 /* ADJDeeplink.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ADJDeeplink.m; sourceTree = ""; }; 9D9D154D212EB3D00081445E /* AdjustExample-FbPixel.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "AdjustExample-FbPixel.xcodeproj"; path = "examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj"; sourceTree = ""; }; 9DBE560723054FCC0065E19C /* AdjustExample-ObjC.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "AdjustExample-ObjC.xcodeproj"; path = "examples/AdjustExample-ObjC/AdjustExample-ObjC.xcodeproj"; sourceTree = ""; }; 9DD0E9AC1F44690B00B2A759 /* ADJUserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJUserDefaults.h; sourceTree = ""; }; @@ -1241,6 +1261,8 @@ 969952D11A01309200928462 /* ADJAttribution.m */, 960A8BB71A029A8000F2BB95 /* ADJConfig.h */, 960A8BB81A029A8000F2BB95 /* ADJConfig.m */, + 9D7D3DEA2C49A8B200FACB18 /* ADJDeeplink.h */, + 9D7D3DEB2C49A8B200FACB18 /* ADJDeeplink.m */, 9609BC6819EEA55800E02303 /* ADJEvent.h */, 9609BC6919EEA55800E02303 /* ADJEvent.m */, 9601CAE61C74BAAE00670879 /* ADJEventFailure.h */, @@ -1430,6 +1452,7 @@ 0A584CE12C3E95B10071A651 /* ADJEventFailure.h in Headers */, 0A584CE22C3E95B10071A651 /* ADJEventSuccess.h in Headers */, 0A584CE32C3E95B10071A651 /* ADJLinkResolution.h in Headers */, + 9D7D3DF62C49A8B200FACB18 /* ADJDeeplink.h in Headers */, 0A584CE42C3E95B10071A651 /* ADJLogger.h in Headers */, 0A584CE52C3E95B10071A651 /* ADJPurchaseVerificationResult.h in Headers */, 0A584CE62C3E95B10071A651 /* ADJSessionFailure.h in Headers */, @@ -1475,6 +1498,7 @@ 0A584D082C3E96250071A651 /* ADJEventFailure.h in Headers */, 0A584D092C3E96250071A651 /* ADJEventSuccess.h in Headers */, 0A584D0A2C3E96250071A651 /* ADJLinkResolution.h in Headers */, + 9D7D3DF92C49A8B200FACB18 /* ADJDeeplink.h in Headers */, 0A584D0B2C3E96250071A651 /* ADJLogger.h in Headers */, 0A584D0C2C3E96250071A651 /* ADJPurchaseVerificationResult.h in Headers */, 0A584D0D2C3E96250071A651 /* ADJSessionFailure.h in Headers */, @@ -1520,6 +1544,7 @@ 0A584D2F2C3E968A0071A651 /* ADJEventFailure.h in Headers */, 0A584D302C3E968A0071A651 /* ADJEventSuccess.h in Headers */, 0A584D312C3E968A0071A651 /* ADJLinkResolution.h in Headers */, + 9D7D3DFA2C49A8B200FACB18 /* ADJDeeplink.h in Headers */, 0A584D322C3E968A0071A651 /* ADJLogger.h in Headers */, 0A584D332C3E968A0071A651 /* ADJPurchaseVerificationResult.h in Headers */, 0A584D342C3E968A0071A651 /* ADJSessionFailure.h in Headers */, @@ -1598,6 +1623,7 @@ 0A584D772C3E97020071A651 /* ADJTimerOnce.h in Headers */, 0A584D782C3E97020071A651 /* ADJUrlStrategy.h in Headers */, 0A584D792C3E97020071A651 /* ADJUserDefaults.h in Headers */, + 9D7D3DFC2C49A8B200FACB18 /* ADJDeeplink.h in Headers */, 0A584D7A2C3E97020071A651 /* ADJUtil.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1615,6 +1641,7 @@ 9D2F23E22447CE5C00B7CA90 /* ADJAppStoreSubscription.h in Headers */, 9601CAE81C74BAAE00670879 /* ADJEventFailure.h in Headers */, 9D52A3212C071BBC00E0AA55 /* ADJAdditions.h in Headers */, + 9D7D3DEC2C49A8B200FACB18 /* ADJDeeplink.h in Headers */, 968173871C3C2D36002AE1DE /* ADJSessionFailure.h in Headers */, 968173831C3C2D07002AE1DE /* ADJSessionSuccess.h in Headers */, 9DF92D832630ED02000FC3FC /* ADJPackageParams.h in Headers */, @@ -1693,6 +1720,7 @@ 0A584CD62C3E95710071A651 /* ADJTimerOnce.h in Headers */, 0A584CD72C3E95710071A651 /* ADJUrlStrategy.h in Headers */, 0A584CD82C3E95710071A651 /* ADJUserDefaults.h in Headers */, + 9D7D3DF42C49A8B200FACB18 /* ADJDeeplink.h in Headers */, 0A584CD92C3E95710071A651 /* ADJUtil.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1710,6 +1738,7 @@ 0A584C1A2C3E94B50071A651 /* ADJEventFailure.h in Headers */, 0A584C1B2C3E94B50071A651 /* ADJEventSuccess.h in Headers */, 0A584C1C2C3E94B50071A651 /* ADJLinkResolution.h in Headers */, + 9D7D3DF12C49A8B200FACB18 /* ADJDeeplink.h in Headers */, 0A584C1D2C3E94B50071A651 /* ADJLogger.h in Headers */, 0A584C1E2C3E94B50071A651 /* ADJPurchaseVerificationResult.h in Headers */, 0A584C1F2C3E94B50071A651 /* ADJSessionFailure.h in Headers */, @@ -1755,6 +1784,7 @@ 0A584BCF2C3E944F0071A651 /* ADJEventFailure.h in Headers */, 0A584BD02C3E944F0071A651 /* ADJEventSuccess.h in Headers */, 0A584BD12C3E944F0071A651 /* ADJLinkResolution.h in Headers */, + 9D7D3DEE2C49A8B200FACB18 /* ADJDeeplink.h in Headers */, 0A584BD22C3E944F0071A651 /* ADJLogger.h in Headers */, 0A584BD32C3E944F0071A651 /* ADJPurchaseVerificationResult.h in Headers */, 0A584BD42C3E944F0071A651 /* ADJSessionFailure.h in Headers */, @@ -1800,6 +1830,7 @@ 0A584C652C3E94FA0071A651 /* ADJEventFailure.h in Headers */, 0A584C662C3E94FA0071A651 /* ADJEventSuccess.h in Headers */, 0A584C672C3E94FA0071A651 /* ADJLinkResolution.h in Headers */, + 9D7D3DF22C49A8B200FACB18 /* ADJDeeplink.h in Headers */, 0A584C682C3E94FA0071A651 /* ADJLogger.h in Headers */, 0A584C692C3E94FA0071A651 /* ADJPurchaseVerificationResult.h in Headers */, 0A584C6A2C3E94FA0071A651 /* ADJSessionFailure.h in Headers */, @@ -2396,6 +2427,7 @@ 9D4CC6D52C0735B400A1E0C0 /* ADJAdditions.m in Sources */, 0AB1C99A27DD4B3100509231 /* Adjust.m in Sources */, 0AB1C99B27DD4B3100509231 /* ADJActivityHandler.m in Sources */, + 9D7D3DF72C49A8B200FACB18 /* ADJDeeplink.m in Sources */, 0AB1C99C27DD4B3100509231 /* ADJActivityKind.m in Sources */, 0AB1C99D27DD4B3100509231 /* ADJActivityPackage.m in Sources */, 0AB1C99E27DD4B3100509231 /* ADJActivityState.m in Sources */, @@ -2440,6 +2472,7 @@ 9D4CC6E82C0735BC00A1E0C0 /* ADJAdditions.m in Sources */, 0AB1CA3227DF49CB00509231 /* Adjust.m in Sources */, 0AB1CA3327DF49CB00509231 /* ADJActivityHandler.m in Sources */, + 9D7D3DF82C49A8B200FACB18 /* ADJDeeplink.m in Sources */, 0AB1CA3427DF49CC00509231 /* ADJActivityKind.m in Sources */, 0AB1CA3527DF49CC00509231 /* ADJActivityPackage.m in Sources */, 0AB1CA3627DF49CC00509231 /* ADJActivityState.m in Sources */, @@ -2484,6 +2517,7 @@ 9D4CC6E92C0735C400A1E0C0 /* ADJAdditions.m in Sources */, 0AB1CA7527DF61F200509231 /* Adjust.m in Sources */, 0AB1CA7627DF61F200509231 /* ADJActivityHandler.m in Sources */, + 9D7D3DFB2C49A8B200FACB18 /* ADJDeeplink.m in Sources */, 0AB1CA7727DF61F200509231 /* ADJActivityKind.m in Sources */, 0AB1CA7827DF61F200509231 /* ADJActivityPackage.m in Sources */, 0AB1CA7927DF61F200509231 /* ADJActivityState.m in Sources */, @@ -2560,6 +2594,7 @@ 0AB1CB2727DF68C100509231 /* ADJAppStoreSubscription.m in Sources */, 0AB1CB2827DF68C100509231 /* ADJUrlStrategy.m in Sources */, 0AB1CB2927DF68C100509231 /* ADJThirdPartySharing.m in Sources */, + 9D7D3DFD2C49A8B200FACB18 /* ADJDeeplink.m in Sources */, 0AB1CB2A27DF68C100509231 /* ADJAdRevenue.m in Sources */, 0AB1CB2B27DF68C100509231 /* ADJLinkResolution.m in Sources */, 0AB1CB2C27DF68DB00509231 /* AdjustBridge.m in Sources */, @@ -2589,6 +2624,7 @@ 9DB561862C072BAF0004CCAD /* ADJUrlStrategy.m in Sources */, 9DF92D842630ED02000FC3FC /* ADJPackageParams.m in Sources */, 96E5E38118BBB48A008E7B30 /* Adjust.m in Sources */, + 9D7D3DED2C49A8B200FACB18 /* ADJDeeplink.m in Sources */, 96E5E38B18BBB48A008E7B30 /* ADJActivityHandler.m in Sources */, 96E5E38C18BBB48A008E7B30 /* ADJActivityKind.m in Sources */, 96E5E38D18BBB48A008E7B30 /* ADJActivityPackage.m in Sources */, @@ -2665,6 +2701,7 @@ 0A584CA52C3E952C0071A651 /* ADJTimerCycle.m in Sources */, 0A584CA62C3E952C0071A651 /* ADJTimerOnce.m in Sources */, 0A584CA72C3E952C0071A651 /* ADJUrlStrategy.m in Sources */, + 9D7D3DF52C49A8B200FACB18 /* ADJDeeplink.m in Sources */, 0A584CA82C3E952C0071A651 /* ADJUserDefaults.m in Sources */, 0A584CA92C3E952C0071A651 /* ADJUtil.m in Sources */, 0A584CAA2C3E952C0071A651 /* AdjustBridge.m in Sources */, @@ -2682,6 +2719,7 @@ 0A584BEF2C3E949B0071A651 /* ADJAdRevenue.m in Sources */, 0A584BF02C3E949B0071A651 /* ADJAppStorePurchase.m in Sources */, 0A584BF12C3E949B0071A651 /* ADJAppStoreSubscription.m in Sources */, + 9D7D3DF02C49A8B200FACB18 /* ADJDeeplink.m in Sources */, 0A584BF22C3E949B0071A651 /* ADJAttribution.m in Sources */, 0A584BF32C3E949B0071A651 /* ADJConfig.m in Sources */, 0A584BF42C3E949B0071A651 /* ADJEvent.m in Sources */, @@ -2726,6 +2764,7 @@ 0A584BA42C3E94230071A651 /* ADJAdRevenue.m in Sources */, 0A584BA52C3E94230071A651 /* ADJAppStorePurchase.m in Sources */, 0A584BA62C3E94240071A651 /* ADJAppStoreSubscription.m in Sources */, + 9D7D3DEF2C49A8B200FACB18 /* ADJDeeplink.m in Sources */, 0A584BA72C3E94240071A651 /* ADJAttribution.m in Sources */, 0A584BA82C3E94240071A651 /* ADJConfig.m in Sources */, 0A584BA92C3E94240071A651 /* ADJEvent.m in Sources */, @@ -2770,6 +2809,7 @@ 0A584C3A2C3E94E70071A651 /* ADJAdRevenue.m in Sources */, 0A584C3B2C3E94E70071A651 /* ADJAppStorePurchase.m in Sources */, 0A584C3C2C3E94E70071A651 /* ADJAppStoreSubscription.m in Sources */, + 9D7D3DF32C49A8B200FACB18 /* ADJDeeplink.m in Sources */, 0A584C3D2C3E94E70071A651 /* ADJAttribution.m in Sources */, 0A584C3E2C3E94E70071A651 /* ADJConfig.m in Sources */, 0A584C3F2C3E94E70071A651 /* ADJEvent.m in Sources */, diff --git a/Adjust/ADJDeeplink.h b/Adjust/ADJDeeplink.h new file mode 100644 index 000000000..966850205 --- /dev/null +++ b/Adjust/ADJDeeplink.h @@ -0,0 +1,19 @@ +// +// ADJDeeplink.h +// Adjust +// +// Created by Uglješa Erceg (@uerceg) on 18th July 2024. +// Copyright © 2024-Present Adjust. All rights reserved. +// + +#import + +@interface ADJDeeplink : NSObject + +@property (nonatomic, copy, readonly, nonnull) NSURL *deeplink; + +@property (nonatomic, copy, nullable) NSURL *referrer; + +- (nullable ADJDeeplink *)initWithDeeplink:(nonnull NSURL *)deeplink; + +@end diff --git a/Adjust/ADJDeeplink.m b/Adjust/ADJDeeplink.m new file mode 100644 index 000000000..8d4b52b07 --- /dev/null +++ b/Adjust/ADJDeeplink.m @@ -0,0 +1,24 @@ +// +// ADJDeeplink.m +// Adjust +// +// Created by Uglješa Erceg (@uerceg) on 18th July 2024. +// Copyright © 2024-Present Adjust. All rights reserved. +// + +#import "ADJDeeplink.h" + +@implementation ADJDeeplink + +- (id)initWithDeeplink:(NSURL *)deeplink { + self = [super init]; + if (self == nil) { + return nil; + } + + _deeplink = deeplink; + + return self; +} + +@end diff --git a/Adjust/Adjust.h b/Adjust/Adjust.h index 4ad0cace8..2d5452c91 100644 --- a/Adjust/Adjust.h +++ b/Adjust/Adjust.h @@ -18,6 +18,7 @@ @class ADJLinkResolution; @class ADJAppStorePurchase; @class ADJPurchaseVerificationResult; +@class ADJDeeplink; typedef void(^ADJResolvedDeeplinkBlock)(NSString * _Nullable resolvedLink); typedef void(^ADJAttributionGetterBlock)(ADJAttribution * _Nullable attribution); @@ -88,9 +89,9 @@ extern NSString * __nonnull const ADJEnvironmentProduction; /** * @brief Read the URL that opened the application to search for an adjust deep link. * - * @param deeplink URL object which contains info about adjust deep link. + * @param deeplink Deeplink object which contains info about adjust deep link. */ -+ (void)processDeeplink:(nonnull NSURL *)deeplink; ++ (void)processDeeplink:(nonnull ADJDeeplink *)deeplink; /** * @brief Process the deep link that has opened an app and potentially get a resolved link. @@ -98,7 +99,7 @@ extern NSString * __nonnull const ADJEnvironmentProduction; * @param deeplink URL object which contains info about adjust deep link. * @param completion Completion block where either resolved or echoed deep link will be sent. */ -+ (void)processAndResolveDeeplink:(nonnull NSURL *)deeplink ++ (void)processAndResolveDeeplink:(nonnull ADJDeeplink *)deeplink withCompletionHandler:(nonnull ADJResolvedDeeplinkBlock)completion; /** diff --git a/Adjust/Adjust.m b/Adjust/Adjust.m index c14800fd9..e51936633 100644 --- a/Adjust/Adjust.m +++ b/Adjust/Adjust.m @@ -14,6 +14,7 @@ #import "ADJActivityHandler.h" #import "ADJSKAdNetwork.h" #import "ADJPurchaseVerificationResult.h" +#import "ADJDeeplink.h" #if !__has_feature(objc_arc) #error Adjust requires ARC @@ -109,13 +110,13 @@ + (void)isEnabledWithCompletionHandler:(nonnull ADJIsEnabledGetterBlock)completi } } -+ (void)processDeeplink:(NSURL *)deeplink { ++ (void)processDeeplink:(ADJDeeplink *)deeplink { @synchronized (self) { - [[Adjust getInstance] processDeeplink:[deeplink copy]]; + [[Adjust getInstance] processDeeplink:deeplink]; } } -+ (void)processAndResolveDeeplink:(nonnull NSURL *)deeplink ++ (void)processAndResolveDeeplink:(nonnull ADJDeeplink *)deeplink withCompletionHandler:(nonnull ADJResolvedDeeplinkBlock)completion { @synchronized (self) { [[Adjust getInstance] processAndResolveDeeplink:deeplink @@ -396,17 +397,19 @@ - (void)isEnabledWithCompletionHandler:(nonnull ADJIsEnabledGetterBlock)completi [self.activityHandler isEnabledWithCompletionHandler:completion]; } -- (void)processDeeplink:(NSURL *)deeplink { - [ADJUserDefaults cacheDeeplinkUrl:deeplink]; +- (void)processDeeplink:(ADJDeeplink *)deeplink { + [ADJUserDefaults cacheDeeplinkUrl:deeplink.deeplink]; NSDate *clickTime = [NSDate date]; if (![self checkActivityHandler]) { - [ADJUserDefaults saveDeeplinkUrl:deeplink andClickTime:clickTime]; + [ADJUserDefaults saveDeeplinkUrl:deeplink.deeplink + referrerUrl:deeplink.referrer + clickTime:clickTime]; return; } [self.activityHandler processDeeplink:deeplink withClickTime:clickTime]; } -- (void)processAndResolveDeeplink:(nonnull NSURL *)deeplink +- (void)processAndResolveDeeplink:(nonnull ADJDeeplink *)deeplink withCompletionHandler:(nonnull ADJResolvedDeeplinkBlock)completion { // if resolution result is not wanted, fallback to default method if (completion == nil) { @@ -414,10 +417,12 @@ - (void)processAndResolveDeeplink:(nonnull NSURL *)deeplink return; } // if deep link processing is triggered prior to SDK being initialized - [ADJUserDefaults cacheDeeplinkUrl:deeplink]; + [ADJUserDefaults cacheDeeplinkUrl:deeplink.deeplink]; NSDate *clickTime = [NSDate date]; if (![self checkActivityHandler]) { - [ADJUserDefaults saveDeeplinkUrl:deeplink andClickTime:clickTime]; + [ADJUserDefaults saveDeeplinkUrl:deeplink.deeplink + referrerUrl:deeplink.referrer + clickTime:clickTime]; self.cachedResolvedDeeplinkBlock = completion; return; } diff --git a/Adjust/Internal/ADJActivityHandler.h b/Adjust/Internal/ADJActivityHandler.h index 26a1e933d..2470ac8e2 100644 --- a/Adjust/Internal/ADJActivityHandler.h +++ b/Adjust/Internal/ADJActivityHandler.h @@ -75,9 +75,9 @@ - (void)isEnabledWithCompletionHandler:(nonnull ADJIsEnabledGetterBlock)completion; - (BOOL)isGdprForgotten; -- (void)processDeeplink:(NSURL * _Nullable)deeplink +- (void)processDeeplink:(ADJDeeplink * _Nullable)deeplink withClickTime:(NSDate * _Nullable)clickTime; -- (void)processAndResolveDeeplink:(NSURL * _Nullable)deeplink +- (void)processAndResolveDeeplink:(ADJDeeplink * _Nullable)deeplink clickTime:(NSDate * _Nullable)clickTime withCompletionHandler:(ADJResolvedDeeplinkBlock _Nullable)completion; - (void)setPushTokenData:(NSData * _Nullable)pushTokenData; diff --git a/Adjust/Internal/ADJActivityHandler.m b/Adjust/Internal/ADJActivityHandler.m index f96831bb8..ac30e8964 100644 --- a/Adjust/Internal/ADJActivityHandler.m +++ b/Adjust/Internal/ADJActivityHandler.m @@ -26,6 +26,7 @@ #import "ADJPurchaseVerificationHandler.h" #import "ADJPurchaseVerificationResult.h" #import "ADJAdRevenue.h" +#import "ADJDeeplink.h" NSString * const ADJAdServicesPackageKey = @"apple_ads"; @@ -394,22 +395,28 @@ - (BOOL)isGdprForgotten { return [self isGdprForgottenI:self]; } -- (void)processDeeplink:(NSURL *)deeplink withClickTime:(NSDate *)clickTime { +- (void)processDeeplink:(ADJDeeplink *)deeplink withClickTime:(NSDate *)clickTime { [ADJUtil launchInQueue:self.internalQueue selfInject:self block:^(ADJActivityHandler * selfI) { - [selfI processDeeplinkI:selfI url:deeplink clickTime:clickTime]; + [selfI processDeeplinkI:selfI + url:deeplink.deeplink + referrer:deeplink.referrer + clickTime:clickTime]; }]; } -- (void)processAndResolveDeeplink:(NSURL * _Nullable)deeplink +- (void)processAndResolveDeeplink:(ADJDeeplink * _Nullable)deeplink clickTime:(NSDate * _Nullable)clickTime withCompletionHandler:(ADJResolvedDeeplinkBlock _Nullable)completion { [ADJUtil launchInQueue:self.internalQueue selfInject:self block:^(ADJActivityHandler * selfI) { selfI.cachedDeeplinkResolutionCallback = completion; - [selfI processDeeplinkI:selfI url:deeplink clickTime:clickTime]; + [selfI processDeeplinkI:selfI + url:deeplink.deeplink + referrer:deeplink.referrer + clickTime:clickTime]; }]; } @@ -1161,8 +1168,13 @@ - (void)processCachedDeeplinkI:(ADJActivityHandler *)selfI { if (cachedDeeplinkClickTime == nil) { return; } + // referrer URL can be nil + NSURL *cachedDeeplinkReferrerUrl = [ADJUserDefaults getDeeplinkReferrerUrl]; - [selfI processDeeplinkI:selfI url:cachedDeeplinkUrl clickTime:cachedDeeplinkClickTime]; + [selfI processDeeplinkI:selfI + url:cachedDeeplinkUrl + referrer:cachedDeeplinkReferrerUrl + clickTime:cachedDeeplinkClickTime]; [ADJUserDefaults removeDeeplink]; } @@ -1912,6 +1924,7 @@ - (void)checkStatusI:(ADJActivityHandler *)selfI - (void)processDeeplinkI:(ADJActivityHandler *)selfI url:(NSURL *)deeplink + referrer:(NSURL *)referrer clickTime:(NSDate *)clickTime { if (![selfI isEnabledI:selfI]) { return; @@ -1931,7 +1944,10 @@ - (void)processDeeplinkI:(ADJActivityHandler *)selfI NSMutableDictionary *adjustDeepLinks = [NSMutableDictionary dictionary]; ADJAttribution *deeplinkAttribution = [[ADJAttribution alloc] init]; for (NSString *fieldValuePair in queryArray) { - [selfI readDeeplinkQueryStringI:selfI queryString:fieldValuePair adjustDeepLinks:adjustDeepLinks attribution:deeplinkAttribution]; + [selfI readDeeplinkQueryStringI:selfI + queryString:fieldValuePair + adjustDeepLinks:adjustDeepLinks + attribution:deeplinkAttribution]; } double now = [NSDate.date timeIntervalSince1970]; @@ -1940,18 +1956,21 @@ - (void)processDeeplinkI:(ADJActivityHandler *)selfI double lastInterval = now - selfI.activityState.lastActivity; selfI.activityState.lastInterval = lastInterval; }]; - ADJPackageBuilder *clickBuilder = [[ADJPackageBuilder alloc] - initWithPackageParams:selfI.packageParams + ADJPackageBuilder *clickBuilder = + [[ADJPackageBuilder alloc] initWithPackageParams:selfI.packageParams activityState:selfI.activityState - config:selfI.adjustConfig - globalParameters:selfI.globalParameters - trackingStatusManager:self.trackingStatusManager - createdAt:now]; + config:selfI.adjustConfig + globalParameters:selfI.globalParameters + trackingStatusManager:self.trackingStatusManager + createdAt:now]; clickBuilder.internalState = selfI.internalState; clickBuilder.deeplinkParameters = [adjustDeepLinks copy]; clickBuilder.attribution = deeplinkAttribution; clickBuilder.clickTime = clickTime; clickBuilder.deeplink = [deeplink absoluteString]; + if (referrer != nil) { + clickBuilder.deeplinkReferrer = [referrer absoluteString]; + } ADJActivityPackage *clickPackage = [clickBuilder buildClickPackage:@"deeplink"]; [selfI.sdkClickHandler sendSdkClick:clickPackage]; diff --git a/Adjust/Internal/ADJPackageBuilder.h b/Adjust/Internal/ADJPackageBuilder.h index a33ace8e6..91acf59b4 100644 --- a/Adjust/Internal/ADJPackageBuilder.h +++ b/Adjust/Internal/ADJPackageBuilder.h @@ -20,6 +20,8 @@ @property (nonatomic, copy) NSString * _Nullable deeplink; +@property (nonatomic, copy) NSString * _Nullable deeplinkReferrer; + @property (nonatomic, copy) NSString * _Nullable reftag; @property (nonatomic, copy) NSDate * _Nullable clickTime; diff --git a/Adjust/Internal/ADJPackageBuilder.m b/Adjust/Internal/ADJPackageBuilder.m index 83e7e294b..b73e4db13 100644 --- a/Adjust/Internal/ADJPackageBuilder.m +++ b/Adjust/Internal/ADJPackageBuilder.m @@ -604,6 +604,7 @@ - (NSMutableDictionary *)getClickParameters:(NSString *)source { [ADJPackageBuilder parameters:parameters setDictionary:self.deeplinkParameters forKey:@"params"]; [ADJPackageBuilder parameters:parameters setDictionary:[self.globalParameters.partnerParameters copy] forKey:@"partner_params"]; [ADJPackageBuilder parameters:parameters setDate:self.purchaseTime forKey:@"purchase_time"]; + [ADJPackageBuilder parameters:parameters setString:self.deeplinkReferrer forKey:@"referrer"]; [ADJPackageBuilder parameters:parameters setDate:[ADJUserDefaults getSkadRegisterCallTimestamp] forKey:@"skadn_registered_at"]; [ADJPackageBuilder parameters:parameters setString:source forKey:@"source"]; [ADJPackageBuilder parameters:parameters setDate1970:(double)self.packageParams.startedAt forKey:@"started_at"]; diff --git a/Adjust/Internal/ADJUserDefaults.h b/Adjust/Internal/ADJUserDefaults.h index 9b5dbf924..d5508f3a6 100644 --- a/Adjust/Internal/ADJUserDefaults.h +++ b/Adjust/Internal/ADJUserDefaults.h @@ -37,10 +37,13 @@ + (void)removeCoppaCompliance; + (void)saveDeeplinkUrl:(NSURL *)deeplink - andClickTime:(NSDate *)clickTime; + referrerUrl:(NSURL *)referrer + clickTime:(NSDate *)clickTime; + (NSURL *)getDeeplinkUrl; ++ (NSURL *)getDeeplinkReferrerUrl; + + (NSDate *)getDeeplinkClickTime; + (void)removeDeeplink; diff --git a/Adjust/Internal/ADJUserDefaults.m b/Adjust/Internal/ADJUserDefaults.m index bc3225a38..4da194d1e 100644 --- a/Adjust/Internal/ADJUserDefaults.m +++ b/Adjust/Internal/ADJUserDefaults.m @@ -14,6 +14,7 @@ static NSString * const PREFS_KEY_INSTALL_TRACKED = @"adj_install_tracked"; static NSString * const PREFS_KEY_COPPA_COMPLIANCE = @"adj_coppa_compliance"; static NSString * const PREFS_KEY_DEEPLINK_URL = @"adj_deeplink_url"; +static NSString * const PREFS_KEY_DEEPLINK_REFERRER_URL = @"adj_deeplink_referrer_url"; static NSString * const PREFS_KEY_DEEPLINK_CLICK_TIME = @"adj_deeplink_click_time"; static NSString * const PREFS_KEY_ADSERVICES_TRACKED = @"adj_adservices_tracked"; static NSString * const PREFS_KEY_SKAD_REGISTER_CALL_TIME = @"adj_skad_register_call_time"; @@ -21,6 +22,7 @@ static NSString * const PREFS_KEY_DEEPLINK_URL_CACHED = @"adj_deeplink_url_cached"; static NSString * const PREFS_KEY_ATT_WAITING_REMAINING_SECONDS = @"adj_att_waiting_remaining_seconds"; static NSString * const PREFS_KEY_CONTROL_PARAMS = @"adj_control_params"; +static NSString * const PREFS_KEY_DEEPLINK_REFERRER_URL_CACHED = @"adj_deeplink_referrer_url_cached"; @implementation ADJUserDefaults @@ -78,11 +80,13 @@ + (BOOL)getCoppaCompliance { + (void)removeCoppaCompliance { [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_COPPA_COMPLIANCE]; - } -+ (void)saveDeeplinkUrl:(NSURL *)deeplink andClickTime:(NSDate *)clickTime { ++ (void)saveDeeplinkUrl:(NSURL *)deeplink + referrerUrl:(NSURL *)referrer + clickTime:(NSDate *)clickTime { [[NSUserDefaults standardUserDefaults] setURL:deeplink forKey:PREFS_KEY_DEEPLINK_URL]; + [[NSUserDefaults standardUserDefaults] setURL:referrer forKey:PREFS_KEY_DEEPLINK_REFERRER_URL]; [[NSUserDefaults standardUserDefaults] setObject:clickTime forKey:PREFS_KEY_DEEPLINK_CLICK_TIME]; } @@ -90,12 +94,17 @@ + (NSURL *)getDeeplinkUrl { return [[NSUserDefaults standardUserDefaults] URLForKey:PREFS_KEY_DEEPLINK_URL]; } ++ (NSURL *)getDeeplinkReferrerUrl { + return [[NSUserDefaults standardUserDefaults] URLForKey:PREFS_KEY_DEEPLINK_REFERRER_URL]; +} + + (NSDate *)getDeeplinkClickTime { return [[NSUserDefaults standardUserDefaults] objectForKey:PREFS_KEY_DEEPLINK_CLICK_TIME]; } + (void)removeDeeplink { [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_DEEPLINK_URL]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_DEEPLINK_REFERRER_URL]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_DEEPLINK_CLICK_TIME]; } @@ -164,6 +173,7 @@ + (void)clearAdjustStuff { [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_COPPA_COMPLIANCE]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_GDPR_FORGET_ME]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_DEEPLINK_URL]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_DEEPLINK_REFERRER_URL]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_DEEPLINK_CLICK_TIME]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_ADSERVICES_TRACKED]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_SKAD_REGISTER_CALL_TIME]; diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m index dc59c466c..f6e126ea4 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m @@ -580,8 +580,12 @@ - (void)setPushToken:(NSDictionary *)parameters { - (void)openDeeplink:(NSDictionary *)parameters { NSString *deeplinkS = [parameters objectForKey:@"deeplink"][0]; + NSString *referrerS = [parameters objectForKey:@"referrer"][0]; NSURL *deeplink = [NSURL URLWithString:deeplinkS]; - [Adjust processDeeplink:deeplink]; + NSURL *referrer = [NSURL URLWithString:referrerS]; + ADJDeeplink *adjustDeeplink = [[ADJDeeplink alloc] initWithDeeplink:deeplink]; + adjustDeeplink.referrer = referrer; + [Adjust processDeeplink:adjustDeeplink]; } - (void)gdprForgetMe:(NSDictionary *)parameters { @@ -793,7 +797,7 @@ - (void)verifyTrack:(NSDictionary *)parameters { - (void)processDeeplink:(NSDictionary *)parameters { NSString *deeplinkS = [parameters objectForKey:@"deeplink"][0]; NSURL *deeplink = [NSURL URLWithString:deeplinkS]; - [Adjust processAndResolveDeeplink:deeplink + [Adjust processAndResolveDeeplink:[[ADJDeeplink alloc] initWithDeeplink:deeplink] withCompletionHandler:^(NSString * _Nullable resolvedLink) { [self.testLibrary addInfoToSend:@"resolved_link" value:resolvedLink]; [self.testLibrary sendInfoToServer:self.extraPath]; diff --git a/UmbrellaHeaders/sdk/AdjustSdk.h b/UmbrellaHeaders/sdk/AdjustSdk.h index b4af8433e..b8e5b15b3 100644 --- a/UmbrellaHeaders/sdk/AdjustSdk.h +++ b/UmbrellaHeaders/sdk/AdjustSdk.h @@ -23,3 +23,4 @@ #import #import #import +#import diff --git a/UmbrellaHeaders/webbridge/AdjustSdk.h b/UmbrellaHeaders/webbridge/AdjustSdk.h index d16f8de06..ee02fc963 100644 --- a/UmbrellaHeaders/webbridge/AdjustSdk.h +++ b/UmbrellaHeaders/webbridge/AdjustSdk.h @@ -23,6 +23,7 @@ #import #import #import +#import #import #import