88
99#import " BNCSKAdNetwork.h"
1010#import " BNCApplication.h"
11+ #import " BNCPreferenceHelper.h"
12+ #import " BranchConstants.h"
1113
1214@interface BNCSKAdNetwork ()
1315
@@ -17,6 +19,7 @@ @interface BNCSKAdNetwork()
1719@property (nonatomic , assign , readwrite ) SEL skAdNetworkRegisterAppForAdNetworkAttribution;
1820@property (nonatomic , assign , readwrite ) SEL skAdNetworkUpdateConversionValue;
1921@property (nonatomic , assign , readwrite ) SEL skAdNetworkUpdatePostbackConversionValue;
22+ @property (nonatomic , assign , readwrite ) SEL skAdNetworkUpdatePostbackConversionValueCoarseValueLockWindow;
2023
2124@end
2225
@@ -34,14 +37,21 @@ + (BNCSKAdNetwork *)sharedInstance {
3437- (instancetype )init {
3538 self = [super init ];
3639 if (self) {
37- // by default, we send updates to SKAdNetwork for up a day after install
38- self.maxTimeSinceInstall = 3600.0 * 24.0 ;
40+ if (@available (iOS 16.1 , *)){
41+ // For SKAN 4.0, its 60 days = 3600.0 * 24.0 * 60 seconds
42+ self.maxTimeSinceInstall = 3600.0 * 24.0 * 60 ;
43+ } else {
44+ // by default, we send updates to SKAdNetwork for up a day after install
45+ self.maxTimeSinceInstall = 3600.0 * 24.0 ;
46+ }
47+
3948 self.installDate = [BNCApplication currentApplication ].currentInstallDate ;
4049
4150 self.skAdNetworkClass = NSClassFromString (@" SKAdNetwork" );
4251 self.skAdNetworkRegisterAppForAdNetworkAttribution = NSSelectorFromString (@" registerAppForAdNetworkAttribution" );
4352 self.skAdNetworkUpdateConversionValue = NSSelectorFromString (@" updateConversionValue:" );
4453 self.skAdNetworkUpdatePostbackConversionValue = NSSelectorFromString (@" updatePostbackConversionValue:completionHandler:" );
54+ self.skAdNetworkUpdatePostbackConversionValueCoarseValueLockWindow = NSSelectorFromString (@" updatePostbackConversionValue:coarseValue:lockWindow:completionHandler:" );
4555 }
4656 return self;
4757}
@@ -91,4 +101,93 @@ - (void)updatePostbackConversionValue:(NSInteger)conversionValue
91101
92102}
93103
104+ - (void )updatePostbackConversionValue : (NSInteger )fineValue
105+ coarseValue : (NSString *)coarseValue
106+ lockWindow : (BOOL )lockWindow
107+ completionHandler : (void (^)(NSError *error))completion {
108+ if (@available (iOS 16.1 , *)) {
109+ if ([self shouldAttemptSKAdNetworkCallout ]) {
110+
111+ ((id (*)(id , SEL , NSInteger , NSString *, BOOL , void (^)(NSError *error)))[self .skAdNetworkClass methodForSelector: self .skAdNetworkUpdatePostbackConversionValueCoarseValueLockWindow])(self.skAdNetworkClass , self.skAdNetworkUpdatePostbackConversionValueCoarseValueLockWindow , fineValue, coarseValue, lockWindow, completion);
112+ }
113+ }
114+ }
115+
116+ - (int ) calculateSKANWindowForTime : (NSDate *) currentTime {
117+
118+ int firstWindowDuration = 2 * 24 * 3600 ;
119+ int secondWindowDuration = 7 * 24 * 3600 ;
120+ int thirdWindowDuration = 35 * 24 * 3600 ;
121+
122+ NSTimeInterval timeDiff = [currentTime timeIntervalSinceDate: [BNCPreferenceHelper sharedInstance ].firstAppLaunchTime];
123+
124+ if (timeDiff <= firstWindowDuration) {
125+ return BranchSkanWindowFirst;
126+ } else if (timeDiff <= secondWindowDuration) {
127+ return BranchSkanWindowSecond;
128+ }else if (timeDiff <= thirdWindowDuration) {
129+ return BranchSkanWindowThird;
130+ }
131+ return BranchSkanWindowInvalid;
132+ }
133+
134+ - (NSString *) getCoarseConversionValueFromDataResponse : (NSDictionary *) dataResponseDictionary {
135+
136+ NSString *coarseConversionValue = dataResponseDictionary[BRANCH_RESPONSE_KEY_COARSE_KEY] ;
137+
138+ if (!coarseConversionValue)
139+ return @" low" ;
140+
141+ return coarseConversionValue;
142+
143+ }
144+
145+ - (BOOL ) getLockedStatusFromDataResponse : (NSDictionary *) dataResponseDictionary {
146+
147+ BOOL lockWin = NO ;
148+ if ([dataResponseDictionary[BRANCH_RESPONSE_KEY_UPDATE_IS_LOCKED] isKindOfClass: NSNumber .class])
149+ lockWin = ((NSNumber *)dataResponseDictionary[BRANCH_RESPONSE_KEY_UPDATE_IS_LOCKED]).boolValue ;
150+ return lockWin;
151+ }
152+
153+ - (BOOL ) getAscendingOnlyFromDataResponse : (NSDictionary *) dataResponseDictionary {
154+
155+ BOOL ascendingOnly = YES ;
156+ if ([dataResponseDictionary[BRANCH_RESPONSE_KEY_ASCENDING_ONLY] isKindOfClass: NSNumber .class])
157+ ascendingOnly = ((NSNumber *)dataResponseDictionary[BRANCH_RESPONSE_KEY_ASCENDING_ONLY]).boolValue ;
158+ return ascendingOnly;
159+ }
160+
161+ - (BOOL ) shouldCallPostbackForDataResponse : (NSDictionary *) dataResponseDictionary {
162+
163+ BOOL shouldCallUpdatePostback = NO ;
164+
165+ if (![BNCPreferenceHelper sharedInstance ].invokeRegisterApp )
166+ return shouldCallUpdatePostback;
167+
168+ NSNumber *conversionValue = (NSNumber *)dataResponseDictionary[BRANCH_RESPONSE_KEY_UPDATE_CONVERSION_VALUE];
169+
170+ int currentWindow = [self calculateSKANWindowForTime: [NSDate date ]];
171+
172+ if (currentWindow == BranchSkanWindowInvalid)
173+ return shouldCallUpdatePostback;
174+
175+ if ( [BNCPreferenceHelper sharedInstance ].skanCurrentWindow < currentWindow) {
176+ [BNCPreferenceHelper sharedInstance ].highestConversionValueSent = 0 ;
177+ [BNCPreferenceHelper sharedInstance ].skanCurrentWindow = currentWindow;
178+ }
179+
180+ int highestConversionValue = (int )[BNCPreferenceHelper sharedInstance ].highestConversionValueSent ;
181+ if ( conversionValue.intValue <= highestConversionValue ){
182+ BOOL ascendingOnly = [self getAscendingOnlyFromDataResponse: dataResponseDictionary];
183+ if (!ascendingOnly)
184+ shouldCallUpdatePostback = YES ;
185+ } else {
186+ [BNCPreferenceHelper sharedInstance ].highestConversionValueSent = conversionValue.intValue ;
187+ shouldCallUpdatePostback = YES ;
188+ }
189+
190+ return shouldCallUpdatePostback;
191+ }
192+
94193@end
0 commit comments