From 2b49ddd6a6e77363f690a3873fb9236e5b4d8025 Mon Sep 17 00:00:00 2001 From: nonelse Date: Fri, 3 Aug 2018 09:32:37 +0200 Subject: [PATCH 01/27] Consolidate WK and UI bridge register --- AdjustBridge/AdjustBridge.h | 2 +- AdjustBridge/AdjustBridge.m | 15 ++++++++---- AdjustBridge/AdjustBridgeRegister.h | 13 ++++++++++ AdjustBridge/AdjustBridgeRegister.m | 37 +++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/AdjustBridge/AdjustBridge.h b/AdjustBridge/AdjustBridge.h index 6e52a84bc..7aab0f9e9 100644 --- a/AdjustBridge/AdjustBridge.h +++ b/AdjustBridge/AdjustBridge.h @@ -14,7 +14,7 @@ @interface AdjustBridge : NSObject -@property (nonatomic, strong, readonly) id bridgeRegister; +@property (nonatomic, strong, readonly) AdjustBridgeRegister * bridgeRegister; - (void)loadUIWebViewBridge:(WVJB_WEBVIEW_TYPE *)webView; - (void)loadWKWebViewBridge:(WKWebView *)wkWebView; diff --git a/AdjustBridge/AdjustBridge.m b/AdjustBridge/AdjustBridge.m index c5ebe3333..e6de0c9fd 100644 --- a/AdjustBridge/AdjustBridge.m +++ b/AdjustBridge/AdjustBridge.m @@ -138,11 +138,12 @@ - (void)loadUIWebViewBridge:(WVJB_WEBVIEW_TYPE *)webView // WebViewBridge already loaded. return; } - +/* AdjustUIBridgeRegister *uiBridgeRegister = [AdjustUIBridgeRegister bridgeRegisterWithUIWebView:webView]; [uiBridgeRegister setWebViewDelegate:webViewDelegate]; _bridgeRegister = uiBridgeRegister; - [self loadWebViewBridge]; + */ + [self loadWebViewBridge:webView webViewDelegate:webViewDelegate]; } - (void)loadWKWebViewBridge:(WKWebView *)wkWebView @@ -151,14 +152,18 @@ - (void)loadWKWebViewBridge:(WKWebView *)wkWebView // WebViewBridge already loaded. return; } - +/* AdjustWKBridgeRegister *wkBridgeRegister = [AdjustWKBridgeRegister bridgeRegisterWithWKWebView:wkWebView]; [wkBridgeRegister setWebViewDelegate:wkWebViewDelegate]; _bridgeRegister = wkBridgeRegister; - [self loadWebViewBridge]; +*/ + [self loadWebViewBridge:wkWebView webViewDelegate:wkWebViewDelegate]; } -- (void)loadWebViewBridge { +- (void)loadWebViewBridge:(id)webView webViewDelegate:(id)webViewDelegate { + _bridgeRegister = [[AdjustBridgeRegister alloc] initWithWebView:webView]; + [self.bridgeRegister setWebViewDelegate:webViewDelegate]; + // Register setCallback method to save callbacks before appDidLaunch [self.bridgeRegister registerHandler:@"adjust_setCallback" handler:^(id data, WVJBResponseCallback responseCallback) { if (responseCallback == nil) { diff --git a/AdjustBridge/AdjustBridgeRegister.h b/AdjustBridge/AdjustBridgeRegister.h index 032ad003b..a560656ff 100644 --- a/AdjustBridge/AdjustBridgeRegister.h +++ b/AdjustBridge/AdjustBridgeRegister.h @@ -9,10 +9,22 @@ #import #import "WebViewJavascriptBridge.h" +@interface AdjustBridgeRegister : NSObject + +- (id)initWithWebView:(id)webView; +- (void)setWebViewDelegate:(id)webViewDelegate; + +- (void)callHandler:(NSString *)handlerName data:(id)data; +- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler; + +@end +/* @protocol AdjustBridgeRegister - (void)callHandler:(NSString *)handlerName data:(id)data; - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler; +- (void)augmentHybridWebView; ++ (NSString *)AdjustBridge_js; @end @@ -29,3 +41,4 @@ - (void)setWebViewDelegate:(id)webViewDelegate; @end +*/ diff --git a/AdjustBridge/AdjustBridgeRegister.m b/AdjustBridge/AdjustBridgeRegister.m index a5f125300..459f1c1eb 100644 --- a/AdjustBridge/AdjustBridgeRegister.m +++ b/AdjustBridge/AdjustBridgeRegister.m @@ -10,6 +10,42 @@ static NSString * const kHandlerPrefix = @"adjust_"; +@interface AdjustBridgeRegister() + +@property (nonatomic, strong) WebViewJavascriptBridge *wvjb; +@property BOOL isToAugmentHybridWebView; + +@end + +@implementation AdjustBridgeRegister + +- (id)initWithWebView:(id)webView { + self = [super init]; + if (self == nil) { + return nil; + } + + self.wvjb = [WebViewJavascriptBridge bridgeForWebView:webView]; + self.isToAugmentHybridWebView = NO; + return self; +} + +- (void)setWebViewDelegate:(id)webViewDelegate { + [self.wvjb setWebViewDelegate:webViewDelegate]; +} + +- (void)callHandler:(NSString *)handlerName data:(id)data { + [self.wvjb callHandler:handlerName data:data]; +} + +- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { + [self.wvjb registerHandler:handlerName handler:handler]; +} + + +@end +/* + @interface AdjustUIBridgeRegister() @property (nonatomic, strong) WebViewJavascriptBridge *uiBridge; @@ -93,3 +129,4 @@ - (void)callHandler:(NSString *)handlerName data:(id)data { } @end +*/ From a90a85d72d1ca2dd57bd786dff4ffb12aac70741 Mon Sep 17 00:00:00 2001 From: nonelse Date: Fri, 3 Aug 2018 09:36:36 +0200 Subject: [PATCH 02/27] Load adjust JS from register --- AdjustBridge/AdjustBridgeRegister.h | 1 + AdjustBridge/AdjustBridgeRegister.m | 284 ++++++++++++++++++ .../WebViewJavascriptBridgeBase.m | 6 +- 3 files changed, 289 insertions(+), 2 deletions(-) diff --git a/AdjustBridge/AdjustBridgeRegister.h b/AdjustBridge/AdjustBridgeRegister.h index a560656ff..f47bea07b 100644 --- a/AdjustBridge/AdjustBridgeRegister.h +++ b/AdjustBridge/AdjustBridgeRegister.h @@ -16,6 +16,7 @@ - (void)callHandler:(NSString *)handlerName data:(id)data; - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler; ++ (NSString *)AdjustBridge_js; @end /* diff --git a/AdjustBridge/AdjustBridgeRegister.m b/AdjustBridge/AdjustBridgeRegister.m index 459f1c1eb..9c674d4b8 100644 --- a/AdjustBridge/AdjustBridgeRegister.m +++ b/AdjustBridge/AdjustBridgeRegister.m @@ -42,6 +42,290 @@ - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { [self.wvjb registerHandler:handlerName handler:handler]; } ++ (NSString *)AdjustBridge_js { +#define __adj_wvjb_js_func__(x) #x + // BEGIN preprocessorJSCode + static NSString * preprocessorJSCode = + @__adj_wvjb_js_func__(;(function() { + if (window.Adjust) { + return; + } + + // copied from adjust.js + window.Adjust = { + appDidLaunch: function (adjustConfig) { + if (WebViewJavascriptBridge) { + if (adjustConfig) { + adjustConfig.iterateConfiguredCallbacks( + function(callbackName, callback) { + WebViewJavascriptBridge.callHandler('adjust_setCallback', callbackName, callback); + } + ); + WebViewJavascriptBridge.callHandler('adjust_appDidLaunch', adjustConfig, null); + } + } + }, + trackEvent: function (adjustEvent) { + if (WebViewJavascriptBridge) { + WebViewJavascriptBridge.callHandler('adjust_trackEvent', adjustEvent, null); + } + }, + trackSubsessionStart: function() { + if (WebViewJavascriptBridge) { + WebViewJavascriptBridge.callHandler('adjust_trackSubsessionStart', null, null); + } + }, + trackSubsessionEnd: function() { + if (WebViewJavascriptBridge) { + WebViewJavascriptBridge.callHandler('adjust_trackSubsessionEnd', null, null); + } + }, + setEnabled: function (enabled) { + if (WebViewJavascriptBridge) { + WebViewJavascriptBridge.callHandler('adjust_setEnabled', enabled, null); + } + }, + isEnabled: function (callback) { + if (WebViewJavascriptBridge) { + WebViewJavascriptBridge.callHandler('adjust_isEnabled', null, + function(response) { + callback(new Boolean(response)); + } + ); + } + }, + appWillOpenUrl: function (url) { + if (WebViewJavascriptBridge) { + WebViewJavascriptBridge.callHandler('adjust_appWillOpenUrl', url, null); + } + }, + setDeviceToken: function (deviceToken) { + if (WebViewJavascriptBridge) { + WebViewJavascriptBridge.callHandler('adjust_setDeviceToken', deviceToken, null); + } + }, + setOfflineMode: function(isOffline) { + if (WebViewJavascriptBridge) { + WebViewJavascriptBridge.callHandler('adjust_setOfflineMode', isOffline, null); + } + }, + getIdfa: function (callback) { + if (WebViewJavascriptBridge) { + WebViewJavascriptBridge.callHandler('adjust_idfa', null, callback); + } + }, + getAdid: function (callback) { + if (WebViewJavascriptBridge) { + WebViewJavascriptBridge.callHandler('adjust_adid', null, callback); + } + }, + getAttribution: function (callback) { + if (WebViewJavascriptBridge) { + WebViewJavascriptBridge.callHandler('adjust_attribution', null, callback); + } + }, + sendFirstPackages: function () { + if (WebViewJavascriptBridge) { + WebViewJavascriptBridge.callHandler('adjust_sendFirstPackages', null, null); + } + }, + addSessionCallbackParameter: function (key, value) { + if (WebViewJavascriptBridge != null) { + WebViewJavascriptBridge.callHandler('adjust_addSessionCallbackParameter', {key: key, value: value}, null); + } + }, + addSessionPartnerParameter: function (key, value) { + if (WebViewJavascriptBridge != null) { + WebViewJavascriptBridge.callHandler('adjust_addSessionPartnerParameter', {key: key, value: value}, null); + } + }, + removeSessionCallbackParameter: function (key) { + if (WebViewJavascriptBridge != null) { + WebViewJavascriptBridge.callHandler('adjust_removeSessionCallbackParameter', key, null); + } + }, + removeSessionPartnerParameter: function (key) { + if (WebViewJavascriptBridge != null) { + WebViewJavascriptBridge.callHandler('adjust_removeSessionPartnerParameter', key, null); + } + }, + resetSessionCallbackParameters: function () { + if (WebViewJavascriptBridge != null) { + WebViewJavascriptBridge.callHandler('adjust_resetSessionCallbackParameters', null, null); + } + }, + resetSessionPartnerParameters: function () { + if (WebViewJavascriptBridge != null) { + WebViewJavascriptBridge.callHandler('adjust_resetSessionPartnerParameters', null, null); + } + }, + gdprForgetMe: function () { + if (WebViewJavascriptBridge != null) { + WebViewJavascriptBridge.callHandler('adjust_gdprForgetMe', null, null); + } + } + }; + + // copied from adjust_event.js + window.AdjustEvent = function (eventToken) { + this.eventToken = eventToken; + + this.revenue = null; + this.currency = null; + this.transactionId = null; + + this.callbackParameters = []; + this.partnerParameters = []; + }; + + AdjustEvent.prototype.addCallbackParameter = function(key, value) { + this.callbackParameters.push(key); + this.callbackParameters.push(value); + }; + + AdjustEvent.prototype.addPartnerParameter = function(key, value) { + this.partnerParameters.push(key); + this.partnerParameters.push(value); + }; + + AdjustEvent.prototype.setRevenue = function(revenue, currency) { + this.revenue = revenue; + this.currency = currency; + }; + + AdjustEvent.prototype.setTransactionId = function(transactionId) { + this.transactionId = transactionId; + }; + + // copied from adjust_config.js + window.AdjustConfig = function (appToken, environment, legacy) { + + if (arguments.length === 2) { + // New format does not require bridge as first parameter. + this.appToken = appToken; + this.environment = environment; + } else if (arguments.length === 3) { + // New format with allowSuppressLogLevel. + if (typeof(legacy) == typeof(true)) { + this.appToken = appToken; + this.environment = environment; + this.allowSuppressLogLevel = legacy; + } else { + // Old format with first argument being the bridge instance. + this.bridge = appToken; + this.appToken = environment; + this.environment = legacy; + } + } + + this.sdkPrefix = 'web-bridge4.14.0'; + this.defaultTracker = null; + this.logLevel = null; + this.eventBufferingEnabled = null; + this.sendInBackground = null; + this.delayStart = null; + this.userAgent = null; + this.isDeviceKnown = null; + this.secretId = null; + this.info1 = null; + this.info2 = null; + this.info3 = null; + this.info4 = null; + this.openDeferredDeeplink = null; + this.callbacksMap = {}; + this.test = null; + }; + AdjustConfig.EnvironmentSandbox = 'sandbox'; + AdjustConfig.EnvironmentProduction = 'production'; + + AdjustConfig.LogLevelVerbose = 'VERBOSE'; + AdjustConfig.LogLevelDebug = 'DEBUG'; + AdjustConfig.LogLevelInfo = 'INFO'; + AdjustConfig.LogLevelWarn = 'WARN'; + AdjustConfig.LogLevelError = 'ERROR'; + AdjustConfig.LogLevelAssert = 'ASSERT'; + AdjustConfig.LogLevelSuppress = 'SUPPRESS'; + + AdjustConfig.prototype.iterateConfiguredCallbacks = function(handleCallbackWithName) { + if (!this.callbacksMap) { + return; + } + var keysArray = Object.keys(this.callbacksMap); + for (var idx in keysArray) { + var key = keysArray[idx]; + handleCallbackWithName(key, this.callbacksMap[key]); + } + }; + + AdjustConfig.prototype.setSdkPrefix = function(sdkPrefix) { + this.sdkPrefix = sdkPrefix; + }; + AdjustConfig.prototype.setDefaultTracker = function(defaultTracker) { + this.defaultTracker = defaultTracker; + }; + AdjustConfig.prototype.setLogLevel = function(logLevel) { + this.logLevel = logLevel; + }; + AdjustConfig.prototype.setEventBufferingEnabled = function(isEnabled) { + this.eventBufferingEnabled = isEnabled; + }; + AdjustConfig.prototype.setSendInBackground = function(isEnabled) { + this.sendInBackground = isEnabled; + }; + AdjustConfig.prototype.setDelayStart = function(delayStartInSeconds) { + this.delayStart = delayStartInSeconds; + }; + AdjustConfig.prototype.setUserAgent = function(userAgent) { + this.userAgent = userAgent; + }; + AdjustConfig.prototype.setIsDeviceKnown = function(isDeviceKnown) { + this.isDeviceKnown = isDeviceKnown; + }; + AdjustConfig.prototype.setAppSecret = function(secretId, info1, info2, info3, info4) { + this.secretId = secretId; + this.info1 = info1; + this.info2 = info2; + this.info3 = info3; + this.info4 = info4; + }; + + AdjustConfig.prototype.setOpenDeferredDeeplink = function(shouldOpen) { + this.openDeferredDeeplink = shouldOpen; + }; + + AdjustConfig.prototype.setAttributionCallback = function(callback) { + this.callbacksMap['attributionCallback'] = callback; + }; + + AdjustConfig.prototype.setEventSuccessCallback = function(callback) { + this.callbacksMap['eventSuccessCallback'] = callback; + }; + + AdjustConfig.prototype.setEventFailureCallback = function(callback) { + this.callbacksMap['eventFailureCallback'] = callback; + }; + + AdjustConfig.prototype.setSessionSuccessCallback = function(callback) { + this.callbacksMap['sessionSuccessCallback'] = callback; + }; + + AdjustConfig.prototype.setSessionFailureCallback = function(callback) { + this.callbacksMap['sessionFailureCallback'] = callback; + }; + + AdjustConfig.prototype.setDeferredDeeplinkCallback = function(callback) { + this.callbacksMap['deferredDeeplinkCallback'] = callback; + }; + + AdjustConfig.prototype.setTest = function() { + this.test = true; + }; + + })();); // END preprocessorJSCode + +#undef __adj_wvjb_js_func__ + return preprocessorJSCode; +} @end /* diff --git a/AdjustBridge/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m b/AdjustBridge/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m index b6f4ec141..d68140586 100755 --- a/AdjustBridge/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m +++ b/AdjustBridge/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m @@ -8,7 +8,8 @@ #import #import "WebViewJavascriptBridgeBase.h" #import "WebViewJavascriptBridge_JS.h" -#import "AdjustBridge_JS.h" +//#import "AdjustBridge_JS.h" +#import "AdjustBridgeRegister.h" @implementation WebViewJavascriptBridgeBase { __weak id _webViewDelegate; @@ -115,7 +116,8 @@ - (void)injectJavascriptFile { NSString *js = WebViewJavascriptBridge_js(); [self _evaluateJavascript:js]; // Added to inject adjust js code - NSString *adjust_js = AdjustBridge_js(); + //NSString *adjust_js = AdjustBridge_js(); + NSString *adjust_js = [AdjustBridgeRegister AdjustBridge_js]; [self _evaluateJavascript:adjust_js]; if (self.startupMessageQueue) { NSArray* queue = self.startupMessageQueue; From 617c565fd61fe838a9262e1220c2586ffb34c5d6 Mon Sep 17 00:00:00 2001 From: nonelse Date: Fri, 3 Aug 2018 12:22:51 +0200 Subject: [PATCH 03/27] Add fb pixel bridge --- AdjustBridge/AdjustBridge.h | 2 + AdjustBridge/AdjustBridge.m | 93 +++++++++++++++++++++++++++++ AdjustBridge/AdjustBridgeRegister.h | 1 + AdjustBridge/AdjustBridgeRegister.m | 68 +++++++++++++++++---- 4 files changed, 153 insertions(+), 11 deletions(-) diff --git a/AdjustBridge/AdjustBridge.h b/AdjustBridge/AdjustBridge.h index 7aab0f9e9..2ce0ca2bd 100644 --- a/AdjustBridge/AdjustBridge.h +++ b/AdjustBridge/AdjustBridge.h @@ -21,4 +21,6 @@ - (void)loadUIWebViewBridge:(WVJB_WEBVIEW_TYPE *)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE *)webViewDelegate; - (void)loadWKWebViewBridge:(WKWebView *)wkWebView wkWebViewDelegate:(id)wkWebViewDelegate; +- (void)augmentHybridWebView; + @end diff --git a/AdjustBridge/AdjustBridge.m b/AdjustBridge/AdjustBridge.m index e6de0c9fd..b81c05fbc 100644 --- a/AdjustBridge/AdjustBridge.m +++ b/AdjustBridge/AdjustBridge.m @@ -26,6 +26,8 @@ @interface AdjustBridge() @property WVJBResponseCallback sessionSuccessCallback; @property WVJBResponseCallback sessionFailureCallback; @property WVJBResponseCallback deferredDeeplinkCallback; +@property (nonatomic, copy) NSString *fbPixelDefaultEventToken; +@property (nonatomic, strong) NSMutableDictionary* fbPixelMapping; @end @@ -46,6 +48,8 @@ - (id)init { self.eventFailureCallback = nil; self.sessionSuccessCallback = nil; self.sessionFailureCallback = nil; + self.fbPixelDefaultEventToken = nil; + self.fbPixelMapping = nil; return self; } @@ -124,6 +128,17 @@ - (BOOL)adjustDeeplinkResponse:(NSURL *)deeplink { #pragma mark - Public methods +- (void)augmentHybridWebView { + NSString * fbAppId = [self getFbAppId]; + + if (fbAppId == nil) { + [[ADJAdjustFactory logger] error:@"FacebookAppID is not correctly configured in the pList"]; + return; + } + [_bridgeRegister augmentHybridWebView:fbAppId]; + [self registerAugmentedView]; +} + - (void)loadUIWebViewBridge:(WVJB_WEBVIEW_TYPE *)webView { [self loadUIWebViewBridge:webView webViewDelegate:nil]; } @@ -203,6 +218,8 @@ - (void)loadWebViewBridge:(id)webView webViewDelegate:(id)webViewDelegate { NSNumber *info3 = [data objectForKey:@"info3"]; NSNumber *info4 = [data objectForKey:@"info4"]; NSNumber *openDeferredDeeplink = [data objectForKey:@"openDeferredDeeplink"]; + NSString *fbPixelDefaultEventToken = [data objectForKey:@"fbPixelDefaultEventToken"]; + id fbPixelMapping = [data objectForKey:@"fbPixelMapping"]; ADJConfig *adjustConfig; if ([self isFieldValid:allowSuppressLogLevel]) { @@ -255,6 +272,18 @@ - (void)loadWebViewBridge:(id)webView webViewDelegate:(id)webViewDelegate { if ([self isFieldValid:openDeferredDeeplink]) { self.openDeferredDeeplink = [openDeferredDeeplink boolValue]; } + if ([self isFieldValid:fbPixelDefaultEventToken]) { + self.fbPixelDefaultEventToken = fbPixelDefaultEventToken; + } + if ([fbPixelMapping count] > 0) { + self.fbPixelMapping = [[NSMutableDictionary alloc] initWithCapacity:[fbPixelMapping count] / 2]; + } + for (int i = 0; i < [fbPixelMapping count]; i += 2) { + NSString *key = [[fbPixelMapping objectAtIndex:i] description]; + NSString *value = [[fbPixelMapping objectAtIndex:(i + 1)] description]; + [self.fbPixelMapping setObject:value forKey:key]; + } + // Set self as delegate if any callback is configured. // Change to swifle the methods in the future. if (self.attributionCallback != nil @@ -421,6 +450,50 @@ - (void)loadWebViewBridge:(id)webView webViewDelegate:(id)webViewDelegate { }]; } +- (void)registerAugmentedView { + [self.bridgeRegister registerHandler:@"adjust_fbPixelEvent" handler:^(id data, WVJBResponseCallback responseCallback) { + NSString *pixelID = [data objectForKey:@"pixelID"]; + if (pixelID == nil) { + [[ADJAdjustFactory logger] error:@"Can't bridge an event without a referral Pixel ID. Check your webview Pixel configuration"]; + return; + } + NSString *evtName = [data objectForKey:@"evtName"]; + NSString *eventToken = [self getEventTokenFromFbPixelEventName:evtName]; + if (eventToken == nil) { + [[ADJAdjustFactory logger] debug:@"No mapping found for the fb pixel event %@, trying to fall back to the default event token", evtName]; + eventToken = self.fbPixelDefaultEventToken; + } + if (eventToken == nil) { + [[ADJAdjustFactory logger] debug:@"There is a also not a default event token configured, it won't be tracked"]; + return; + } + + ADJEvent * fbPixelEvent = [ADJEvent eventWithEventToken:eventToken]; + if (![fbPixelEvent isValid]) { + return; + } + + id customData = [data objectForKey:@"customData"]; + + [fbPixelEvent addPartnerParameter:@"_fb_pixel_referral_id" value:pixelID]; + //[fbPixelEvent addPartnerParameter:@"_eventName" value:evtName]; + if ([customData isKindOfClass:[NSString class]]) { + NSError *jsonParseError = nil; + NSDictionary * params = + [NSJSONSerialization JSONObjectWithData:[customData dataUsingEncoding:NSUTF8StringEncoding] + options:NSJSONReadingMutableContainers + error:&jsonParseError + ]; + [params enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + NSString * keyS = [key description]; + NSString * valueS = [obj description]; + [fbPixelEvent addPartnerParameter:keyS value:valueS]; + }]; + } + [Adjust trackEvent:fbPixelEvent]; + }]; +} + #pragma mark - Private & helper methods - (BOOL)isFieldValid:(NSObject *)field { @@ -433,4 +506,24 @@ - (BOOL)isFieldValid:(NSObject *)field { return YES; } +- (NSString *)getFbAppId { + NSString * facebookLoggingOverrideAppID = [self getValueFromBundleByKey:@"FacebookLoggingOverrideAppID"]; + + if (facebookLoggingOverrideAppID != nil) { + return facebookLoggingOverrideAppID; + } + return [self getValueFromBundleByKey:@"FacebookAppID"]; +} + +- (NSString *)getValueFromBundleByKey:(NSString *)key { + return [[[NSBundle mainBundle] objectForInfoDictionaryKey:key] copy]; +} + +- (NSString *)getEventTokenFromFbPixelEventName:(NSString *)fbPixelEventName { + if (self.fbPixelMapping == nil) { + return nil; + } + return [self.fbPixelMapping objectForKey:fbPixelEventName]; +} + @end diff --git a/AdjustBridge/AdjustBridgeRegister.h b/AdjustBridge/AdjustBridgeRegister.h index f47bea07b..d35042223 100644 --- a/AdjustBridge/AdjustBridgeRegister.h +++ b/AdjustBridge/AdjustBridgeRegister.h @@ -16,6 +16,7 @@ - (void)callHandler:(NSString *)handlerName data:(id)data; - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler; +- (void)augmentHybridWebView:(NSString *)fbAppId; + (NSString *)AdjustBridge_js; @end diff --git a/AdjustBridge/AdjustBridgeRegister.m b/AdjustBridge/AdjustBridgeRegister.m index 9c674d4b8..ffb8821a6 100644 --- a/AdjustBridge/AdjustBridgeRegister.m +++ b/AdjustBridge/AdjustBridgeRegister.m @@ -10,10 +10,11 @@ static NSString * const kHandlerPrefix = @"adjust_"; +static NSString * fbAppIdStatic = nil; + @interface AdjustBridgeRegister() @property (nonatomic, strong) WebViewJavascriptBridge *wvjb; -@property BOOL isToAugmentHybridWebView; @end @@ -26,7 +27,6 @@ - (id)initWithWebView:(id)webView { } self.wvjb = [WebViewJavascriptBridge bridgeForWebView:webView]; - self.isToAugmentHybridWebView = NO; return self; } @@ -42,11 +42,41 @@ - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { [self.wvjb registerHandler:handlerName handler:handler]; } +- (void)augmentHybridWebView:(NSString *)fbAppId { + fbAppIdStatic = fbAppId; +} + + (NSString *)AdjustBridge_js { -#define __adj_wvjb_js_func__(x) #x - // BEGIN preprocessorJSCode - static NSString * preprocessorJSCode = - @__adj_wvjb_js_func__(;(function() { + if (fbAppIdStatic != nil) { + return [NSString stringWithFormat:@"%@%@" + ,[AdjustBridgeRegister adjust_js] + ,[AdjustBridgeRegister augmented_js]]; + } else { + return [AdjustBridgeRegister adjust_js]; + } +} + +#define __adj_js_func__(x) #x +// BEGIN preprocessorJSCode + ++ (NSString *)augmented_js { + return [NSString stringWithFormat: + @__adj_js_func__(;(function() { + window['fbmq_%@'] = { + 'getProtocol' : function() { + return 'fbmq-0.1'; + + }, + 'sendEvent': function(pixelID, evtName, customData) { + Adjust.fbPixelEvent(pixelID, evtName, customData); + } + }; + })();) // END preprocessorJSCode + , fbAppIdStatic]; +} + ++ (NSString *)adjust_js { + static NSString * preprocessorJSCode = @__adj_js_func__(;(function() { if (window.Adjust) { return; } @@ -163,6 +193,16 @@ + (NSString *)AdjustBridge_js { if (WebViewJavascriptBridge != null) { WebViewJavascriptBridge.callHandler('adjust_gdprForgetMe', null, null); } + }, + fbPixelEvent: function (pixelID, evtName, customData) { + if (WebViewJavascriptBridge != null) { + WebViewJavascriptBridge.callHandler('adjust_fbPixelEvent', + { pixelID: pixelID, + evtName:evtName, + customData: customData + }, + null); + } } }; @@ -233,7 +273,8 @@ + (NSString *)AdjustBridge_js { this.info4 = null; this.openDeferredDeeplink = null; this.callbacksMap = {}; - this.test = null; + this.fbPixelDefaultEventToken = null; + this.fbPixelMapping = []; }; AdjustConfig.EnvironmentSandbox = 'sandbox'; AdjustConfig.EnvironmentProduction = 'production'; @@ -317,13 +358,18 @@ + (NSString *)AdjustBridge_js { this.callbacksMap['deferredDeeplinkCallback'] = callback; }; - AdjustConfig.prototype.setTest = function() { - this.test = true; + AdjustConfig.prototype.setFbPixelDefaultEventToken = function(fbPixelDefaultEventToken) { + this.fbPixelDefaultEventToken = fbPixelDefaultEventToken; }; - })();); // END preprocessorJSCode + AdjustConfig.prototype.addFbPixelMapping = function(fbEventNameKey, adjEventTokenValue) { + this.fbPixelMapping.push(fbEventNameKey); + this.fbPixelMapping.push(adjEventTokenValue); + }; -#undef __adj_wvjb_js_func__ + })();); // END preprocessorJSCode + //, augmentedSection]; +#undef __adj_js_func__ return preprocessorJSCode; } From 9d9267d883b45e16000296c55ea5c50fcd49c4d0 Mon Sep 17 00:00:00 2001 From: Pedro Filipe Date: Fri, 3 Aug 2018 14:05:51 +0200 Subject: [PATCH 04/27] Create fb_pixel.md --- doc/english/fb_pixel.md | 124 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 doc/english/fb_pixel.md diff --git a/doc/english/fb_pixel.md b/doc/english/fb_pixel.md new file mode 100644 index 000000000..17fc0a070 --- /dev/null +++ b/doc/english/fb_pixel.md @@ -0,0 +1,124 @@ +## Facebook pixel integration + +[The Facebook Pixel](https://www.facebook.com/business/help/952192354843755) is a web only analytics tool from Facebook. +Usually, it would not be possible to use in a web view app, but since [FB SDK](https://developers.facebook.com/docs/analytics) +was updated to v4.34, it's now possible to use the [Hybrid Mobile App Events](https://developers.facebook.com/docs/app-events/hybrid-app-events) +to convert Facebook Pixel events into Facebook App events. + +The adjust SDK now also allows you to use the Facebook pixel in your web view app, without the need of integrating the FB SDK. + +### Facebook integration + +#### Facebook App ID + +Even though, there is no need to integrate the FB SDK, it's still required to follow some of the integration steps from FB SDK +to allow the adjust SDK to integrate the Facebook Pixel. + +As is described in the [FB SDK iOS SDK guide](https://developers.facebook.com/docs/ios/getting-started/#xcode) +you need to add your Facebook App ID to the app. You can follow the steps on that guide, but we copied it here: + +1. In Xcode, right-click your project's `Info.plist` file and select Open As -> Source Code. + +2. Insert the following XML snippet into the body of your file just before the final `` element. + +```xml + + ... + FacebookAppID + {your-app-id} + ... + +``` + +3. Replace `{your-app-id}`, with your app's App's ID found on the *Facebook App Dashboard*. + +#### Facebook Pixel configuration + +Follow Facebook's guide how to integrate the Facebook Pixel. The Javascript code should look something like this: + +```js + + +... + +``` + +Now, just like described in [Hybrid Mobile App Events guide](https://developers.facebook.com/docs/app-events/hybrid-app-events) +`Update Your Pixel` section, you need to update the Facebook Pixel code like so: + +```js +fbq('init', ); +fbq('set', 'mobileBridge', , ); +``` + +### Adjust integration + +#### Augment the webview + +First, you still need to follow the integration guide for [iOs web view](web_views.md) apps. +Then in the section where you load the webview bridge, like so: + +```objc +- (void)viewWillAppear:(BOOL)animated { + ... + UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.bounds]; + // or with WKWebView: + // WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds]; + + // add @property (nonatomic, strong) AdjustBridge *adjustBridge; on your interface + self.adjustBridge = [[AdjustBridge alloc] init]; + [self.adjustBridge loadUIWebViewBridge:webView]; + // optionally you can add a web view delegate so that you can also capture its events + // [self.adjustBridge loadUIWebViewBridge:webView webViewDelegate:(UIWebViewDelegate*)self]; + + // or with WKWebView: + // [self.adjustBridge loadWKWebViewBridge:webView]; + // optionally you can add a web view delegate so that you can also capture its events + // [self.adjustBridge loadWKWebViewBridge:webView wkWebViewDelegate:(id)self]; + ... +``` + +however you choose to load the webview into the adjust bridge, afterwards add the following line: + +```objc +[self.adjustBridge augmentHybridWebView]; +``` + +#### Event name configuration + +The adjust web bridge SDK needs to translate the Facebook Pixel events into adjust events. + +For this reason it's necessary to configure either a mapping between a Facebook Pixel to a specific adjust event, or to +configure a default adjust event token ***before*** tracking any Facebook Pixel event, +including the copy-pasted `fbq('track', 'PageView');` from the Facebook Pixel configuration. + +To add mappings between Facebook Pixel events and adjust events, you need to call `addFbPixelMapping(fbEventNameKey, adjEventTokenValue)` +in the `adjustConfig` instance before initialise the adjust SDK. An example of mapping could be: + +```js +adjustConfig.addFbPixelMapping('fb_mobile_search', adjustEventTokenForSearch); +adjustConfig.addFbPixelMapping('fb_mobile_purchase', adjustEventTokenForPurchase); +``` + +Take notice that this would match when tracking the Facebook pixel events `fbq('track', 'Search', ...);` and +`fbq('track', 'Purchase', ...);` respectively. Unfortunatly we do not have access to the mapping between the event name +tracked in javascript and the event name used by the FB SDK. + +Some don't even have a event name different mapping, so you will need to test the different Facebook Pixel event types +your app uses and see what event names they will be translated into our SDK. During tests you should be able to see a log +like `Facebook Pixel event with name 'fb_mobile_search' tracked from Javascript`. To help you, we've colled the following +event name mappings that we found so far. Take note that, although unlikely, Facebook could change them, and likely add new +ones in the future: + +``` +TODO, table with even name mappings +``` + +There is also the option to have a default adjust event to be used if a mapping is not configured. +Just call `adjustConfig.setFbPixelDefaultEventToken(defaultEventToken);` before initialise the adjust SDK. + From 4bb64bc69eb3f2b5643fd4ece2e5f44aeaaa070a Mon Sep 17 00:00:00 2001 From: Pedro Filipe Date: Fri, 3 Aug 2018 14:23:00 +0200 Subject: [PATCH 05/27] Update fb_pixel.md --- doc/english/fb_pixel.md | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/doc/english/fb_pixel.md b/doc/english/fb_pixel.md index 17fc0a070..1484e19e3 100644 --- a/doc/english/fb_pixel.md +++ b/doc/english/fb_pixel.md @@ -109,14 +109,24 @@ Take notice that this would match when tracking the Facebook pixel events `fbq(' `fbq('track', 'Purchase', ...);` respectively. Unfortunatly we do not have access to the mapping between the event name tracked in javascript and the event name used by the FB SDK. -Some don't even have a event name different mapping, so you will need to test the different Facebook Pixel event types -your app uses and see what event names they will be translated into our SDK. During tests you should be able to see a log -like `Facebook Pixel event with name 'fb_mobile_search' tracked from Javascript`. To help you, we've colled the following -event name mappings that we found so far. Take note that, although unlikely, Facebook could change them, and likely add new -ones in the future: +To help you, we've colled the following event name mappings that we found so far: + +| Pixel event name | Corresponding Facebook app event name +| ---------------- | ------------------------------------- +| ViewContent | fb_mobile_content_view +| Search | fb_mobile_search +| AddToCart | fb_mobile_add_to_cart +| AddToWishlist | fb_mobile_add_to_wishlist +| InitiateCheckout | fb_mobile_initiated_checkout +| AddPaymentInfo | fb_mobile_add_payment_info +| Purchase | fb_mobile_purchase +| CompleteRegistration | fb_mobile_complete_registration + +This might not be an exaustive list, and it's possible that Facebook adds or updates the current listing. +To make sure, during tests, check the adjust logs for warning like: ``` -TODO, table with even name mappings +There is not a default event token configured or a mapping found for event named: 'fb_mobile_search'. It won't be tracked as an adjust event ``` There is also the option to have a default adjust event to be used if a mapping is not configured. From c3fee096902eca1afc7ffef859ca7c29a59c9ffa Mon Sep 17 00:00:00 2001 From: nonelse Date: Fri, 3 Aug 2018 14:27:58 +0200 Subject: [PATCH 06/27] Remove unecessary files and sections --- Adjust.xcodeproj/project.pbxproj | 10 - AdjustBridge/AdjustBridgeRegister.m | 86 ----- .../WebViewJavascriptBridge/AdjustBridge_JS.h | 11 - .../WebViewJavascriptBridge/AdjustBridge_JS.m | 303 ------------------ .../project.pbxproj | 6 - 5 files changed, 416 deletions(-) delete mode 100644 AdjustBridge/WebViewJavascriptBridge/AdjustBridge_JS.h delete mode 100644 AdjustBridge/WebViewJavascriptBridge/AdjustBridge_JS.m diff --git a/Adjust.xcodeproj/project.pbxproj b/Adjust.xcodeproj/project.pbxproj index 7deefe82e..51eee01d2 100644 --- a/Adjust.xcodeproj/project.pbxproj +++ b/Adjust.xcodeproj/project.pbxproj @@ -23,7 +23,6 @@ /* Begin PBXBuildFile section */ 2067002A1F18BDC700B4FDE1 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9601C19C1A31DD7F00A9AE21 /* CoreTelephony.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - 6FA69FD72101E00100FCD3B5 /* AdjustBridge_JS.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FA69FD62101E00100FCD3B5 /* AdjustBridge_JS.m */; }; 6FCC85001F278CF300D6A0ED /* ADJReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FCC84F71F278CF300D6A0ED /* ADJReachability.m */; }; 6FCC85011F278CF300D6A0ED /* ADJReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FCC84F81F278CF300D6A0ED /* ADJReachability.h */; }; 6FCC85041F27945E00D6A0ED /* ADJReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FCC85021F27944600D6A0ED /* ADJReachability.h */; }; @@ -211,12 +210,10 @@ 9D0E2EAE210B575600133B4F /* AdjustBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D0E2E5C210B575600133B4F /* AdjustBridge.m */; }; 9D0E2EAF210B575600133B4F /* AdjustBridgeRegister.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D0E2E5D210B575600133B4F /* AdjustBridgeRegister.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9D0E2EB0210B575600133B4F /* WebViewJavascriptBridgeBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D0E2E5F210B575600133B4F /* WebViewJavascriptBridgeBase.m */; }; - 9D0E2EB1210B575600133B4F /* AdjustBridge_JS.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D0E2E60210B575600133B4F /* AdjustBridge_JS.m */; }; 9D0E2EB2210B575600133B4F /* WKWebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D0E2E61210B575600133B4F /* WKWebViewJavascriptBridge.m */; }; 9D0E2EB3210B575600133B4F /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D0E2E62210B575600133B4F /* WebViewJavascriptBridge.m */; }; 9D0E2EB4210B575600133B4F /* WebViewJavascriptBridge_JS.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D0E2E63210B575600133B4F /* WebViewJavascriptBridge_JS.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9D0E2EB5210B575600133B4F /* WebViewJavascriptBridgeBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D0E2E64210B575600133B4F /* WebViewJavascriptBridgeBase.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9D0E2EB6210B575600133B4F /* AdjustBridge_JS.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D0E2E65210B575600133B4F /* AdjustBridge_JS.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9D0E2EB7210B575600133B4F /* WebViewJavascriptBridge_JS.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D0E2E66210B575600133B4F /* WebViewJavascriptBridge_JS.m */; }; 9D0E2EB8210B575600133B4F /* WebViewJavascriptBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D0E2E67210B575600133B4F /* WebViewJavascriptBridge.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9D0E2EB9210B575600133B4F /* WKWebViewJavascriptBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D0E2E68210B575600133B4F /* WKWebViewJavascriptBridge.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -553,8 +550,6 @@ /* Begin PBXFileReference section */ 6F0842182007766700568A31 /* AdjustTestLibrary.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AdjustTestLibrary.xcodeproj; path = AdjustTestLibrary/AdjustTestLibrary.xcodeproj; sourceTree = ""; }; 6F084240200776A000568A31 /* AdjustTestApp.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AdjustTestApp.xcodeproj; path = AdjustTestApp/AdjustTestApp.xcodeproj; sourceTree = ""; }; - 6FA69FD52101E00100FCD3B5 /* AdjustBridge_JS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AdjustBridge_JS.h; sourceTree = ""; }; - 6FA69FD62101E00100FCD3B5 /* AdjustBridge_JS.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AdjustBridge_JS.m; sourceTree = ""; }; 6FCC84F71F278CF300D6A0ED /* ADJReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJReachability.m; sourceTree = ""; }; 6FCC84F81F278CF300D6A0ED /* ADJReachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJReachability.h; sourceTree = ""; }; 6FCC85021F27944600D6A0ED /* ADJReachability.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ADJReachability.h; sourceTree = ""; }; @@ -1152,8 +1147,6 @@ 9648C5E51CD1765E00A3B049 /* WebViewJavascriptBridge */ = { isa = PBXGroup; children = ( - 6FA69FD52101E00100FCD3B5 /* AdjustBridge_JS.h */, - 6FA69FD62101E00100FCD3B5 /* AdjustBridge_JS.m */, 9648C5E61CD1765E00A3B049 /* WebViewJavascriptBridge.h */, 9648C5E71CD1765E00A3B049 /* WebViewJavascriptBridge.m */, 9648C5E81CD1765E00A3B049 /* WebViewJavascriptBridge_JS.h */, @@ -1830,7 +1823,6 @@ 9D0E2E06210B570600133B4F /* AdjustSdkWebBridge.h in Headers */, 9D0E2EBA210B575600133B4F /* AdjustBridge.h in Headers */, 9D0E2EAF210B575600133B4F /* AdjustBridgeRegister.h in Headers */, - 9D0E2EB6210B575600133B4F /* AdjustBridge_JS.h in Headers */, 9D0E2EB8210B575600133B4F /* WebViewJavascriptBridge.h in Headers */, 9D0E2EB9210B575600133B4F /* WKWebViewJavascriptBridge.h in Headers */, 9D0E2EB4210B575600133B4F /* WebViewJavascriptBridge_JS.h in Headers */, @@ -2402,7 +2394,6 @@ 961515A31CD2CB9D0022D336 /* WebViewJavascriptBridge.m in Sources */, 961515A41CD2CBA20022D336 /* WebViewJavascriptBridge_JS.m in Sources */, 961515A61CD2CBAC0022D336 /* WKWebViewJavascriptBridge.m in Sources */, - 6FA69FD72101E00100FCD3B5 /* AdjustBridge_JS.m in Sources */, 961515A51CD2CBA80022D336 /* WebViewJavascriptBridgeBase.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2512,7 +2503,6 @@ 9D0E2E6D210B575600133B4F /* ADJTimerOnce.m in Sources */, 9D0E2E77210B575600133B4F /* ADJEvent.m in Sources */, 9D0E2E8D210B575600133B4F /* ADJConfig.m in Sources */, - 9D0E2EB1210B575600133B4F /* AdjustBridge_JS.m in Sources */, 9D0E2E6E210B575600133B4F /* ADJAttributionHandler.m in Sources */, 9D0E2E87210B575600133B4F /* ADJBackoffStrategy.m in Sources */, 9D0E2EBB210B575600133B4F /* AdjustBridgeRegister.m in Sources */, diff --git a/AdjustBridge/AdjustBridgeRegister.m b/AdjustBridge/AdjustBridgeRegister.m index ffb8821a6..0ad8bb6af 100644 --- a/AdjustBridge/AdjustBridgeRegister.m +++ b/AdjustBridge/AdjustBridgeRegister.m @@ -374,89 +374,3 @@ + (NSString *)adjust_js { } @end -/* - -@interface AdjustUIBridgeRegister() - -@property (nonatomic, strong) WebViewJavascriptBridge *uiBridge; - -@end - -@implementation AdjustUIBridgeRegister - -+ (id)bridgeRegisterWithUIWebView:(WVJB_WEBVIEW_TYPE *)uiWebView { - return [[AdjustUIBridgeRegister alloc] initWithUIWebView:uiWebView]; -} - -- (id)initWithUIWebView:(WVJB_WEBVIEW_TYPE *)uiWebView { - self = [super init]; - if (self == nil) { - return nil; - } - - self.uiBridge = [WebViewJavascriptBridge bridgeForWebView:uiWebView]; - return self; -} - -- (void)setWebViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE *)webViewDelegate { - [self.uiBridge setWebViewDelegate:webViewDelegate]; -} - -- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { - if ([handlerName hasPrefix:kHandlerPrefix] == NO) { - return; - } - [self.uiBridge registerHandler:handlerName handler:handler]; -} - -- (void)callHandler:(NSString *)handlerName data:(id)data { - if ([handlerName hasPrefix:kHandlerPrefix] == NO) { - return; - } - [self.uiBridge callHandler:handlerName data:data]; -} - -@end - -@interface AdjustWKBridgeRegister() - -@property (nonatomic, strong) WebViewJavascriptBridge *wkBridge; - -@end - -@implementation AdjustWKBridgeRegister - -+ (id)bridgeRegisterWithWKWebView:(WKWebView *)wkWebView { - return [[AdjustWKBridgeRegister alloc] initWithWKWebView:wkWebView]; -} - -- (id)initWithWKWebView:(WKWebView *)wkWebView { - self = [super init]; - if (self == nil) { - return nil; - } - - self.wkBridge = [WebViewJavascriptBridge bridgeForWebView:wkWebView]; - return self; -} - -- (void)setWebViewDelegate:(id)webViewDelegate { - [self.wkBridge setWebViewDelegate:webViewDelegate]; -} - -- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { - if ([handlerName hasPrefix:kHandlerPrefix] == NO) { - return; - } - [self.wkBridge registerHandler:handlerName handler:handler]; -} - -- (void)callHandler:(NSString *)handlerName data:(id)data { - if ([handlerName hasPrefix:kHandlerPrefix] == NO) { - return; - } - [self.wkBridge callHandler:handlerName data:data]; -} - -@end -*/ diff --git a/AdjustBridge/WebViewJavascriptBridge/AdjustBridge_JS.h b/AdjustBridge/WebViewJavascriptBridge/AdjustBridge_JS.h deleted file mode 100644 index 6fac087a9..000000000 --- a/AdjustBridge/WebViewJavascriptBridge/AdjustBridge_JS.h +++ /dev/null @@ -1,11 +0,0 @@ -// -// AdjustBridge_JS.h -// Adjust SDK -// -// Created by Pedro Filipe (@nonelse) on 20th July 2018. -// Copyright © 2018 Adjust GmbH. All rights reserved. -// - -#import - -NSString * AdjustBridge_js(void); diff --git a/AdjustBridge/WebViewJavascriptBridge/AdjustBridge_JS.m b/AdjustBridge/WebViewJavascriptBridge/AdjustBridge_JS.m deleted file mode 100644 index 89088ee18..000000000 --- a/AdjustBridge/WebViewJavascriptBridge/AdjustBridge_JS.m +++ /dev/null @@ -1,303 +0,0 @@ -// -// AdjustBridge_JS.m -// Adjust SDK -// -// Created by Pedro Filipe (@nonelse) on 20th July 2018. -// Copyright © 2018 Adjust GmbH. All rights reserved. -// - -// This file including the header and format is copied with adaptions from -// WebViewJavascriptBridge_JS.m - -// This file contains the source for the Javascript side of the -// Adjust Webview bridge. It is plaintext, but converted to an NSString -// via some preprocessor tricks. - -// Previous implementations of Adjust Webview bridge loaded the javascript source -// from a resource. This worked fine for app developers, but library developers who -// included the bridge into their library, awkwardly had to ask consumers of their -// library to include the resource, violating their encapsulation. By including the -// Javascript as a string resource, the encapsulation of the library is maintained. - -#import "AdjustBridge_JS.h" - -NSString * AdjustBridge_js() { - #define __adj_wvjb_js_func__(x) #x - // BEGIN preprocessorJSCode - static NSString * preprocessorJSCode = @__adj_wvjb_js_func__( -;(function() { - if (window.Adjust) { - return; - } - - // copied from adjust.js - window.Adjust = { - appDidLaunch: function (adjustConfig) { - if (WebViewJavascriptBridge) { - if (adjustConfig) { - adjustConfig.iterateConfiguredCallbacks( - function(callbackName, callback) { - WebViewJavascriptBridge.callHandler('adjust_setCallback', callbackName, callback); - } - ); - WebViewJavascriptBridge.callHandler('adjust_appDidLaunch', adjustConfig, null); - } - } - }, - trackEvent: function (adjustEvent) { - if (WebViewJavascriptBridge) { - WebViewJavascriptBridge.callHandler('adjust_trackEvent', adjustEvent, null); - } - }, - trackSubsessionStart: function() { - if (WebViewJavascriptBridge) { - WebViewJavascriptBridge.callHandler('adjust_trackSubsessionStart', null, null); - } - }, - trackSubsessionEnd: function() { - if (WebViewJavascriptBridge) { - WebViewJavascriptBridge.callHandler('adjust_trackSubsessionEnd', null, null); - } - }, - setEnabled: function (enabled) { - if (WebViewJavascriptBridge) { - WebViewJavascriptBridge.callHandler('adjust_setEnabled', enabled, null); - } - }, - isEnabled: function (callback) { - if (WebViewJavascriptBridge) { - WebViewJavascriptBridge.callHandler('adjust_isEnabled', null, - function(response) { - callback(new Boolean(response)); - } - ); - } - }, - appWillOpenUrl: function (url) { - if (WebViewJavascriptBridge) { - WebViewJavascriptBridge.callHandler('adjust_appWillOpenUrl', url, null); - } - }, - setDeviceToken: function (deviceToken) { - if (WebViewJavascriptBridge) { - WebViewJavascriptBridge.callHandler('adjust_setDeviceToken', deviceToken, null); - } - }, - setOfflineMode: function(isOffline) { - if (WebViewJavascriptBridge) { - WebViewJavascriptBridge.callHandler('adjust_setOfflineMode', isOffline, null); - } - }, - getIdfa: function (callback) { - if (WebViewJavascriptBridge) { - WebViewJavascriptBridge.callHandler('adjust_idfa', null, callback); - } - }, - getAdid: function (callback) { - if (WebViewJavascriptBridge) { - WebViewJavascriptBridge.callHandler('adjust_adid', null, callback); - } - }, - getAttribution: function (callback) { - if (WebViewJavascriptBridge) { - WebViewJavascriptBridge.callHandler('adjust_attribution', null, callback); - } - }, - sendFirstPackages: function () { - if (WebViewJavascriptBridge) { - WebViewJavascriptBridge.callHandler('adjust_sendFirstPackages', null, null); - } - }, - addSessionCallbackParameter: function (key, value) { - if (WebViewJavascriptBridge != null) { - WebViewJavascriptBridge.callHandler('adjust_addSessionCallbackParameter', {key: key, value: value}, null); - } - }, - addSessionPartnerParameter: function (key, value) { - if (WebViewJavascriptBridge != null) { - WebViewJavascriptBridge.callHandler('adjust_addSessionPartnerParameter', {key: key, value: value}, null); - } - }, - removeSessionCallbackParameter: function (key) { - if (WebViewJavascriptBridge != null) { - WebViewJavascriptBridge.callHandler('adjust_removeSessionCallbackParameter', key, null); - } - }, - removeSessionPartnerParameter: function (key) { - if (WebViewJavascriptBridge != null) { - WebViewJavascriptBridge.callHandler('adjust_removeSessionPartnerParameter', key, null); - } - }, - resetSessionCallbackParameters: function () { - if (WebViewJavascriptBridge != null) { - WebViewJavascriptBridge.callHandler('adjust_resetSessionCallbackParameters', null, null); - } - }, - resetSessionPartnerParameters: function () { - if (WebViewJavascriptBridge != null) { - WebViewJavascriptBridge.callHandler('adjust_resetSessionPartnerParameters', null, null); - } - }, - gdprForgetMe: function () { - if (WebViewJavascriptBridge != null) { - WebViewJavascriptBridge.callHandler('adjust_gdprForgetMe', null, null); - } - } - }; - - // copied from adjust_event.js - window.AdjustEvent = function (eventToken) { - this.eventToken = eventToken; - - this.revenue = null; - this.currency = null; - this.transactionId = null; - - this.callbackParameters = []; - this.partnerParameters = []; - }; - - AdjustEvent.prototype.addCallbackParameter = function(key, value) { - this.callbackParameters.push(key); - this.callbackParameters.push(value); - }; - - AdjustEvent.prototype.addPartnerParameter = function(key, value) { - this.partnerParameters.push(key); - this.partnerParameters.push(value); - }; - - AdjustEvent.prototype.setRevenue = function(revenue, currency) { - this.revenue = revenue; - this.currency = currency; - }; - - AdjustEvent.prototype.setTransactionId = function(transactionId) { - this.transactionId = transactionId; - }; - - // copied from adjust_config.js - window.AdjustConfig = function (appToken, environment, legacy) { - - if (arguments.length === 2) { - // New format does not require bridge as first parameter. - this.appToken = appToken; - this.environment = environment; - } else if (arguments.length === 3) { - // New format with allowSuppressLogLevel. - if (typeof(legacy) == typeof(true)) { - this.appToken = appToken; - this.environment = environment; - this.allowSuppressLogLevel = legacy; - } else { - // Old format with first argument being the bridge instance. - this.bridge = appToken; - this.appToken = environment; - this.environment = legacy; - } - } - - this.sdkPrefix = 'web-bridge4.14.0'; - this.defaultTracker = null; - this.logLevel = null; - this.eventBufferingEnabled = null; - this.sendInBackground = null; - this.delayStart = null; - this.userAgent = null; - this.isDeviceKnown = null; - this.secretId = null; - this.info1 = null; - this.info2 = null; - this.info3 = null; - this.info4 = null; - this.openDeferredDeeplink = null; - this.callbacksMap = {}; - }; - AdjustConfig.EnvironmentSandbox = 'sandbox'; - AdjustConfig.EnvironmentProduction = 'production'; - - AdjustConfig.LogLevelVerbose = 'VERBOSE'; - AdjustConfig.LogLevelDebug = 'DEBUG'; - AdjustConfig.LogLevelInfo = 'INFO'; - AdjustConfig.LogLevelWarn = 'WARN'; - AdjustConfig.LogLevelError = 'ERROR'; - AdjustConfig.LogLevelAssert = 'ASSERT'; - AdjustConfig.LogLevelSuppress = 'SUPPRESS'; - - AdjustConfig.prototype.iterateConfiguredCallbacks = function(handleCallbackWithName) { - if (!this.callbacksMap) { - return; - } - var keysArray = Object.keys(this.callbacksMap); - for (var idx in keysArray) { - var key = keysArray[idx]; - handleCallbackWithName(key, this.callbacksMap[key]); - } - }; - - AdjustConfig.prototype.setSdkPrefix = function(sdkPrefix) { - this.sdkPrefix = sdkPrefix; - }; - AdjustConfig.prototype.setDefaultTracker = function(defaultTracker) { - this.defaultTracker = defaultTracker; - }; - AdjustConfig.prototype.setLogLevel = function(logLevel) { - this.logLevel = logLevel; - }; - AdjustConfig.prototype.setEventBufferingEnabled = function(isEnabled) { - this.eventBufferingEnabled = isEnabled; - }; - AdjustConfig.prototype.setSendInBackground = function(isEnabled) { - this.sendInBackground = isEnabled; - }; - AdjustConfig.prototype.setDelayStart = function(delayStartInSeconds) { - this.delayStart = delayStartInSeconds; - }; - AdjustConfig.prototype.setUserAgent = function(userAgent) { - this.userAgent = userAgent; - }; - AdjustConfig.prototype.setIsDeviceKnown = function(isDeviceKnown) { - this.isDeviceKnown = isDeviceKnown; - }; - AdjustConfig.prototype.setAppSecret = function(secretId, info1, info2, info3, info4) { - this.secretId = secretId; - this.info1 = info1; - this.info2 = info2; - this.info3 = info3; - this.info4 = info4; - }; - - AdjustConfig.prototype.setOpenDeferredDeeplink = function(shouldOpen) { - this.openDeferredDeeplink = shouldOpen; - }; - - AdjustConfig.prototype.setAttributionCallback = function(callback) { - this.callbacksMap['attributionCallback'] = callback; - }; - - AdjustConfig.prototype.setEventSuccessCallback = function(callback) { - this.callbacksMap['eventSuccessCallback'] = callback; - }; - - AdjustConfig.prototype.setEventFailureCallback = function(callback) { - this.callbacksMap['eventFailureCallback'] = callback; - }; - - AdjustConfig.prototype.setSessionSuccessCallback = function(callback) { - this.callbacksMap['sessionSuccessCallback'] = callback; - }; - - AdjustConfig.prototype.setSessionFailureCallback = function(callback) { - this.callbacksMap['sessionFailureCallback'] = callback; - }; - - AdjustConfig.prototype.setDeferredDeeplinkCallback = function(callback) { - this.callbacksMap['deferredDeeplinkCallback'] = callback; - }; - - })(); - ); // END preprocessorJSCode - -#undef __adj_wvjb_js_func__ - return preprocessorJSCode; -}; diff --git a/examples/AdjustExample-WebView/AdjustExample-WebView.xcodeproj/project.pbxproj b/examples/AdjustExample-WebView/AdjustExample-WebView.xcodeproj/project.pbxproj index af3dbcb87..faed1db2b 100644 --- a/examples/AdjustExample-WebView/AdjustExample-WebView.xcodeproj/project.pbxproj +++ b/examples/AdjustExample-WebView/AdjustExample-WebView.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 6FA69FEB2101EA2900FCD3B5 /* AdjustBridge_JS.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FA69FEA2101EA2900FCD3B5 /* AdjustBridge_JS.m */; }; 6FCC85121F2794D900D6A0ED /* ADJReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FCC85111F2794D600D6A0ED /* ADJReachability.m */; }; 968595F11D0B2E630011CA2B /* AdjustBridgeRegister.m in Sources */ = {isa = PBXBuildFile; fileRef = 968595F01D0B2E630011CA2B /* AdjustBridgeRegister.m */; }; 9D1082A91CFDAF8E0050568B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D1082A81CFDAF8E0050568B /* main.m */; }; @@ -63,8 +62,6 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 6FA69FE92101EA2900FCD3B5 /* AdjustBridge_JS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AdjustBridge_JS.h; sourceTree = ""; }; - 6FA69FEA2101EA2900FCD3B5 /* AdjustBridge_JS.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AdjustBridge_JS.m; sourceTree = ""; }; 6FCC85101F2794D600D6A0ED /* ADJReachability.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ADJReachability.h; sourceTree = ""; }; 6FCC85111F2794D600D6A0ED /* ADJReachability.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ADJReachability.m; sourceTree = ""; }; 968595EF1D0B2E630011CA2B /* AdjustBridgeRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdjustBridgeRegister.h; sourceTree = ""; }; @@ -323,8 +320,6 @@ 9D75F18F1D07463800E5D222 /* WebViewJavascriptBridge */ = { isa = PBXGroup; children = ( - 6FA69FE92101EA2900FCD3B5 /* AdjustBridge_JS.h */, - 6FA69FEA2101EA2900FCD3B5 /* AdjustBridge_JS.m */, 9D75F1871D07463800E5D222 /* WebViewJavascriptBridge.h */, 9D75F1881D07463800E5D222 /* WebViewJavascriptBridge.m */, 9D75F1891D07463800E5D222 /* WebViewJavascriptBridge_JS.h */, @@ -445,7 +440,6 @@ 9D75F19A1D07463800E5D222 /* AdjustBridge.m in Sources */, 9D449EF21E6EDD4100E7E80B /* ADJSessionFailure.m in Sources */, 9D449EDD1E6EDD4100E7E80B /* ADJActivityState.m in Sources */, - 6FA69FEB2101EA2900FCD3B5 /* AdjustBridge_JS.m in Sources */, 9D449EEB1E6EDD4100E7E80B /* ADJKeychain.m in Sources */, 9D449EE11E6EDD4100E7E80B /* ADJAdjustFactory.m in Sources */, 9D75F1971D07463800E5D222 /* WebViewJavascriptBridge_JS.m in Sources */, From bc1d9b623c77447451c04408aae60240929bf95d Mon Sep 17 00:00:00 2001 From: nonelse Date: Fri, 3 Aug 2018 14:29:44 +0200 Subject: [PATCH 07/27] Update logging --- AdjustBridge/AdjustBridge.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AdjustBridge/AdjustBridge.m b/AdjustBridge/AdjustBridge.m index b81c05fbc..15a835dcd 100644 --- a/AdjustBridge/AdjustBridge.m +++ b/AdjustBridge/AdjustBridge.m @@ -464,7 +464,7 @@ - (void)registerAugmentedView { eventToken = self.fbPixelDefaultEventToken; } if (eventToken == nil) { - [[ADJAdjustFactory logger] debug:@"There is a also not a default event token configured, it won't be tracked"]; + [[ADJAdjustFactory logger] debug:@"There is not a default event token configured or a mapping found for event named: '%@'. It won't be tracked as an adjust event", evtName]; return; } From c6bd7eb36bdae7597745f39fe8530e37c2bdbe16 Mon Sep 17 00:00:00 2001 From: hellomarne Date: Fri, 10 Aug 2018 17:25:23 +0200 Subject: [PATCH 08/27] Update fb_pixel.md --- doc/english/fb_pixel.md | 54 +++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/doc/english/fb_pixel.md b/doc/english/fb_pixel.md index 1484e19e3..4e0a96be5 100644 --- a/doc/english/fb_pixel.md +++ b/doc/english/fb_pixel.md @@ -1,25 +1,22 @@ ## Facebook pixel integration -[The Facebook Pixel](https://www.facebook.com/business/help/952192354843755) is a web only analytics tool from Facebook. -Usually, it would not be possible to use in a web view app, but since [FB SDK](https://developers.facebook.com/docs/analytics) -was updated to v4.34, it's now possible to use the [Hybrid Mobile App Events](https://developers.facebook.com/docs/app-events/hybrid-app-events) +[The Facebook Pixel](https://www.facebook.com/business/help/952192354843755) is a web-only analytics tool from Facebook. In the past it was impossible to use the Facebook SDK to track Pixel events in an app's webview. Since the release of [FB SDK](https://developers.facebook.com/docs/analytics) v4.34, it's now possible to do so, and use the [Hybrid Mobile App Events](https://developers.facebook.com/docs/app-events/hybrid-app-events) to convert Facebook Pixel events into Facebook App events. -The adjust SDK now also allows you to use the Facebook pixel in your web view app, without the need of integrating the FB SDK. +It is also now possible to use the Facebook Pixel with the Adjust SDK, without integrating the FB SDK. ### Facebook integration #### Facebook App ID -Even though, there is no need to integrate the FB SDK, it's still required to follow some of the integration steps from FB SDK -to allow the adjust SDK to integrate the Facebook Pixel. +There is no need to integrate the FB SDK; however, you must follow a few of the same integration steps from the FB SDK in order for the Adjust SDK to integrate the Facebook Pixel. As is described in the [FB SDK iOS SDK guide](https://developers.facebook.com/docs/ios/getting-started/#xcode) -you need to add your Facebook App ID to the app. You can follow the steps on that guide, but we copied it here: +you will need to add your Facebook App ID to the app. You can follow the steps in that guide, but we've also copied them here below: -1. In Xcode, right-click your project's `Info.plist` file and select Open As -> Source Code. +1. In Xcode, right click on your project's `Info.plist` file and select Open As -> Source Code. -2. Insert the following XML snippet into the body of your file just before the final `` element. +2. Insert the following XML snippet into the body of your file just before the final `` element: ```xml @@ -30,11 +27,11 @@ you need to add your Facebook App ID to the app. You can follow the steps on tha ``` -3. Replace `{your-app-id}`, with your app's App's ID found on the *Facebook App Dashboard*. +3. Replace `{your-app-id}` with your app's App ID (found on the *Facebook App Dashboard*). #### Facebook Pixel configuration -Follow Facebook's guide how to integrate the Facebook Pixel. The Javascript code should look something like this: +Follow Facebook's guide on how to integrate the Facebook Pixel. The Javascript code should look something like this: ```js @@ -48,8 +45,8 @@ Follow Facebook's guide how to integrate the Facebook Pixel. The Javascript code ``` -Now, just like described in [Hybrid Mobile App Events guide](https://developers.facebook.com/docs/app-events/hybrid-app-events) -`Update Your Pixel` section, you need to update the Facebook Pixel code like so: +Now, just as described in the [Hybrid Mobile App Events guide](https://developers.facebook.com/docs/app-events/hybrid-app-events) +`Update Your Pixel` section, you'll need to update the Facebook Pixel code like this: ```js fbq('init', ); @@ -60,8 +57,8 @@ fbq('set', 'mobileBridge', , ); #### Augment the webview -First, you still need to follow the integration guide for [iOs web view](web_views.md) apps. -Then in the section where you load the webview bridge, like so: +Follow the integration guide for [iOs web view](web_views.md) apps. +In the section where you load the webview bridge (see below): ```objc - (void)viewWillAppear:(BOOL)animated { @@ -83,7 +80,7 @@ Then in the section where you load the webview bridge, like so: ... ``` -however you choose to load the webview into the adjust bridge, afterwards add the following line: +No matter how you choose to load the webview into the Adjust bridge, follow that step by adding the following line: ```objc [self.adjustBridge augmentHybridWebView]; @@ -91,25 +88,24 @@ however you choose to load the webview into the adjust bridge, afterwards add th #### Event name configuration -The adjust web bridge SDK needs to translate the Facebook Pixel events into adjust events. +The Adjust web bridge SDK translates Facebook Pixel events into Adjust events. -For this reason it's necessary to configure either a mapping between a Facebook Pixel to a specific adjust event, or to -configure a default adjust event token ***before*** tracking any Facebook Pixel event, +For this reason, it's necessary to map Facebook Pixels to specific Adjust events, or to +configure a default Adjust event token ***before*** tracking any Facebook Pixel event, including the copy-pasted `fbq('track', 'PageView');` from the Facebook Pixel configuration. -To add mappings between Facebook Pixel events and adjust events, you need to call `addFbPixelMapping(fbEventNameKey, adjEventTokenValue)` -in the `adjustConfig` instance before initialise the adjust SDK. An example of mapping could be: +To map Facebook Pixel events and Adjust events, call `addFbPixelMapping(fbEventNameKey, adjEventTokenValue)` +in the `adjustConfig` instance before initializing the Adjust SDK. Here's an example of what that could look like: ```js adjustConfig.addFbPixelMapping('fb_mobile_search', adjustEventTokenForSearch); adjustConfig.addFbPixelMapping('fb_mobile_purchase', adjustEventTokenForPurchase); ``` -Take notice that this would match when tracking the Facebook pixel events `fbq('track', 'Search', ...);` and -`fbq('track', 'Purchase', ...);` respectively. Unfortunatly we do not have access to the mapping between the event name -tracked in javascript and the event name used by the FB SDK. +Note that this would match when tracking the following Facebook Pixel events: `fbq('track', 'Search', ...);` and +`fbq('track', 'Purchase', ...);` respectively. Unfortunately, we do not have access to the entire mapping scheme between the event names tracked in Javascript and the event names used by the FB SDK. -To help you, we've colled the following event name mappings that we found so far: +To help you, here is the event name information we've found so far: | Pixel event name | Corresponding Facebook app event name | ---------------- | ------------------------------------- @@ -122,13 +118,13 @@ To help you, we've colled the following event name mappings that we found so far | Purchase | fb_mobile_purchase | CompleteRegistration | fb_mobile_complete_registration -This might not be an exaustive list, and it's possible that Facebook adds or updates the current listing. -To make sure, during tests, check the adjust logs for warning like: +This may not be an exhaustive list; it's also possible that Facebook adds to or updates the current listing. +While testing, check the Adjust logs for warnings such as: ``` There is not a default event token configured or a mapping found for event named: 'fb_mobile_search'. It won't be tracked as an adjust event ``` -There is also the option to have a default adjust event to be used if a mapping is not configured. -Just call `adjustConfig.setFbPixelDefaultEventToken(defaultEventToken);` before initialise the adjust SDK. +There is also the option to use a default Adjust event if you do not have mapping configured. +Just call `adjustConfig.setFbPixelDefaultEventToken(defaultEventToken);` before initializing the Adjust SDK. From 5976c211f575a314aa61a31d1a4a539d4021bc7e Mon Sep 17 00:00:00 2001 From: uerceg Date: Fri, 17 Aug 2018 10:59:07 +0200 Subject: [PATCH 09/27] Fire attribution request if none available after session tracking --- Adjust/ADJActivityHandler.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Adjust/ADJActivityHandler.m b/Adjust/ADJActivityHandler.m index c54f58dcc..74928403b 100644 --- a/Adjust/ADJActivityHandler.m +++ b/Adjust/ADJActivityHandler.m @@ -1014,6 +1014,11 @@ - (void)launchSessionResponseTasksI:(ADJActivityHandler *)selfI withObject:sessionResponseData.attribution]; } + // if attribution didn't update and it's still null -> ask for attribution + if (selfI.attribution == nil && selfI.activityState.askingAttribution == NO) { + [selfI.attributionHandler getAttribution]; + } + selfI.internalState.sessionResponseProcessed = YES; } From 1b3e8ef6c5f275ea5b4a3e85a448b4ffdc737b0b Mon Sep 17 00:00:00 2001 From: uerceg Date: Thu, 23 Aug 2018 12:50:58 +0200 Subject: [PATCH 10/27] Adding example app for Facebook Pixel integration --- Adjust.xcodeproj/project.pbxproj | 28 + .../project.pbxproj | 652 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../AdjustExample-FbPixel.html | 166 +++++ .../AdjustExample-FbPixel/AppDelegate.h | 17 + .../AdjustExample-FbPixel/AppDelegate.m | 81 +++ .../AppIcon.appiconset/Contents.json | 98 +++ .../Assets.xcassets/Contents.json | 6 + .../Base.lproj/LaunchScreen.storyboard | 25 + .../Base.lproj/Main.storyboard | 24 + .../AdjustExample-FbPixel/Info.plist | 47 ++ .../UIWebViewController.h | 20 + .../UIWebViewController.m | 53 ++ .../WKWebViewController.h | 18 + .../WKWebViewController.m | 48 ++ .../AdjustExample-FbPixel/main.m | 16 + 17 files changed, 1314 insertions(+) create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.pbxproj create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AdjustExample-FbPixel.html create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AppDelegate.h create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AppDelegate.m create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Assets.xcassets/Contents.json create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Base.lproj/LaunchScreen.storyboard create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Base.lproj/Main.storyboard create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Info.plist create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/UIWebViewController.h create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/UIWebViewController.m create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/WKWebViewController.h create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/WKWebViewController.m create mode 100644 examples/AdjustExample-FbPixel/AdjustExample-FbPixel/main.m diff --git a/Adjust.xcodeproj/project.pbxproj b/Adjust.xcodeproj/project.pbxproj index 51eee01d2..69b5a3032 100644 --- a/Adjust.xcodeproj/project.pbxproj +++ b/Adjust.xcodeproj/project.pbxproj @@ -516,6 +516,13 @@ remoteGlobalIDString = 9D7431E51EB9F9B700969F14; remoteInfo = AdjustExampleTests; }; + 9D9D1551212EB3D00081445E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9D9D154D212EB3D00081445E /* AdjustExample-FbPixel.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 9D9D152E212EB3920081445E; + remoteInfo = "AdjustExample-FbPixel"; + }; 9DE7C8FF1AE68EF1001556E5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 9679920518BBAE2800394606 /* Project object */; @@ -786,6 +793,7 @@ 9D7431F41EB9F9B700969F14 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 9D7431F71EB9F9B700969F14 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 9D7431F91EB9F9B700969F14 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9D9D154D212EB3D00081445E /* AdjustExample-FbPixel.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "AdjustExample-FbPixel.xcodeproj"; path = "examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj"; sourceTree = ""; }; 9DD0E9AC1F44690B00B2A759 /* ADJUserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJUserDefaults.h; sourceTree = ""; }; 9DD0E9AD1F44690B00B2A759 /* ADJUserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJUserDefaults.m; sourceTree = ""; }; 9DE354D22100726300D211C9 /* AdjustSdkIm.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AdjustSdkIm.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1434,6 +1442,7 @@ 9D449DC51E6ED24000E7E80B /* AdjustExample-tvOS.xcodeproj */, 9D449DB31E6ED23400E7E80B /* AdjustExample-iWatch.xcodeproj */, 9D0167FE20FF88DE0029CFFF /* AdjustExample-iMessage.xcodeproj */, + 9D9D154D212EB3D00081445E /* AdjustExample-FbPixel.xcodeproj */, ); name = "Example Apps"; sourceTree = ""; @@ -1504,6 +1513,14 @@ name = "Supporting Files"; sourceTree = ""; }; + 9D9D154E212EB3D00081445E /* Products */ = { + isa = PBXGroup; + children = ( + 9D9D1552212EB3D00081445E /* AdjustExample-FbPixel.app */, + ); + name = Products; + sourceTree = ""; + }; 9DE354D32100726300D211C9 /* AdjustSdkIm */ = { isa = PBXGroup; children = ( @@ -2183,6 +2200,10 @@ productRefGroup = 9679920E18BBAE2800394606 /* Products */; projectDirPath = ""; projectReferences = ( + { + ProductGroup = 9D9D154E212EB3D00081445E /* Products */; + ProjectRef = 9D9D154D212EB3D00081445E /* AdjustExample-FbPixel.xcodeproj */; + }, { ProductGroup = 9D0167FF20FF88DE0029CFFF /* Products */; ProjectRef = 9D0167FE20FF88DE0029CFFF /* AdjustExample-iMessage.xcodeproj */; @@ -2309,6 +2330,13 @@ remoteRef = 9D449DCF1E6ED24400E7E80B /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 9D9D1552212EB3D00081445E /* AdjustExample-FbPixel.app */ = { + isa = PBXReferenceProxy; + fileType = wrapper.application; + path = "AdjustExample-FbPixel.app"; + remoteRef = 9D9D1551212EB3D00081445E /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.pbxproj b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.pbxproj new file mode 100644 index 000000000..e76ed1aed --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.pbxproj @@ -0,0 +1,652 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 9D9D1533212EB3920081445E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1532212EB3920081445E /* AppDelegate.m */; }; + 9D9D1539212EB3920081445E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9D9D1537212EB3920081445E /* Main.storyboard */; }; + 9D9D153B212EB3940081445E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9D9D153A212EB3940081445E /* Assets.xcassets */; }; + 9D9D153E212EB3940081445E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9D9D153C212EB3940081445E /* LaunchScreen.storyboard */; }; + 9D9D1541212EB3940081445E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1540212EB3940081445E /* main.m */; }; + 9D9D1561212EB4080081445E /* iAd.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D9D1560212EB4080081445E /* iAd.framework */; }; + 9D9D1563212EB40D0081445E /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D9D1562212EB40D0081445E /* AdSupport.framework */; }; + 9D9D1565212EB4130081445E /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D9D1564212EB4130081445E /* WebKit.framework */; }; + 9D9D15BA212EB4570081445E /* ADJDeviceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1569212EB4560081445E /* ADJDeviceInfo.m */; }; + 9D9D15BB212EB4570081445E /* ADJTimerOnce.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D156A212EB4560081445E /* ADJTimerOnce.m */; }; + 9D9D15BC212EB4570081445E /* ADJAttributionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D156B212EB4560081445E /* ADJAttributionHandler.m */; }; + 9D9D15BD212EB4570081445E /* ADJRequestHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D156E212EB4560081445E /* ADJRequestHandler.m */; }; + 9D9D15BE212EB4570081445E /* ADJKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1571212EB4560081445E /* ADJKeychain.m */; }; + 9D9D15BF212EB4570081445E /* ADJSdkClickHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1572212EB4560081445E /* ADJSdkClickHandler.m */; }; + 9D9D15C0212EB4570081445E /* ADJEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1574212EB4560081445E /* ADJEvent.m */; }; + 9D9D15C1212EB4570081445E /* ADJSessionSuccess.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1578212EB4560081445E /* ADJSessionSuccess.m */; }; + 9D9D15C2212EB4570081445E /* ADJEventFailure.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1579212EB4560081445E /* ADJEventFailure.m */; }; + 9D9D15C3212EB4570081445E /* ADJEventSuccess.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D157B212EB4560081445E /* ADJEventSuccess.m */; }; + 9D9D15C4212EB4570081445E /* ADJActivityState.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D157C212EB4560081445E /* ADJActivityState.m */; }; + 9D9D15C5212EB4570081445E /* ADJSessionFailure.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D157D212EB4560081445E /* ADJSessionFailure.m */; }; + 9D9D15C6212EB4570081445E /* ADJTimerCycle.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1581212EB4560081445E /* ADJTimerCycle.m */; }; + 9D9D15C7212EB4570081445E /* ADJSessionParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1582212EB4560081445E /* ADJSessionParameters.m */; }; + 9D9D15C8212EB4570081445E /* ADJLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1583212EB4560081445E /* ADJLogger.m */; }; + 9D9D15C9212EB4570081445E /* ADJBackoffStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1584212EB4560081445E /* ADJBackoffStrategy.m */; }; + 9D9D15CA212EB4570081445E /* Adjust.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1586212EB4560081445E /* Adjust.m */; }; + 9D9D15CB212EB4570081445E /* ADJConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D158A212EB4560081445E /* ADJConfig.m */; }; + 9D9D15CC212EB4570081445E /* ADJPackageHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D158B212EB4560081445E /* ADJPackageHandler.m */; }; + 9D9D15CD212EB4570081445E /* ADJActivityKind.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D158E212EB4560081445E /* ADJActivityKind.m */; }; + 9D9D15CE212EB4570081445E /* NSString+ADJAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1591212EB4560081445E /* NSString+ADJAdditions.m */; }; + 9D9D15CF212EB4570081445E /* NSData+ADJAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1593212EB4560081445E /* NSData+ADJAdditions.m */; }; + 9D9D15D0212EB4570081445E /* UIDevice+ADJAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1595212EB4560081445E /* UIDevice+ADJAdditions.m */; }; + 9D9D15D1212EB4570081445E /* ADJAttribution.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1597212EB4560081445E /* ADJAttribution.m */; }; + 9D9D15D2212EB4570081445E /* ADJSystemProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1598212EB4560081445E /* ADJSystemProfile.m */; }; + 9D9D15D3212EB4570081445E /* ADJActivityPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D159A212EB4560081445E /* ADJActivityPackage.m */; }; + 9D9D15D4212EB4570081445E /* ADJUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D159B212EB4560081445E /* ADJUtil.m */; }; + 9D9D15D5212EB4570081445E /* ADJAdjustFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D159E212EB4560081445E /* ADJAdjustFactory.m */; }; + 9D9D15D6212EB4570081445E /* ADJResponseData.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15A1212EB4560081445E /* ADJResponseData.m */; }; + 9D9D15D7212EB4570081445E /* ADJPackageBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15A3212EB4560081445E /* ADJPackageBuilder.m */; }; + 9D9D15D8212EB4570081445E /* ADJUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15A4212EB4560081445E /* ADJUserDefaults.m */; }; + 9D9D15D9212EB4570081445E /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9D9D15A8212EB4560081445E /* Info.plist */; }; + 9D9D15DA212EB4570081445E /* ADJActivityHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15AA212EB4560081445E /* ADJActivityHandler.m */; }; + 9D9D15DB212EB4570081445E /* ADJReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15AB212EB4560081445E /* ADJReachability.m */; }; + 9D9D15DC212EB4570081445E /* AdjustBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15AD212EB4570081445E /* AdjustBridge.m */; }; + 9D9D15DD212EB4570081445E /* WebViewJavascriptBridgeBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15B0212EB4570081445E /* WebViewJavascriptBridgeBase.m */; }; + 9D9D15DE212EB4570081445E /* WKWebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15B1212EB4570081445E /* WKWebViewJavascriptBridge.m */; }; + 9D9D15DF212EB4570081445E /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15B2212EB4570081445E /* WebViewJavascriptBridge.m */; }; + 9D9D15E0212EB4570081445E /* WebViewJavascriptBridge_JS.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15B5212EB4570081445E /* WebViewJavascriptBridge_JS.m */; }; + 9D9D15E1212EB4570081445E /* AdjustBridgeRegister.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15B9212EB4570081445E /* AdjustBridgeRegister.m */; }; + 9D9D15E3212EB47C0081445E /* AdjustExample-FbPixel.html in Resources */ = {isa = PBXBuildFile; fileRef = 9D9D15E2212EB47C0081445E /* AdjustExample-FbPixel.html */; }; + 9D9D15E8212EB5230081445E /* UIWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15E4212EB5230081445E /* UIWebViewController.m */; }; + 9D9D15E9212EB5230081445E /* WKWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15E6212EB5230081445E /* WKWebViewController.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 9D9D152E212EB3920081445E /* AdjustExample-FbPixel.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "AdjustExample-FbPixel.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 9D9D1531212EB3920081445E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 9D9D1532212EB3920081445E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 9D9D1538212EB3920081445E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 9D9D153A212EB3940081445E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 9D9D153D212EB3940081445E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 9D9D153F212EB3940081445E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9D9D1540212EB3940081445E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 9D9D1560212EB4080081445E /* iAd.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = iAd.framework; path = System/Library/Frameworks/iAd.framework; sourceTree = SDKROOT; }; + 9D9D1562212EB40D0081445E /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; + 9D9D1564212EB4130081445E /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + 9D9D1568212EB4560081445E /* ADJConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJConfig.h; sourceTree = ""; }; + 9D9D1569212EB4560081445E /* ADJDeviceInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJDeviceInfo.m; sourceTree = ""; }; + 9D9D156A212EB4560081445E /* ADJTimerOnce.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJTimerOnce.m; sourceTree = ""; }; + 9D9D156B212EB4560081445E /* ADJAttributionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJAttributionHandler.m; sourceTree = ""; }; + 9D9D156C212EB4560081445E /* Adjust.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Adjust.h; sourceTree = ""; }; + 9D9D156D212EB4560081445E /* ADJActivityPackage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJActivityPackage.h; sourceTree = ""; }; + 9D9D156E212EB4560081445E /* ADJRequestHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJRequestHandler.m; sourceTree = ""; }; + 9D9D156F212EB4560081445E /* ADJSystemProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSystemProfile.h; sourceTree = ""; }; + 9D9D1570212EB4560081445E /* ADJAttribution.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJAttribution.h; sourceTree = ""; }; + 9D9D1571212EB4560081445E /* ADJKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJKeychain.m; sourceTree = ""; }; + 9D9D1572212EB4560081445E /* ADJSdkClickHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSdkClickHandler.m; sourceTree = ""; }; + 9D9D1573212EB4560081445E /* ADJActivityKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJActivityKind.h; sourceTree = ""; }; + 9D9D1574212EB4560081445E /* ADJEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJEvent.m; sourceTree = ""; }; + 9D9D1575212EB4560081445E /* ADJPackageHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJPackageHandler.h; sourceTree = ""; }; + 9D9D1576212EB4560081445E /* ADJPackageBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJPackageBuilder.h; sourceTree = ""; }; + 9D9D1577212EB4560081445E /* ADJResponseData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJResponseData.h; sourceTree = ""; }; + 9D9D1578212EB4560081445E /* ADJSessionSuccess.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSessionSuccess.m; sourceTree = ""; }; + 9D9D1579212EB4560081445E /* ADJEventFailure.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJEventFailure.m; sourceTree = ""; }; + 9D9D157A212EB4560081445E /* ADJAdjustFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJAdjustFactory.h; sourceTree = ""; }; + 9D9D157B212EB4560081445E /* ADJEventSuccess.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJEventSuccess.m; sourceTree = ""; }; + 9D9D157C212EB4560081445E /* ADJActivityState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJActivityState.m; sourceTree = ""; }; + 9D9D157D212EB4560081445E /* ADJSessionFailure.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSessionFailure.m; sourceTree = ""; }; + 9D9D157E212EB4560081445E /* ADJUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJUtil.h; sourceTree = ""; }; + 9D9D157F212EB4560081445E /* ADJReachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJReachability.h; sourceTree = ""; }; + 9D9D1580212EB4560081445E /* ADJActivityHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJActivityHandler.h; sourceTree = ""; }; + 9D9D1581212EB4560081445E /* ADJTimerCycle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJTimerCycle.m; sourceTree = ""; }; + 9D9D1582212EB4560081445E /* ADJSessionParameters.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSessionParameters.m; sourceTree = ""; }; + 9D9D1583212EB4560081445E /* ADJLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJLogger.m; sourceTree = ""; }; + 9D9D1584212EB4560081445E /* ADJBackoffStrategy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJBackoffStrategy.m; sourceTree = ""; }; + 9D9D1585212EB4560081445E /* ADJUserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJUserDefaults.h; sourceTree = ""; }; + 9D9D1586212EB4560081445E /* Adjust.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Adjust.m; sourceTree = ""; }; + 9D9D1587212EB4560081445E /* ADJAttributionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJAttributionHandler.h; sourceTree = ""; }; + 9D9D1588212EB4560081445E /* ADJTimerOnce.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJTimerOnce.h; sourceTree = ""; }; + 9D9D1589212EB4560081445E /* ADJDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJDeviceInfo.h; sourceTree = ""; }; + 9D9D158A212EB4560081445E /* ADJConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJConfig.m; sourceTree = ""; }; + 9D9D158B212EB4560081445E /* ADJPackageHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJPackageHandler.m; sourceTree = ""; }; + 9D9D158C212EB4560081445E /* ADJEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJEvent.h; sourceTree = ""; }; + 9D9D158D212EB4560081445E /* ADJSdkClickHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSdkClickHandler.h; sourceTree = ""; }; + 9D9D158E212EB4560081445E /* ADJActivityKind.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJActivityKind.m; sourceTree = ""; }; + 9D9D158F212EB4560081445E /* ADJKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJKeychain.h; sourceTree = ""; }; + 9D9D1591212EB4560081445E /* NSString+ADJAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+ADJAdditions.m"; sourceTree = ""; }; + 9D9D1592212EB4560081445E /* UIDevice+ADJAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIDevice+ADJAdditions.h"; sourceTree = ""; }; + 9D9D1593212EB4560081445E /* NSData+ADJAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+ADJAdditions.m"; sourceTree = ""; }; + 9D9D1594212EB4560081445E /* NSData+ADJAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+ADJAdditions.h"; sourceTree = ""; }; + 9D9D1595212EB4560081445E /* UIDevice+ADJAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIDevice+ADJAdditions.m"; sourceTree = ""; }; + 9D9D1596212EB4560081445E /* NSString+ADJAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+ADJAdditions.h"; sourceTree = ""; }; + 9D9D1597212EB4560081445E /* ADJAttribution.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJAttribution.m; sourceTree = ""; }; + 9D9D1598212EB4560081445E /* ADJSystemProfile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSystemProfile.m; sourceTree = ""; }; + 9D9D1599212EB4560081445E /* ADJRequestHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJRequestHandler.h; sourceTree = ""; }; + 9D9D159A212EB4560081445E /* ADJActivityPackage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJActivityPackage.m; sourceTree = ""; }; + 9D9D159B212EB4560081445E /* ADJUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJUtil.m; sourceTree = ""; }; + 9D9D159C212EB4560081445E /* ADJSessionFailure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSessionFailure.h; sourceTree = ""; }; + 9D9D159D212EB4560081445E /* ADJActivityState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJActivityState.h; sourceTree = ""; }; + 9D9D159E212EB4560081445E /* ADJAdjustFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJAdjustFactory.m; sourceTree = ""; }; + 9D9D159F212EB4560081445E /* ADJEventSuccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJEventSuccess.h; sourceTree = ""; }; + 9D9D15A0212EB4560081445E /* ADJEventFailure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJEventFailure.h; sourceTree = ""; }; + 9D9D15A1212EB4560081445E /* ADJResponseData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJResponseData.m; sourceTree = ""; }; + 9D9D15A2212EB4560081445E /* ADJSessionSuccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSessionSuccess.h; sourceTree = ""; }; + 9D9D15A3212EB4560081445E /* ADJPackageBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJPackageBuilder.m; sourceTree = ""; }; + 9D9D15A4212EB4560081445E /* ADJUserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJUserDefaults.m; sourceTree = ""; }; + 9D9D15A5212EB4560081445E /* ADJBackoffStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJBackoffStrategy.h; sourceTree = ""; }; + 9D9D15A6212EB4560081445E /* ADJLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJLogger.h; sourceTree = ""; }; + 9D9D15A7212EB4560081445E /* ADJSessionParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSessionParameters.h; sourceTree = ""; }; + 9D9D15A8212EB4560081445E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9D9D15A9212EB4560081445E /* ADJTimerCycle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJTimerCycle.h; sourceTree = ""; }; + 9D9D15AA212EB4560081445E /* ADJActivityHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJActivityHandler.m; sourceTree = ""; }; + 9D9D15AB212EB4560081445E /* ADJReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJReachability.m; sourceTree = ""; }; + 9D9D15AD212EB4570081445E /* AdjustBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AdjustBridge.m; sourceTree = ""; }; + 9D9D15AE212EB4570081445E /* AdjustBridgeRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdjustBridgeRegister.h; sourceTree = ""; }; + 9D9D15B0212EB4570081445E /* WebViewJavascriptBridgeBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeBase.m; sourceTree = ""; }; + 9D9D15B1212EB4570081445E /* WKWebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WKWebViewJavascriptBridge.m; sourceTree = ""; }; + 9D9D15B2212EB4570081445E /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; + 9D9D15B3212EB4570081445E /* WebViewJavascriptBridge_JS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_JS.h; sourceTree = ""; }; + 9D9D15B4212EB4570081445E /* WebViewJavascriptBridgeBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeBase.h; sourceTree = ""; }; + 9D9D15B5212EB4570081445E /* WebViewJavascriptBridge_JS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_JS.m; sourceTree = ""; }; + 9D9D15B6212EB4570081445E /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; + 9D9D15B7212EB4570081445E /* WKWebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewJavascriptBridge.h; sourceTree = ""; }; + 9D9D15B8212EB4570081445E /* AdjustBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdjustBridge.h; sourceTree = ""; }; + 9D9D15B9212EB4570081445E /* AdjustBridgeRegister.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AdjustBridgeRegister.m; sourceTree = ""; }; + 9D9D15E2212EB47C0081445E /* AdjustExample-FbPixel.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "AdjustExample-FbPixel.html"; sourceTree = ""; }; + 9D9D15E4212EB5230081445E /* UIWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIWebViewController.m; sourceTree = ""; }; + 9D9D15E5212EB5230081445E /* UIWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIWebViewController.h; sourceTree = ""; }; + 9D9D15E6212EB5230081445E /* WKWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WKWebViewController.m; sourceTree = ""; }; + 9D9D15E7212EB5230081445E /* WKWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewController.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9D9D152B212EB3920081445E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9D9D1561212EB4080081445E /* iAd.framework in Frameworks */, + 9D9D1565212EB4130081445E /* WebKit.framework in Frameworks */, + 9D9D1563212EB40D0081445E /* AdSupport.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9D9D1525212EB3920081445E = { + isa = PBXGroup; + children = ( + 9D9D1530212EB3920081445E /* AdjustExample-FbPixel */, + 9D9D152F212EB3920081445E /* Products */, + 9D9D155F212EB4080081445E /* Frameworks */, + ); + sourceTree = ""; + }; + 9D9D152F212EB3920081445E /* Products */ = { + isa = PBXGroup; + children = ( + 9D9D152E212EB3920081445E /* AdjustExample-FbPixel.app */, + ); + name = Products; + sourceTree = ""; + }; + 9D9D1530212EB3920081445E /* AdjustExample-FbPixel */ = { + isa = PBXGroup; + children = ( + 9D9D1531212EB3920081445E /* AppDelegate.h */, + 9D9D1532212EB3920081445E /* AppDelegate.m */, + 9D9D15E5212EB5230081445E /* UIWebViewController.h */, + 9D9D15E4212EB5230081445E /* UIWebViewController.m */, + 9D9D15E7212EB5230081445E /* WKWebViewController.h */, + 9D9D15E6212EB5230081445E /* WKWebViewController.m */, + 9D9D1537212EB3920081445E /* Main.storyboard */, + 9D9D153A212EB3940081445E /* Assets.xcassets */, + 9D9D153C212EB3940081445E /* LaunchScreen.storyboard */, + 9D9D153F212EB3940081445E /* Info.plist */, + 9D9D1540212EB3940081445E /* main.m */, + 9D9D15E2212EB47C0081445E /* AdjustExample-FbPixel.html */, + 9D9D1566212EB43D0081445E /* Supporting Files */, + ); + path = "AdjustExample-FbPixel"; + sourceTree = ""; + }; + 9D9D155F212EB4080081445E /* Frameworks */ = { + isa = PBXGroup; + children = ( + 9D9D1564212EB4130081445E /* WebKit.framework */, + 9D9D1562212EB40D0081445E /* AdSupport.framework */, + 9D9D1560212EB4080081445E /* iAd.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9D9D1566212EB43D0081445E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 9D9D1567212EB4560081445E /* Adjust */, + 9D9D15AC212EB4570081445E /* AdjustBridge */, + ); + path = "Supporting Files"; + sourceTree = ""; + }; + 9D9D1567212EB4560081445E /* Adjust */ = { + isa = PBXGroup; + children = ( + 9D9D1568212EB4560081445E /* ADJConfig.h */, + 9D9D1569212EB4560081445E /* ADJDeviceInfo.m */, + 9D9D156A212EB4560081445E /* ADJTimerOnce.m */, + 9D9D156B212EB4560081445E /* ADJAttributionHandler.m */, + 9D9D156C212EB4560081445E /* Adjust.h */, + 9D9D156D212EB4560081445E /* ADJActivityPackage.h */, + 9D9D156E212EB4560081445E /* ADJRequestHandler.m */, + 9D9D156F212EB4560081445E /* ADJSystemProfile.h */, + 9D9D1570212EB4560081445E /* ADJAttribution.h */, + 9D9D1571212EB4560081445E /* ADJKeychain.m */, + 9D9D1572212EB4560081445E /* ADJSdkClickHandler.m */, + 9D9D1573212EB4560081445E /* ADJActivityKind.h */, + 9D9D1574212EB4560081445E /* ADJEvent.m */, + 9D9D1575212EB4560081445E /* ADJPackageHandler.h */, + 9D9D1576212EB4560081445E /* ADJPackageBuilder.h */, + 9D9D1577212EB4560081445E /* ADJResponseData.h */, + 9D9D1578212EB4560081445E /* ADJSessionSuccess.m */, + 9D9D1579212EB4560081445E /* ADJEventFailure.m */, + 9D9D157A212EB4560081445E /* ADJAdjustFactory.h */, + 9D9D157B212EB4560081445E /* ADJEventSuccess.m */, + 9D9D157C212EB4560081445E /* ADJActivityState.m */, + 9D9D157D212EB4560081445E /* ADJSessionFailure.m */, + 9D9D157E212EB4560081445E /* ADJUtil.h */, + 9D9D157F212EB4560081445E /* ADJReachability.h */, + 9D9D1580212EB4560081445E /* ADJActivityHandler.h */, + 9D9D1581212EB4560081445E /* ADJTimerCycle.m */, + 9D9D1582212EB4560081445E /* ADJSessionParameters.m */, + 9D9D1583212EB4560081445E /* ADJLogger.m */, + 9D9D1584212EB4560081445E /* ADJBackoffStrategy.m */, + 9D9D1585212EB4560081445E /* ADJUserDefaults.h */, + 9D9D1586212EB4560081445E /* Adjust.m */, + 9D9D1587212EB4560081445E /* ADJAttributionHandler.h */, + 9D9D1588212EB4560081445E /* ADJTimerOnce.h */, + 9D9D1589212EB4560081445E /* ADJDeviceInfo.h */, + 9D9D158A212EB4560081445E /* ADJConfig.m */, + 9D9D158B212EB4560081445E /* ADJPackageHandler.m */, + 9D9D158C212EB4560081445E /* ADJEvent.h */, + 9D9D158D212EB4560081445E /* ADJSdkClickHandler.h */, + 9D9D158E212EB4560081445E /* ADJActivityKind.m */, + 9D9D158F212EB4560081445E /* ADJKeychain.h */, + 9D9D1590212EB4560081445E /* ADJAdditions */, + 9D9D1597212EB4560081445E /* ADJAttribution.m */, + 9D9D1598212EB4560081445E /* ADJSystemProfile.m */, + 9D9D1599212EB4560081445E /* ADJRequestHandler.h */, + 9D9D159A212EB4560081445E /* ADJActivityPackage.m */, + 9D9D159B212EB4560081445E /* ADJUtil.m */, + 9D9D159C212EB4560081445E /* ADJSessionFailure.h */, + 9D9D159D212EB4560081445E /* ADJActivityState.h */, + 9D9D159E212EB4560081445E /* ADJAdjustFactory.m */, + 9D9D159F212EB4560081445E /* ADJEventSuccess.h */, + 9D9D15A0212EB4560081445E /* ADJEventFailure.h */, + 9D9D15A1212EB4560081445E /* ADJResponseData.m */, + 9D9D15A2212EB4560081445E /* ADJSessionSuccess.h */, + 9D9D15A3212EB4560081445E /* ADJPackageBuilder.m */, + 9D9D15A4212EB4560081445E /* ADJUserDefaults.m */, + 9D9D15A5212EB4560081445E /* ADJBackoffStrategy.h */, + 9D9D15A6212EB4560081445E /* ADJLogger.h */, + 9D9D15A7212EB4560081445E /* ADJSessionParameters.h */, + 9D9D15A8212EB4560081445E /* Info.plist */, + 9D9D15A9212EB4560081445E /* ADJTimerCycle.h */, + 9D9D15AA212EB4560081445E /* ADJActivityHandler.m */, + 9D9D15AB212EB4560081445E /* ADJReachability.m */, + ); + name = Adjust; + path = ../../../../Adjust; + sourceTree = ""; + }; + 9D9D1590212EB4560081445E /* ADJAdditions */ = { + isa = PBXGroup; + children = ( + 9D9D1591212EB4560081445E /* NSString+ADJAdditions.m */, + 9D9D1592212EB4560081445E /* UIDevice+ADJAdditions.h */, + 9D9D1593212EB4560081445E /* NSData+ADJAdditions.m */, + 9D9D1594212EB4560081445E /* NSData+ADJAdditions.h */, + 9D9D1595212EB4560081445E /* UIDevice+ADJAdditions.m */, + 9D9D1596212EB4560081445E /* NSString+ADJAdditions.h */, + ); + path = ADJAdditions; + sourceTree = ""; + }; + 9D9D15AC212EB4570081445E /* AdjustBridge */ = { + isa = PBXGroup; + children = ( + 9D9D15AD212EB4570081445E /* AdjustBridge.m */, + 9D9D15AE212EB4570081445E /* AdjustBridgeRegister.h */, + 9D9D15AF212EB4570081445E /* WebViewJavascriptBridge */, + 9D9D15B8212EB4570081445E /* AdjustBridge.h */, + 9D9D15B9212EB4570081445E /* AdjustBridgeRegister.m */, + ); + name = AdjustBridge; + path = ../../../../AdjustBridge; + sourceTree = ""; + }; + 9D9D15AF212EB4570081445E /* WebViewJavascriptBridge */ = { + isa = PBXGroup; + children = ( + 9D9D15B0212EB4570081445E /* WebViewJavascriptBridgeBase.m */, + 9D9D15B1212EB4570081445E /* WKWebViewJavascriptBridge.m */, + 9D9D15B2212EB4570081445E /* WebViewJavascriptBridge.m */, + 9D9D15B3212EB4570081445E /* WebViewJavascriptBridge_JS.h */, + 9D9D15B4212EB4570081445E /* WebViewJavascriptBridgeBase.h */, + 9D9D15B5212EB4570081445E /* WebViewJavascriptBridge_JS.m */, + 9D9D15B6212EB4570081445E /* WebViewJavascriptBridge.h */, + 9D9D15B7212EB4570081445E /* WKWebViewJavascriptBridge.h */, + ); + path = WebViewJavascriptBridge; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9D9D152D212EB3920081445E /* AdjustExample-FbPixel */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9D9D1544212EB3940081445E /* Build configuration list for PBXNativeTarget "AdjustExample-FbPixel" */; + buildPhases = ( + 9D9D152A212EB3920081445E /* Sources */, + 9D9D152B212EB3920081445E /* Frameworks */, + 9D9D152C212EB3920081445E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "AdjustExample-FbPixel"; + productName = "AdjustExample-FbPixel"; + productReference = 9D9D152E212EB3920081445E /* AdjustExample-FbPixel.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9D9D1526212EB3920081445E /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0940; + ORGANIZATIONNAME = "Adjust GmbH"; + TargetAttributes = { + 9D9D152D212EB3920081445E = { + CreatedOnToolsVersion = 9.4.1; + }; + }; + }; + buildConfigurationList = 9D9D1529212EB3920081445E /* Build configuration list for PBXProject "AdjustExample-FbPixel" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 9D9D1525212EB3920081445E; + productRefGroup = 9D9D152F212EB3920081445E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 9D9D152D212EB3920081445E /* AdjustExample-FbPixel */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 9D9D152C212EB3920081445E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9D9D15D9212EB4570081445E /* Info.plist in Resources */, + 9D9D15E3212EB47C0081445E /* AdjustExample-FbPixel.html in Resources */, + 9D9D153E212EB3940081445E /* LaunchScreen.storyboard in Resources */, + 9D9D153B212EB3940081445E /* Assets.xcassets in Resources */, + 9D9D1539212EB3920081445E /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9D9D152A212EB3920081445E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9D9D15BF212EB4570081445E /* ADJSdkClickHandler.m in Sources */, + 9D9D15D5212EB4570081445E /* ADJAdjustFactory.m in Sources */, + 9D9D15D0212EB4570081445E /* UIDevice+ADJAdditions.m in Sources */, + 9D9D15E0212EB4570081445E /* WebViewJavascriptBridge_JS.m in Sources */, + 9D9D15D6212EB4570081445E /* ADJResponseData.m in Sources */, + 9D9D15BB212EB4570081445E /* ADJTimerOnce.m in Sources */, + 9D9D15CE212EB4570081445E /* NSString+ADJAdditions.m in Sources */, + 9D9D15C1212EB4570081445E /* ADJSessionSuccess.m in Sources */, + 9D9D15D7212EB4570081445E /* ADJPackageBuilder.m in Sources */, + 9D9D15DF212EB4570081445E /* WebViewJavascriptBridge.m in Sources */, + 9D9D15C9212EB4570081445E /* ADJBackoffStrategy.m in Sources */, + 9D9D15BD212EB4570081445E /* ADJRequestHandler.m in Sources */, + 9D9D15C0212EB4570081445E /* ADJEvent.m in Sources */, + 9D9D15CF212EB4570081445E /* NSData+ADJAdditions.m in Sources */, + 9D9D15CC212EB4570081445E /* ADJPackageHandler.m in Sources */, + 9D9D15C3212EB4570081445E /* ADJEventSuccess.m in Sources */, + 9D9D15D3212EB4570081445E /* ADJActivityPackage.m in Sources */, + 9D9D15DB212EB4570081445E /* ADJReachability.m in Sources */, + 9D9D15DE212EB4570081445E /* WKWebViewJavascriptBridge.m in Sources */, + 9D9D15E8212EB5230081445E /* UIWebViewController.m in Sources */, + 9D9D15CD212EB4570081445E /* ADJActivityKind.m in Sources */, + 9D9D15BE212EB4570081445E /* ADJKeychain.m in Sources */, + 9D9D15E1212EB4570081445E /* AdjustBridgeRegister.m in Sources */, + 9D9D15D2212EB4570081445E /* ADJSystemProfile.m in Sources */, + 9D9D15C4212EB4570081445E /* ADJActivityState.m in Sources */, + 9D9D15C8212EB4570081445E /* ADJLogger.m in Sources */, + 9D9D15E9212EB5230081445E /* WKWebViewController.m in Sources */, + 9D9D15BA212EB4570081445E /* ADJDeviceInfo.m in Sources */, + 9D9D15C6212EB4570081445E /* ADJTimerCycle.m in Sources */, + 9D9D1541212EB3940081445E /* main.m in Sources */, + 9D9D15CA212EB4570081445E /* Adjust.m in Sources */, + 9D9D15D1212EB4570081445E /* ADJAttribution.m in Sources */, + 9D9D15C5212EB4570081445E /* ADJSessionFailure.m in Sources */, + 9D9D15CB212EB4570081445E /* ADJConfig.m in Sources */, + 9D9D15D8212EB4570081445E /* ADJUserDefaults.m in Sources */, + 9D9D15D4212EB4570081445E /* ADJUtil.m in Sources */, + 9D9D15C2212EB4570081445E /* ADJEventFailure.m in Sources */, + 9D9D15BC212EB4570081445E /* ADJAttributionHandler.m in Sources */, + 9D9D1533212EB3920081445E /* AppDelegate.m in Sources */, + 9D9D15DA212EB4570081445E /* ADJActivityHandler.m in Sources */, + 9D9D15C7212EB4570081445E /* ADJSessionParameters.m in Sources */, + 9D9D15DD212EB4570081445E /* WebViewJavascriptBridgeBase.m in Sources */, + 9D9D15DC212EB4570081445E /* AdjustBridge.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 9D9D1537212EB3920081445E /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 9D9D1538212EB3920081445E /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 9D9D153C212EB3940081445E /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 9D9D153D212EB3940081445E /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 9D9D1542212EB3940081445E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 9D9D1543212EB3940081445E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 9D9D1545212EB3940081445E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = QGUGW9AUMK; + INFOPLIST_FILE = "AdjustExample-FbPixel/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.adjust.examples; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 9D9D1546212EB3940081445E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = QGUGW9AUMK; + INFOPLIST_FILE = "AdjustExample-FbPixel/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.adjust.examples; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9D9D1529212EB3920081445E /* Build configuration list for PBXProject "AdjustExample-FbPixel" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9D9D1542212EB3940081445E /* Debug */, + 9D9D1543212EB3940081445E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9D9D1544212EB3940081445E /* Build configuration list for PBXNativeTarget "AdjustExample-FbPixel" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9D9D1545212EB3940081445E /* Debug */, + 9D9D1546212EB3940081445E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9D9D1526212EB3920081445E /* Project object */; +} diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..f9240ddfa --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AdjustExample-FbPixel.html b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AdjustExample-FbPixel.html new file mode 100644 index 000000000..a09af2934 --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AdjustExample-FbPixel.html @@ -0,0 +1,166 @@ + + + + + +

Adjust Web View Demo

+ + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AppDelegate.h b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AppDelegate.h new file mode 100644 index 000000000..0f41ab7fb --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AppDelegate.h @@ -0,0 +1,17 @@ +// +// AppDelegate.h +// AdjustExample-FbPixel +// +// Created by Uglješa Erceg on 23.08.18. +// Copyright © 2018 Adjust GmbH. All rights reserved. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AppDelegate.m b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AppDelegate.m new file mode 100644 index 000000000..527ae09c0 --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AppDelegate.m @@ -0,0 +1,81 @@ +// +// AppDelegate.m +// AdjustExample-FbPixel +// +// Created by Uglješa Erceg on 23.08.18. +// Copyright © 2018 Adjust GmbH. All rights reserved. +// + +#import "Adjust.h" +#import "AppDelegate.h" +#import "UIWebViewController.h" +#import "WKWebViewController.h" + +@interface AppDelegate () + +@property UIWebViewController *uiWebViewExampleController; +@property WKWebViewController *wkWebViewExampleController; + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // 1. Create the UIWebView example + self.uiWebViewExampleController = [[UIWebViewController alloc] init]; + self.uiWebViewExampleController.tabBarItem.title = @"UIWebView"; + + // 2. Create the tab footer and add the UIWebView example + UITabBarController *tabBarController = [[UITabBarController alloc] init]; + [tabBarController addChildViewController:self.uiWebViewExampleController]; + + // 3. Create the WKWebView example for devices >= iOS 8 + if ([WKWebView class]) { + self.wkWebViewExampleController = [[WKWebViewController alloc] init]; + self.wkWebViewExampleController.tabBarItem.title = @"WKWebView"; + [tabBarController addChildViewController:self.wkWebViewExampleController]; + } + + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.window.rootViewController = tabBarController; + [self.window makeKeyAndVisible]; + + return YES; +} + +- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { + [Adjust appWillOpenUrl:url]; + return YES; +} + +- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler { + if ([[userActivity activityType] isEqualToString:NSUserActivityTypeBrowsingWeb]) { + [Adjust appWillOpenUrl:[userActivity webpageURL]]; + } + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..d8db8d65f --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Assets.xcassets/Contents.json b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Assets.xcassets/Contents.json new file mode 100644 index 000000000..da4a164c9 --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Base.lproj/LaunchScreen.storyboard b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..f83f6fd58 --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Base.lproj/Main.storyboard b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Base.lproj/Main.storyboard new file mode 100644 index 000000000..d7c78a125 --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Base.lproj/Main.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Info.plist b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Info.plist new file mode 100644 index 000000000..cc97c7188 --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + FacebookAppID + 308873563017393 + + diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/UIWebViewController.h b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/UIWebViewController.h new file mode 100644 index 000000000..b0e1b37fa --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/UIWebViewController.h @@ -0,0 +1,20 @@ +// +// ViewController.h +// AdjustExample-WebView +// +// Created by Uglješa Erceg on 31/05/16. +// Copyright © 2016 adjust GmbH. All rights reserved. +// + +#import +#import + +#import "AdjustBridge.h" + +@interface UIWebViewController : UINavigationController + +@property AdjustBridge *adjustBridge; +@property JSContext *jsContext; + +@end + diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/UIWebViewController.m b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/UIWebViewController.m new file mode 100644 index 000000000..92863189d --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/UIWebViewController.m @@ -0,0 +1,53 @@ +// +// ViewController.m +// AdjustExample-WebView +// +// Created by Uglješa Erceg on 31/05/16. +// Copyright © 2016 adjust GmbH. All rights reserved. +// + +#import "UIWebViewController.h" + +@interface UIWebViewController () + +@end + +@implementation UIWebViewController + +- (void)viewDidLoad { + [super viewDidLoad]; +} + +- (void)viewWillAppear:(BOOL)animated { + [self loadUIWebView]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +- (void)loadUIWebView { + UIWebView *uiWebView = [[UIWebView alloc] initWithFrame:self.view.bounds]; + [self.view addSubview:uiWebView]; + + _adjustBridge = [[AdjustBridge alloc] init]; + [_adjustBridge loadUIWebViewBridge:uiWebView webViewDelegate:self]; + [_adjustBridge augmentHybridWebView]; + + _jsContext = [uiWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; + _jsContext[@"console"][@"log"] = ^(JSValue * msg) { + NSLog(@"JavaScript %@ log message: %@", [JSContext currentContext], msg); + }; + + NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"AdjustExample-FbPixel" ofType:@"html"]; + NSString *appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; + NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; + [uiWebView loadHTMLString:appHtml baseURL:baseURL]; +} + +- (void)callUiHandler:(id)sender { + +} + +@end + diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/WKWebViewController.h b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/WKWebViewController.h new file mode 100644 index 000000000..5ac43082b --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/WKWebViewController.h @@ -0,0 +1,18 @@ +// +// WKWebViewController.h +// AdjustExample-WebView +// +// Created by Uglješa Erceg on 31/05/16. +// Copyright © 2016 adjust GmbH. All rights reserved. +// + +#import +#import + +#import "AdjustBridge.h" + +@interface WKWebViewController : UINavigationController + +@property AdjustBridge *adjustBridge; + +@end diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/WKWebViewController.m b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/WKWebViewController.m new file mode 100644 index 000000000..37e1ffa41 --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/WKWebViewController.m @@ -0,0 +1,48 @@ +// +// WKWebViewController.m +// AdjustExample-WebView +// +// Created by Uglješa Erceg on 31/05/16. +// Copyright © 2016 adjust GmbH. All rights reserved. +// + +#import "WKWebViewController.h" + +@interface WKWebViewController () + +@end + +@implementation WKWebViewController + +- (void)viewDidLoad { + [super viewDidLoad]; +} + +- (void)viewWillAppear:(BOOL)animated { + [self loadWKWebView]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +- (void)loadWKWebView { + WKWebView *webView = [[NSClassFromString(@"WKWebView") alloc] initWithFrame:self.view.bounds]; + webView.navigationDelegate = self; + [self.view addSubview:webView]; + + _adjustBridge = [[AdjustBridge alloc] init]; + [_adjustBridge loadWKWebViewBridge:webView wkWebViewDelegate:self]; + [_adjustBridge augmentHybridWebView]; + + NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"AdjustExample-FbPixel" ofType:@"html"]; + NSString *appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; + NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; + [webView loadHTMLString:appHtml baseURL:baseURL]; +} + +- (void)callWkHandler:(id)sender { + +} + +@end diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/main.m b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/main.m new file mode 100644 index 000000000..84d221d25 --- /dev/null +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/main.m @@ -0,0 +1,16 @@ +// +// main.m +// AdjustExample-FbPixel +// +// Created by Uglješa Erceg on 23.08.18. +// Copyright © 2018 Adjust GmbH. All rights reserved. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} From e2bb675038e57bba5d58257eca0ade2e6d4d80de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uglje=C5=A1a=20Erceg?= Date: Thu, 23 Aug 2018 12:56:37 +0200 Subject: [PATCH 11/27] Update fb_pixel.md --- doc/english/fb_pixel.md | 72 +++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/doc/english/fb_pixel.md b/doc/english/fb_pixel.md index 4e0a96be5..53b81cb10 100644 --- a/doc/english/fb_pixel.md +++ b/doc/english/fb_pixel.md @@ -1,35 +1,36 @@ ## Facebook pixel integration -[The Facebook Pixel](https://www.facebook.com/business/help/952192354843755) is a web-only analytics tool from Facebook. In the past it was impossible to use the Facebook SDK to track Pixel events in an app's webview. Since the release of [FB SDK](https://developers.facebook.com/docs/analytics) v4.34, it's now possible to do so, and use the [Hybrid Mobile App Events](https://developers.facebook.com/docs/app-events/hybrid-app-events) -to convert Facebook Pixel events into Facebook App events. +[The Facebook Pixel](https://www.facebook.com/business/help/952192354843755) is a web-only analytics tool from Facebook. In the past it was impossible to use the Facebook SDK to track Pixel events in an app's webview. Since the release of [FB SDK](https://developers.facebook.com/docs/analytics) v4.34, it's now possible to do so, and use the [Hybrid Mobile App Events](https://developers.facebook.com/docs/app-events/hybrid-app-events) to convert Facebook Pixel events into Facebook App events. It is also now possible to use the Facebook Pixel with the Adjust SDK, without integrating the FB SDK. -### Facebook integration +## Facebook integration -#### Facebook App ID +### Example app -There is no need to integrate the FB SDK; however, you must follow a few of the same integration steps from the FB SDK in order for the Adjust SDK to integrate the Facebook Pixel. +There is an example app inside the [`AdjustExample-FbPixel` directory][example-fbpixel] that demonstrates how Facebook Pixel events can be tracked with usage of Adjust web view SDK. -As is described in the [FB SDK iOS SDK guide](https://developers.facebook.com/docs/ios/getting-started/#xcode) -you will need to add your Facebook App ID to the app. You can follow the steps in that guide, but we've also copied them here below: +### Facebook App ID -1. In Xcode, right click on your project's `Info.plist` file and select Open As -> Source Code. +There is no need to integrate the FB SDK; however, you must follow a few of the same integration steps from the FB SDK in order for the Adjust SDK to integrate the Facebook Pixel. -2. Insert the following XML snippet into the body of your file just before the final `` element: +As is described in the [FB SDK iOS SDK guide](https://developers.facebook.com/docs/ios/getting-started/#xcode) you will need to add your Facebook App ID to the app. You can follow the steps in that guide, but we've also copied them here below: -```xml - - ... - FacebookAppID - {your-app-id} - ... - -``` +- In Xcode, right click on your project's `Info.plist` file and select Open As -> Source Code. +- Insert the following XML snippet into the body of your file just before the final `` element: -3. Replace `{your-app-id}` with your app's App ID (found on the *Facebook App Dashboard*). + ```xml + + ... + FacebookAppID + {your-app-id} + ... + + ``` -#### Facebook Pixel configuration +- Replace `{your-app-id}` with your app's App ID (found on the *Facebook App Dashboard*). + +### Facebook Pixel configuration Follow Facebook's guide on how to integrate the Facebook Pixel. The Javascript code should look something like this: @@ -45,20 +46,20 @@ Follow Facebook's guide on how to integrate the Facebook Pixel. The Javascript c ``` -Now, just as described in the [Hybrid Mobile App Events guide](https://developers.facebook.com/docs/app-events/hybrid-app-events) -`Update Your Pixel` section, you'll need to update the Facebook Pixel code like this: +Now, just as described in the [Hybrid Mobile App Events guide](https://developers.facebook.com/docs/app-events/hybrid-app-events) `Update Your Pixel` section, you'll need to update the Facebook Pixel code like this: ```js fbq('init', ); fbq('set', 'mobileBridge', , ); ``` -### Adjust integration +**Note**: Please pay attention that it is **very important** that you first call `'init'` and immediately afterwards `'set'` method. Facebook's script snipet they offer you to paste to your HTML web page (like shown above) contains `'track'` method for page view event right after call to `'init'` method. In order for this page view event to be properly tracked, please make sure to call `'set'` method in between! + +## Adjust integration -#### Augment the webview +### Augment the web view -Follow the integration guide for [iOs web view](web_views.md) apps. -In the section where you load the webview bridge (see below): +Follow the integration guide for [iOS web view](web_views.md) apps. In the section where you load the webview bridge (see below): ```objc - (void)viewWillAppear:(BOOL)animated { @@ -80,30 +81,26 @@ In the section where you load the webview bridge (see below): ... ``` -No matter how you choose to load the webview into the Adjust bridge, follow that step by adding the following line: +No matter how you choose to load the web view into the Adjust bridge, follow that step by adding the following line: ```objc [self.adjustBridge augmentHybridWebView]; ``` -#### Event name configuration +### Event name configuration The Adjust web bridge SDK translates Facebook Pixel events into Adjust events. -For this reason, it's necessary to map Facebook Pixels to specific Adjust events, or to -configure a default Adjust event token ***before*** tracking any Facebook Pixel event, -including the copy-pasted `fbq('track', 'PageView');` from the Facebook Pixel configuration. +For this reason, it's necessary to map Facebook Pixels to specific Adjust events, or to configure a default Adjust event token ***before*** starting Adjust SDK and tracking any Facebook Pixel event, including the copy-pasted `fbq('track', 'PageView');` from the Facebook Pixel configuration. -To map Facebook Pixel events and Adjust events, call `addFbPixelMapping(fbEventNameKey, adjEventTokenValue)` -in the `adjustConfig` instance before initializing the Adjust SDK. Here's an example of what that could look like: +To map Facebook Pixel events and Adjust events, call `addFbPixelMapping(fbEventNameKey, adjEventTokenValue)` in the `adjustConfig` instance before initializing the Adjust SDK. Here's an example of what that could look like: ```js adjustConfig.addFbPixelMapping('fb_mobile_search', adjustEventTokenForSearch); adjustConfig.addFbPixelMapping('fb_mobile_purchase', adjustEventTokenForPurchase); ``` -Note that this would match when tracking the following Facebook Pixel events: `fbq('track', 'Search', ...);` and -`fbq('track', 'Purchase', ...);` respectively. Unfortunately, we do not have access to the entire mapping scheme between the event names tracked in Javascript and the event names used by the FB SDK. +Note that this would match when tracking the following Facebook Pixel events: `fbq('track', 'Search', ...);` and `fbq('track', 'Purchase', ...);` respectively. Unfortunately, we do not have access to the entire mapping scheme between the event names tracked in Javascript and the event names used by the FB SDK. To help you, here is the event name information we've found so far: @@ -118,13 +115,12 @@ To help you, here is the event name information we've found so far: | Purchase | fb_mobile_purchase | CompleteRegistration | fb_mobile_complete_registration -This may not be an exhaustive list; it's also possible that Facebook adds to or updates the current listing. -While testing, check the Adjust logs for warnings such as: +This may not be an exhaustive list; it's also possible that Facebook adds to or updates the current listing. While testing, check the Adjust logs for warnings such as: ``` There is not a default event token configured or a mapping found for event named: 'fb_mobile_search'. It won't be tracked as an adjust event ``` -There is also the option to use a default Adjust event if you do not have mapping configured. -Just call `adjustConfig.setFbPixelDefaultEventToken(defaultEventToken);` before initializing the Adjust SDK. +There is also the option to use a default Adjust event if you do not have mapping configured. Just call `adjustConfig.setFbPixelDefaultEventToken(defaultEventToken);` before initializing the Adjust SDK. +[example-fbpixel]: ../../examples/AdjustExample-FbPixel From 77d43581b937cc8e5b99cf3a3cb79b7989bebcac Mon Sep 17 00:00:00 2001 From: uerceg Date: Thu, 23 Aug 2018 13:00:40 +0200 Subject: [PATCH 12/27] Small cleanup --- AdjustBridge/AdjustBridge.h | 4 +--- AdjustBridge/AdjustBridge.m | 20 +++++++++----------- AdjustBridge/AdjustBridgeRegister.m | 7 +++---- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/AdjustBridge/AdjustBridge.h b/AdjustBridge/AdjustBridge.h index 2ce0ca2bd..39447b448 100644 --- a/AdjustBridge/AdjustBridge.h +++ b/AdjustBridge/AdjustBridge.h @@ -9,18 +9,16 @@ #import #import #import - #import "AdjustBridgeRegister.h" @interface AdjustBridge : NSObject -@property (nonatomic, strong, readonly) AdjustBridgeRegister * bridgeRegister; +@property (nonatomic, strong, readonly) AdjustBridgeRegister *bridgeRegister; - (void)loadUIWebViewBridge:(WVJB_WEBVIEW_TYPE *)webView; - (void)loadWKWebViewBridge:(WKWebView *)wkWebView; - (void)loadUIWebViewBridge:(WVJB_WEBVIEW_TYPE *)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE *)webViewDelegate; - (void)loadWKWebViewBridge:(WKWebView *)wkWebView wkWebViewDelegate:(id)wkWebViewDelegate; - - (void)augmentHybridWebView; @end diff --git a/AdjustBridge/AdjustBridge.m b/AdjustBridge/AdjustBridge.m index 15a835dcd..97788a0bd 100644 --- a/AdjustBridge/AdjustBridge.m +++ b/AdjustBridge/AdjustBridge.m @@ -129,7 +129,7 @@ - (BOOL)adjustDeeplinkResponse:(NSURL *)deeplink { #pragma mark - Public methods - (void)augmentHybridWebView { - NSString * fbAppId = [self getFbAppId]; + NSString *fbAppId = [self getFbAppId]; if (fbAppId == nil) { [[ADJAdjustFactory logger] error:@"FacebookAppID is not correctly configured in the pList"]; @@ -468,7 +468,7 @@ - (void)registerAugmentedView { return; } - ADJEvent * fbPixelEvent = [ADJEvent eventWithEventToken:eventToken]; + ADJEvent *fbPixelEvent = [ADJEvent eventWithEventToken:eventToken]; if (![fbPixelEvent isValid]) { return; } @@ -476,17 +476,15 @@ - (void)registerAugmentedView { id customData = [data objectForKey:@"customData"]; [fbPixelEvent addPartnerParameter:@"_fb_pixel_referral_id" value:pixelID]; - //[fbPixelEvent addPartnerParameter:@"_eventName" value:evtName]; + // [fbPixelEvent addPartnerParameter:@"_eventName" value:evtName]; if ([customData isKindOfClass:[NSString class]]) { NSError *jsonParseError = nil; - NSDictionary * params = - [NSJSONSerialization JSONObjectWithData:[customData dataUsingEncoding:NSUTF8StringEncoding] - options:NSJSONReadingMutableContainers - error:&jsonParseError - ]; + NSDictionary *params = [NSJSONSerialization JSONObjectWithData:[customData dataUsingEncoding:NSUTF8StringEncoding] + options:NSJSONReadingMutableContainers + error:&jsonParseError]; [params enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { - NSString * keyS = [key description]; - NSString * valueS = [obj description]; + NSString *keyS = [key description]; + NSString *valueS = [obj description]; [fbPixelEvent addPartnerParameter:keyS value:valueS]; }]; } @@ -507,7 +505,7 @@ - (BOOL)isFieldValid:(NSObject *)field { } - (NSString *)getFbAppId { - NSString * facebookLoggingOverrideAppID = [self getValueFromBundleByKey:@"FacebookLoggingOverrideAppID"]; + NSString *facebookLoggingOverrideAppID = [self getValueFromBundleByKey:@"FacebookLoggingOverrideAppID"]; if (facebookLoggingOverrideAppID != nil) { return facebookLoggingOverrideAppID; diff --git a/AdjustBridge/AdjustBridgeRegister.m b/AdjustBridge/AdjustBridgeRegister.m index 0ad8bb6af..808a423af 100644 --- a/AdjustBridge/AdjustBridgeRegister.m +++ b/AdjustBridge/AdjustBridgeRegister.m @@ -9,7 +9,6 @@ #import "AdjustBridgeRegister.h" static NSString * const kHandlerPrefix = @"adjust_"; - static NSString * fbAppIdStatic = nil; @interface AdjustBridgeRegister() @@ -48,9 +47,9 @@ - (void)augmentHybridWebView:(NSString *)fbAppId { + (NSString *)AdjustBridge_js { if (fbAppIdStatic != nil) { - return [NSString stringWithFormat:@"%@%@" - ,[AdjustBridgeRegister adjust_js] - ,[AdjustBridgeRegister augmented_js]]; + return [NSString stringWithFormat:@"%@%@", + [AdjustBridgeRegister adjust_js], + [AdjustBridgeRegister augmented_js]]; } else { return [AdjustBridgeRegister adjust_js]; } From fa888f076501c65c4ec0708862762d7ecac0f12d Mon Sep 17 00:00:00 2001 From: uerceg Date: Fri, 24 Aug 2018 11:27:27 +0200 Subject: [PATCH 13/27] Add event callback ID functionality --- Adjust/ADJActivityPackage.m | 2 +- Adjust/ADJEvent.h | 13 +++++++++++++ Adjust/ADJEvent.m | 4 ++++ Adjust/ADJEventFailure.h | 5 +++++ Adjust/ADJEventFailure.m | 4 +++- Adjust/ADJEventSuccess.h | 5 +++++ Adjust/ADJEventSuccess.m | 4 +++- Adjust/ADJPackageBuilder.m | 1 + Adjust/ADJResponseData.h | 2 ++ Adjust/ADJResponseData.m | 3 +++ Adjust/ADJUtil.m | 9 +++++++++ .../AdjustExample-iOS/ViewControlleriOS.m | 3 +++ 12 files changed, 52 insertions(+), 3 deletions(-) diff --git a/Adjust/ADJActivityPackage.m b/Adjust/ADJActivityPackage.m index 0fb097f47..6231e28ab 100644 --- a/Adjust/ADJActivityPackage.m +++ b/Adjust/ADJActivityPackage.m @@ -15,7 +15,7 @@ @implementation ADJActivityPackage - (NSString *)extendedString { NSMutableString *builder = [NSMutableString string]; - NSArray *excludedKeys = @[@"secret_id", @"app_secret"]; + NSArray *excludedKeys = @[@"secret_id", @"app_secret", @"event_callback_id"]; [builder appendFormat:@"Path: %@\n", self.path]; [builder appendFormat:@"ClientSdk: %@\n", self.clientSdk]; diff --git a/Adjust/ADJEvent.h b/Adjust/ADJEvent.h index d26247fb6..a2363c228 100644 --- a/Adjust/ADJEvent.h +++ b/Adjust/ADJEvent.h @@ -28,6 +28,11 @@ */ @property (nonatomic, copy, readonly, nonnull) NSString *transactionId; +/** + * @brief Custom user defined event ID. + */ +@property (nonatomic, copy, readonly, nonnull) NSString *callbackId; + /** * @brief Currency value. */ @@ -106,6 +111,14 @@ */ - (void)setTransactionId:(nonnull NSString *)transactionId; +/** + * @brief Set the custom user defined ID for the event which will be reported in + * success/failure callbacks. + * + * @param callbackId Custom user defined identifier for the event + */ +- (void)setCallbackId:(nonnull NSString *)callbackId; + /** * @brief Check if created adjust event object is valid. * diff --git a/Adjust/ADJEvent.m b/Adjust/ADJEvent.m index 3b585b184..99c358de1 100644 --- a/Adjust/ADJEvent.m +++ b/Adjust/ADJEvent.m @@ -93,6 +93,10 @@ - (void) setTransactionId:(NSString *)transactionId { _transactionId = transactionId; } +- (void)setCallbackId:(NSString *)callbackId { + _callbackId = callbackId; +} + - (NSDictionary *) callbackParameters { return (NSDictionary *) self.callbackMutableParameters; } diff --git a/Adjust/ADJEventFailure.h b/Adjust/ADJEventFailure.h index c3be34b17..ff272bbc1 100644 --- a/Adjust/ADJEventFailure.h +++ b/Adjust/ADJEventFailure.h @@ -30,6 +30,11 @@ */ @property (nonatomic, copy) NSString * eventToken; +/** + * @brief Event callback ID. + */ +@property (nonatomic, copy) NSString *callbackId; + /** * @brief Information whether sending of the package will be retried or not. */ diff --git a/Adjust/ADJEventFailure.m b/Adjust/ADJEventFailure.m index 6addc4e9f..bf35abf60 100644 --- a/Adjust/ADJEventFailure.m +++ b/Adjust/ADJEventFailure.m @@ -36,6 +36,7 @@ - (id)copyWithZone:(NSZone *)zone { copy.timeStamp = [self.timeStamp copyWithZone:zone]; copy.adid = [self.adid copyWithZone:zone]; copy.eventToken = [self.eventToken copyWithZone:zone]; + copy.callbackId = [self.callbackId copyWithZone:zone]; copy.willRetry = self.willRetry; copy.jsonResponse = [self.jsonResponse copyWithZone:zone]; } @@ -46,11 +47,12 @@ - (id)copyWithZone:(NSZone *)zone { #pragma mark - NSObject protocol methods - (NSString *)description { - return [NSString stringWithFormat: @"Event Failure msg:%@ time:%@ adid:%@ event:%@ retry:%@ json:%@", + return [NSString stringWithFormat: @"Event Failure msg:%@ time:%@ adid:%@ event:%@ cid:%@, retry:%@ json:%@", self.message, self.timeStamp, self.adid, self.eventToken, + self.callbackId, self.willRetry ? @"YES" : @"NO", self.jsonResponse]; } diff --git a/Adjust/ADJEventSuccess.h b/Adjust/ADJEventSuccess.h index e6d578f71..34214e21c 100644 --- a/Adjust/ADJEventSuccess.h +++ b/Adjust/ADJEventSuccess.h @@ -30,6 +30,11 @@ */ @property (nonatomic, copy) NSString *eventToken; +/** + * @brief Event callback ID. + */ +@property (nonatomic, copy) NSString *callbackId; + /** * @brief Backend response in JSON format. */ diff --git a/Adjust/ADJEventSuccess.m b/Adjust/ADJEventSuccess.m index e0c924a7e..1a40be353 100644 --- a/Adjust/ADJEventSuccess.m +++ b/Adjust/ADJEventSuccess.m @@ -36,6 +36,7 @@ - (id)copyWithZone:(NSZone *)zone { copy.timeStamp = [self.timeStamp copyWithZone:zone]; copy.adid = [self.adid copyWithZone:zone]; copy.eventToken = [self.eventToken copyWithZone:zone]; + copy.callbackId = [self.callbackId copyWithZone:zone]; copy.jsonResponse = [self.jsonResponse copyWithZone:zone]; } @@ -45,11 +46,12 @@ - (id)copyWithZone:(NSZone *)zone { #pragma mark - NSObject protocol methods - (NSString *)description { - return [NSString stringWithFormat: @"Event Success msg:%@ time:%@ adid:%@ event:%@ json:%@", + return [NSString stringWithFormat: @"Event Success msg:%@ time:%@ adid:%@ event:%@ cid:%@ json:%@", self.message, self.timeStamp, self.adid, self.eventToken, + self.callbackId, self.jsonResponse]; } diff --git a/Adjust/ADJPackageBuilder.m b/Adjust/ADJPackageBuilder.m index c34d9a076..8c2c45e35 100644 --- a/Adjust/ADJPackageBuilder.m +++ b/Adjust/ADJPackageBuilder.m @@ -75,6 +75,7 @@ - (ADJActivityPackage *)buildEventPackage:(ADJEvent *)event [ADJPackageBuilder parameters:parameters setNumber:event.revenue forKey:@"revenue"]; [ADJPackageBuilder parameters:parameters setString:event.currency forKey:@"currency"]; [ADJPackageBuilder parameters:parameters setString:event.eventToken forKey:@"event_token"]; + [ADJPackageBuilder parameters:parameters setString:event.callbackId forKey:@"event_callback_id"]; if (!isInDelay) { NSDictionary *mergedCallbackParameters = [ADJUtil mergeParameters:self.sessionParameters.callbackParameters diff --git a/Adjust/ADJResponseData.h b/Adjust/ADJResponseData.h index edf0f6f6a..57b209398 100644 --- a/Adjust/ADJResponseData.h +++ b/Adjust/ADJResponseData.h @@ -62,6 +62,8 @@ typedef NS_ENUM(int, ADJTrackingState) { @property (nonatomic, copy) NSString *eventToken; +@property (nonatomic, copy) NSString *callbackId; + - (ADJEventSuccess *)successResponseData; - (ADJEventFailure *)failureResponseData; diff --git a/Adjust/ADJResponseData.m b/Adjust/ADJResponseData.m index a929a6095..986043723 100644 --- a/Adjust/ADJResponseData.m +++ b/Adjust/ADJResponseData.m @@ -145,6 +145,7 @@ - (id)initWithActivityPackage:(ADJActivityPackage *)activityPackage { } self.eventToken = [activityPackage.parameters objectForKey:@"event_token"]; + self.callbackId = [activityPackage.parameters objectForKey:@"event_callback_id"]; return self; } @@ -156,6 +157,7 @@ - (ADJEventSuccess *)successResponseData { successResponseData.timeStamp = self.timeStamp; successResponseData.adid = self.adid; successResponseData.eventToken = self.eventToken; + successResponseData.callbackId = self.callbackId; successResponseData.jsonResponse = self.jsonResponse; return successResponseData; @@ -168,6 +170,7 @@ - (ADJEventFailure *)failureResponseData { failureResponseData.timeStamp = self.timeStamp; failureResponseData.adid = self.adid; failureResponseData.eventToken = self.eventToken; + failureResponseData.callbackId = self.callbackId; failureResponseData.willRetry = self.willRetry; failureResponseData.jsonResponse = self.jsonResponse; diff --git a/Adjust/ADJUtil.m b/Adjust/ADJUtil.m index 4139abd19..735dfc0d8 100644 --- a/Adjust/ADJUtil.m +++ b/Adjust/ADJUtil.m @@ -630,6 +630,15 @@ + (NSString *)extractSecretId:(ADJActivityPackage *)activityPackage { return appSecret; } ++ (void)extractEventCallbackId:(ADJActivityPackage *)activityPackage { + NSString *eventCallbackId = [activityPackage.parameters objectForKey:@"event_callback_id"]; + if (eventCallbackId == nil) { + return; + } + + [activityPackage.parameters removeObjectForKey:@"event_callback_id"]; +} + + (NSMutableURLRequest *)requestForGetPackage:(ADJActivityPackage *)activityPackage baseUrl:(NSURL *)baseUrl basePath:(NSString *)basePath diff --git a/examples/AdjustExample-iOS/AdjustExample-iOS/ViewControlleriOS.m b/examples/AdjustExample-iOS/AdjustExample-iOS/ViewControlleriOS.m index a86d84ac8..2a8e28864 100644 --- a/examples/AdjustExample-iOS/AdjustExample-iOS/ViewControlleriOS.m +++ b/examples/AdjustExample-iOS/AdjustExample-iOS/ViewControlleriOS.m @@ -37,6 +37,9 @@ - (void)didReceiveMemoryWarning { - (IBAction)clickTrackSimpleEvent:(UIButton *)sender { ADJEvent *event = [ADJEvent eventWithEventToken:kEventToken1]; + // Attach callback ID to event. + [event setCallbackId:@"RandomCallbackId"]; + [Adjust trackEvent:event]; } From 86381a32ae72b17e58cb1459015a931f1739f95a Mon Sep 17 00:00:00 2001 From: uerceg Date: Fri, 24 Aug 2018 14:32:35 +0200 Subject: [PATCH 14/27] Test app support for event callback ID --- .../AdjustTestApp/ATAAdjustCommandExecutor.m | 8 ++++++++ .../Delegates/ATAAdjustDelegateEventFailure.m | 1 + .../Delegates/ATAAdjustDelegateEventSuccess.m | 1 + 3 files changed, 10 insertions(+) diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m index fed0461a5..21a8475a0 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m @@ -371,6 +371,14 @@ - (void)event:(NSDictionary *)parameters { } [adjustEvent setTransactionId:transactionId]; } + + if ([parameters objectForKey:@"callbackId"]) { + NSString *callbackId = [parameters objectForKey:@"callbackId"][0]; + if (callbackId == (id)[NSNull null]) { + callbackId = nil; + } + [adjustEvent setCallbackId:callbackId]; + } } - (void)trackEvent:(NSDictionary *)parameters { diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventFailure.m b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventFailure.m index b394da9d6..17ba3479f 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventFailure.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventFailure.m @@ -38,6 +38,7 @@ - (void)adjustEventTrackingFailed:(ADJEventFailure *)eventFailureResponseData { [self.testLibrary addInfoToSend:@"timestamp" value:eventFailureResponseData.timeStamp]; [self.testLibrary addInfoToSend:@"adid" value:eventFailureResponseData.adid]; [self.testLibrary addInfoToSend:@"eventToken" value:eventFailureResponseData.eventToken]; + [self.testLibrary addInfoToSend:@"callbackId" value:eventFailureResponseData.callbackId]; [self.testLibrary addInfoToSend:@"willRetry" value:(eventFailureResponseData.willRetry ? @"true" : @"false")]; NSError *error; diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventSuccess.m b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventSuccess.m index bfe2b33d6..573eafce7 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventSuccess.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventSuccess.m @@ -38,6 +38,7 @@ - (void)adjustEventTrackingSucceeded:(ADJEventSuccess *)eventSuccessResponseData [self.testLibrary addInfoToSend:@"timestamp" value:eventSuccessResponseData.timeStamp]; [self.testLibrary addInfoToSend:@"adid" value:eventSuccessResponseData.adid]; [self.testLibrary addInfoToSend:@"eventToken" value:eventSuccessResponseData.eventToken]; + [self.testLibrary addInfoToSend:@"callbackId" value:eventSuccessResponseData.callbackId]; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:eventSuccessResponseData.jsonResponse From 0ecf170f368be33d7a111a91a1600e0a60aafdb6 Mon Sep 17 00:00:00 2001 From: nonelse Date: Mon, 27 Aug 2018 14:40:54 +0200 Subject: [PATCH 15/27] Fix fb example plist duplication --- .../AdjustExample-FbPixel.xcodeproj/project.pbxproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.pbxproj b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.pbxproj index e76ed1aed..6d5ef595b 100644 --- a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.pbxproj +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.pbxproj @@ -46,7 +46,6 @@ 9D9D15D6212EB4570081445E /* ADJResponseData.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15A1212EB4560081445E /* ADJResponseData.m */; }; 9D9D15D7212EB4570081445E /* ADJPackageBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15A3212EB4560081445E /* ADJPackageBuilder.m */; }; 9D9D15D8212EB4570081445E /* ADJUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15A4212EB4560081445E /* ADJUserDefaults.m */; }; - 9D9D15D9212EB4570081445E /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9D9D15A8212EB4560081445E /* Info.plist */; }; 9D9D15DA212EB4570081445E /* ADJActivityHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15AA212EB4560081445E /* ADJActivityHandler.m */; }; 9D9D15DB212EB4570081445E /* ADJReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15AB212EB4560081445E /* ADJReachability.m */; }; 9D9D15DC212EB4570081445E /* AdjustBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D15AD212EB4570081445E /* AdjustBridge.m */; }; @@ -135,7 +134,6 @@ 9D9D15A5212EB4560081445E /* ADJBackoffStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJBackoffStrategy.h; sourceTree = ""; }; 9D9D15A6212EB4560081445E /* ADJLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJLogger.h; sourceTree = ""; }; 9D9D15A7212EB4560081445E /* ADJSessionParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSessionParameters.h; sourceTree = ""; }; - 9D9D15A8212EB4560081445E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9D9D15A9212EB4560081445E /* ADJTimerCycle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJTimerCycle.h; sourceTree = ""; }; 9D9D15AA212EB4560081445E /* ADJActivityHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJActivityHandler.m; sourceTree = ""; }; 9D9D15AB212EB4560081445E /* ADJReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJReachability.m; sourceTree = ""; }; @@ -289,7 +287,6 @@ 9D9D15A5212EB4560081445E /* ADJBackoffStrategy.h */, 9D9D15A6212EB4560081445E /* ADJLogger.h */, 9D9D15A7212EB4560081445E /* ADJSessionParameters.h */, - 9D9D15A8212EB4560081445E /* Info.plist */, 9D9D15A9212EB4560081445E /* ADJTimerCycle.h */, 9D9D15AA212EB4560081445E /* ADJActivityHandler.m */, 9D9D15AB212EB4560081445E /* ADJReachability.m */, @@ -396,7 +393,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 9D9D15D9212EB4570081445E /* Info.plist in Resources */, 9D9D15E3212EB47C0081445E /* AdjustExample-FbPixel.html in Resources */, 9D9D153E212EB3940081445E /* LaunchScreen.storyboard in Resources */, 9D9D153B212EB3940081445E /* Assets.xcassets in Resources */, From 82f5c94d2e58ef7696648c0d8ed6ccf0678b7799 Mon Sep 17 00:00:00 2001 From: nonelse Date: Mon, 27 Aug 2018 14:41:28 +0200 Subject: [PATCH 16/27] Add args to fb pixel search track --- .../AdjustExample-FbPixel/AdjustExample-FbPixel.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AdjustExample-FbPixel.html b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AdjustExample-FbPixel.html index a09af2934..a83d3af34 100644 --- a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AdjustExample-FbPixel.html +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel/AdjustExample-FbPixel.html @@ -62,7 +62,11 @@

Adjust Web View Demo

var btnTrackSimpleEvent = document.getElementById('btnTrackSimpleEvent') btnTrackSimpleEvent.onclick = function(e) { e.preventDefault() - config.fbid && fbq('track', 'Search', config.fbid.toString()); + config.fbid && fbq('track', 'Search', { + search_string: 'search_string_value', + content_ids: ['123', '456'], + content_type: 'content_type_value' + }); } var btnTrackRevenueEvent = document.getElementById('btnTrackRevenueEvent') From 6a1fd3f7461e1cf4b14c297126a549b9ba9195c4 Mon Sep 17 00:00:00 2001 From: nonelse Date: Tue, 28 Aug 2018 16:29:01 +0200 Subject: [PATCH 17/27] Refactor network package construction copying and removing parameters --- Adjust/ADJUtil.h | 2 -- Adjust/ADJUtil.m | 59 +++++++++++++++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/Adjust/ADJUtil.h b/Adjust/ADJUtil.h index 74abbf764..784e86f71 100644 --- a/Adjust/ADJUtil.h +++ b/Adjust/ADJUtil.h @@ -112,8 +112,6 @@ typedef void (^isInactiveInjected)(BOOL); + (NSNumber *)readReachabilityFlags; -+ (NSString *)extractAppSecret:(ADJActivityPackage *)activityPackage; - #if !TARGET_OS_TV + (NSString *)readMCC; diff --git a/Adjust/ADJUtil.m b/Adjust/ADJUtil.m index 735dfc0d8..06832b02b 100644 --- a/Adjust/ADJUtil.m +++ b/Adjust/ADJUtil.m @@ -521,10 +521,17 @@ + (void)sendGetRequest:(NSURL *)baseUrl activityPackage:(ADJActivityPackage *)activityPackage responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { - NSString *appSecret = [ADJUtil extractAppSecret:activityPackage]; - NSString *secretId = [ADJUtil extractSecretId:activityPackage]; + NSMutableDictionary * parametersCopy = [[NSMutableDictionary alloc] initWithCapacity:[activityPackage.parameters count]]; + [parametersCopy addEntriesFromDictionary:activityPackage.parameters]; - NSMutableURLRequest *request = [ADJUtil requestForGetPackage:activityPackage baseUrl:baseUrl basePath:basePath]; + NSString *appSecret = [ADJUtil extractAppSecret:parametersCopy]; + NSString *secretId = [ADJUtil extractSecretId:parametersCopy]; + + NSMutableURLRequest *request = [ADJUtil requestForGetPackage:activityPackage.path + clientSdk:activityPackage.clientSdk + parameters:parametersCopy + baseUrl:baseUrl + basePath:basePath]; [ADJUtil sendRequest:request prefixErrorMessage:prefixErrorMessage @@ -556,10 +563,16 @@ + (void)sendPostRequest:(NSURL *)baseUrl activityPackage:(ADJActivityPackage *)activityPackage responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { - NSString *appSecret = [ADJUtil extractAppSecret:activityPackage]; - NSString *secretId = [ADJUtil extractSecretId:activityPackage]; + NSMutableDictionary * parametersCopy = [[NSMutableDictionary alloc] initWithCapacity:[activityPackage.parameters count]]; + [parametersCopy addEntriesFromDictionary:activityPackage.parameters]; + + NSString *appSecret = [ADJUtil extractAppSecret:parametersCopy]; + NSString *secretId = [ADJUtil extractSecretId:parametersCopy]; - NSMutableURLRequest *request = [ADJUtil requestForPostPackage:activityPackage baseUrl:baseUrl queueSize:queueSize]; + NSMutableURLRequest *request = [ADJUtil requestForPostPackage:activityPackage.path + clientSdk:activityPackage.clientSdk + parameters:parametersCopy + baseUrl:baseUrl queueSize:queueSize]; [ADJUtil sendRequest:request prefixErrorMessage:prefixErrorMessage @@ -606,26 +619,26 @@ + (void)sendRequest:(NSMutableURLRequest *)request } } -+ (NSString *)extractAppSecret:(ADJActivityPackage *)activityPackage { - NSString *appSecret = [activityPackage.parameters objectForKey:@"app_secret"]; ++ (NSString *)extractAppSecret:(NSMutableDictionary *)parameters { + NSString *appSecret = [parameters objectForKey:@"app_secret"]; if (appSecret == nil) { return nil; } - [activityPackage.parameters removeObjectForKey:@"app_secret"]; + [parameters removeObjectForKey:@"app_secret"]; return appSecret; } -+ (NSString *)extractSecretId:(ADJActivityPackage *)activityPackage { - NSString *appSecret = [activityPackage.parameters objectForKey:@"secret_id"]; ++ (NSString *)extractSecretId:(NSMutableDictionary *)parameters { + NSString *appSecret = [parameters objectForKey:@"secret_id"]; if (appSecret == nil) { return nil; } - [activityPackage.parameters removeObjectForKey:@"secret_id"]; + [parameters removeObjectForKey:@"secret_id"]; return appSecret; } @@ -639,16 +652,18 @@ + (void)extractEventCallbackId:(ADJActivityPackage *)activityPackage { [activityPackage.parameters removeObjectForKey:@"event_callback_id"]; } -+ (NSMutableURLRequest *)requestForGetPackage:(ADJActivityPackage *)activityPackage ++ (NSMutableURLRequest *)requestForGetPackage:(NSString *)path + clientSdk:(NSString *)clientSdk + parameters:(NSDictionary *)parameters baseUrl:(NSURL *)baseUrl basePath:(NSString *)basePath { - NSString *parameters = [ADJUtil queryString:activityPackage.parameters]; + NSString *queryStringParameters = [ADJUtil queryString:parameters]; NSString *relativePath; if (basePath != nil) { - relativePath = [NSString stringWithFormat:@"%@%@?%@", basePath, activityPackage.path, parameters]; + relativePath = [NSString stringWithFormat:@"%@%@?%@", basePath, path, queryStringParameters]; } else { - relativePath = [NSString stringWithFormat:@"%@?%@", activityPackage.path, parameters]; + relativePath = [NSString stringWithFormat:@"%@?%@", path, queryStringParameters]; } NSURL *url = [NSURL URLWithString:relativePath relativeToURL:baseUrl]; @@ -656,22 +671,24 @@ + (NSMutableURLRequest *)requestForGetPackage:(ADJActivityPackage *)activityPack request.timeoutInterval = kRequestTimeout; request.HTTPMethod = @"GET"; - [request setValue:activityPackage.clientSdk forHTTPHeaderField:@"Client-Sdk"]; + [request setValue:clientSdk forHTTPHeaderField:@"Client-Sdk"]; return request; } -+ (NSMutableURLRequest *)requestForPostPackage:(ADJActivityPackage *)activityPackage ++ (NSMutableURLRequest *)requestForPostPackage:(NSString *)path + clientSdk:(NSString *)clientSdk + parameters:(NSDictionary *)parameters baseUrl:(NSURL *)baseUrl queueSize:(NSUInteger)queueSize { - NSURL *url = [baseUrl URLByAppendingPathComponent:activityPackage.path]; + NSURL *url = [baseUrl URLByAppendingPathComponent:path]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.timeoutInterval = kRequestTimeout; request.HTTPMethod = @"POST"; [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; - [request setValue:activityPackage.clientSdk forHTTPHeaderField:@"Client-Sdk"]; + [request setValue:clientSdk forHTTPHeaderField:@"Client-Sdk"]; - NSString *bodyString = [ADJUtil queryString:activityPackage.parameters queueSize:queueSize]; + NSString *bodyString = [ADJUtil queryString:parameters queueSize:queueSize]; NSData *body = [NSData dataWithBytes:bodyString.UTF8String length:bodyString.length]; [request setHTTPBody:body]; From b1b7bd450414f1101caac43edf7402678be4c529 Mon Sep 17 00:00:00 2001 From: nonelse Date: Tue, 28 Aug 2018 16:29:34 +0200 Subject: [PATCH 18/27] Remove event_callback_id from packages sent --- Adjust/ADJUtil.m | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Adjust/ADJUtil.m b/Adjust/ADJUtil.m index 06832b02b..99f8813df 100644 --- a/Adjust/ADJUtil.m +++ b/Adjust/ADJUtil.m @@ -526,6 +526,7 @@ + (void)sendGetRequest:(NSURL *)baseUrl NSString *appSecret = [ADJUtil extractAppSecret:parametersCopy]; NSString *secretId = [ADJUtil extractSecretId:parametersCopy]; + [ADJUtil extractEventCallbackId:parametersCopy]; NSMutableURLRequest *request = [ADJUtil requestForGetPackage:activityPackage.path clientSdk:activityPackage.clientSdk @@ -568,6 +569,7 @@ + (void)sendPostRequest:(NSURL *)baseUrl NSString *appSecret = [ADJUtil extractAppSecret:parametersCopy]; NSString *secretId = [ADJUtil extractSecretId:parametersCopy]; + [ADJUtil extractEventCallbackId:parametersCopy]; NSMutableURLRequest *request = [ADJUtil requestForPostPackage:activityPackage.path clientSdk:activityPackage.clientSdk @@ -643,13 +645,13 @@ + (NSString *)extractSecretId:(NSMutableDictionary *)parameters { return appSecret; } -+ (void)extractEventCallbackId:(ADJActivityPackage *)activityPackage { - NSString *eventCallbackId = [activityPackage.parameters objectForKey:@"event_callback_id"]; ++ (void)extractEventCallbackId:(NSMutableDictionary *)parameters { + NSString *eventCallbackId = [parameters objectForKey:@"event_callback_id"]; if (eventCallbackId == nil) { return; } - [activityPackage.parameters removeObjectForKey:@"event_callback_id"]; + [parameters removeObjectForKey:@"event_callback_id"]; } + (NSMutableURLRequest *)requestForGetPackage:(NSString *)path From 5fd201a885e83217f4f550c7dca68472585549d6 Mon Sep 17 00:00:00 2001 From: uerceg Date: Wed, 29 Aug 2018 10:17:46 +0200 Subject: [PATCH 19/27] ADJUtil.m cleanup --- Adjust/ADJUtil.m | 249 +++++------------------------------------------ 1 file changed, 26 insertions(+), 223 deletions(-) diff --git a/Adjust/ADJUtil.m b/Adjust/ADJUtil.m index 99f8813df..60ae55a64 100644 --- a/Adjust/ADJUtil.m +++ b/Adjust/ADJUtil.m @@ -1,24 +1,23 @@ // // ADJUtil.m -// Adjust +// Adjust SDK // -// Created by Christian Wellenbrock on 2013-07-05. -// Copyright (c) 2013 adjust GmbH. All rights reserved. +// Created by Christian Wellenbrock (@wellle) on 5th July 2013. +// Copyright (c) 2013-2018 Adjust GmbH. All rights reserved. // #include #include #include - #import #import "ADJUtil.h" #import "ADJLogger.h" +#import "ADJReachability.h" #import "ADJResponseData.h" #import "ADJAdjustFactory.h" #import "UIDevice+ADJAdditions.h" #import "NSString+ADJAdditions.h" -#import "ADJReachability.h" #if !TARGET_OS_TV #import @@ -27,20 +26,19 @@ static const double kRequestTimeout = 60; // 60 seconds +static NSString *userAgent = nil; +static ADJReachability *reachability = nil; static NSRegularExpression *universalLinkRegex = nil; static NSNumberFormatter *secondsNumberFormatter = nil; static NSRegularExpression *optionalRedirectRegex = nil; static NSRegularExpression *shortUniversalLinkRegex = nil; static NSURLSessionConfiguration *urlSessionConfiguration = nil; -static ADJReachability *reachability = nil; #if !TARGET_OS_TV -static CTTelephonyNetworkInfo *networkInfo = nil; static CTCarrier *carrier = nil; +static CTTelephonyNetworkInfo *networkInfo = nil; #endif -static NSString *userAgent = nil; - static NSString * const kClientSdk = @"ios4.14.3"; static NSString * const kDeeplinkParam = @"deep_link="; static NSString * const kSchemeDelimiter = @"://"; @@ -69,12 +67,12 @@ + (void)initialize { } + (void)teardown { + reachability = nil; universalLinkRegex = nil; secondsNumberFormatter = nil; - optionalRedirectRegex = nil; + optionalRedirectRegex = nil; shortUniversalLinkRegex = nil; urlSessionConfiguration = nil; - reachability = nil; #if !TARGET_OS_TV networkInfo = nil; carrier = nil; @@ -84,46 +82,37 @@ + (void)teardown { + (void)initializeUniversalLinkRegex { NSError *error = NULL; - NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:kUniversalLinkPattern options:NSRegularExpressionCaseInsensitive error:&error]; - if ([ADJUtil isNotNull:error]) { [ADJAdjustFactory.logger error:@"Universal link regex rule error (%@)", [error description]]; return; } - universalLinkRegex = regex; } + (void)initializeShortUniversalLinkRegex { NSError *error = NULL; - NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:kShortUniversalLinkPattern options:NSRegularExpressionCaseInsensitive error:&error]; - if ([ADJUtil isNotNull:error]) { [ADJAdjustFactory.logger error:@"Short Universal link regex rule error (%@)", [error description]]; return; } - shortUniversalLinkRegex = regex; } + (void)initializeOptionalRedirectRegex { NSError *error = NULL; - NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:kOptionalRedirectPattern options:NSRegularExpressionCaseInsensitive error:&error]; - if ([ADJUtil isNotNull:error]) { [ADJAdjustFactory.logger error:@"Optional redirect regex rule error (%@)", [error description]]; return; } - optionalRedirectRegex = regex; } @@ -166,11 +155,9 @@ + (NSString *)clientSdk { + (NSDateFormatter *)getDateFormatter { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; - if ([NSCalendar instancesRespondToSelector:@selector(calendarWithIdentifier:)]) { // http://stackoverflow.com/a/3339787 NSString *calendarIdentifier; - #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wtautological-pointer-compare" if (&NSCalendarIdentifierGregorian != NULL) { @@ -183,10 +170,8 @@ + (NSDateFormatter *)getDateFormatter { calendarIdentifier = NSGregorianCalendar; #pragma clang diagnostic pop } - dateFormatter.calendar = [NSCalendar calendarWithIdentifier:calendarIdentifier]; } - dateFormatter.locale = [NSLocale systemLocale]; [dateFormatter setDateFormat:kDateFormat]; @@ -206,18 +191,15 @@ + (void)excludeFromBackup:(NSString *)path { if (&NSURLIsExcludedFromBackupKey == nil) { u_int8_t attrValue = 1; int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0); - if (result != 0) { [logger debug:@"Failed to exclude '%@' from backup", url.lastPathComponent]; } } else { // iOS 5.0 and higher // First try and remove the extended attribute if it is present ssize_t result = getxattr(filePath, attrName, NULL, sizeof(u_int8_t), 0, 0); - if (result != -1) { // The attribute exists, we need to remove it int removeResult = removexattr(filePath, attrName, 0); - if (removeResult == 0) { [logger debug:@"Removed extended attribute on file '%@'", url]; } @@ -228,7 +210,6 @@ + (void)excludeFromBackup:(NSString *)path { BOOL success = [url setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error]; - if (!success || error != nil) { [logger debug:@"Failed to exclude '%@' from backup (%@)", url.lastPathComponent, error.localizedDescription]; } @@ -243,11 +224,9 @@ + (NSString *)formatSeconds1970:(double)value { + (NSString *)formatDate:(NSDate *)value { NSDateFormatter *dateFormatter = [ADJUtil getDateFormatter]; - if (dateFormatter == nil) { return nil; } - return [dateFormatter stringFromDate:value]; } @@ -258,19 +237,14 @@ + (void)saveJsonResponse:(NSData *)jsonData responseData:(ADJResponseData *)resp if (exception != nil) { NSString *message = [NSString stringWithFormat:@"Failed to parse json response. (%@)", exception.description]; - [ADJAdjustFactory.logger error:message]; responseData.message = message; - return; } - if (error != nil) { NSString *message = [NSString stringWithFormat:@"Failed to parse json response. (%@)", error.localizedDescription]; - [ADJAdjustFactory.logger error:message]; responseData.message = message; - return; } @@ -285,14 +259,12 @@ + (NSDictionary *)buildJsonDict:(NSData *)jsonData } NSDictionary *jsonDict = nil; - @try { jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:error]; } @catch (NSException *ex) { *exceptionPtr = ex; return nil; } - return jsonDict; } @@ -305,19 +277,15 @@ + (id)readObject:(NSString *)fileName @try { id appSupportObject = [NSKeyedUnarchiver unarchiveObjectWithFile:appSupportFilePath]; - if ([appSupportObject isKindOfClass:classToRead]) { // Successfully read object from Application Support folder, return it. - if ([appSupportObject isKindOfClass:[NSArray class]]) { [[ADJAdjustFactory logger] debug:@"Package handler read %d packages", [appSupportObject count]]; } else { [[ADJAdjustFactory logger] debug:@"Read %@: %@", objectName, appSupportObject]; } - // Just in case check if old file exists in Documents folder and if yes, remove it. [ADJUtil deleteFileInPath:documentsFilePath]; - return appSupportObject; } else if (appSupportObject == nil) { // [[ADJAdjustFactory logger] verbose:@"%@ file not found", appSupportFilePath]; @@ -333,23 +301,18 @@ + (id)readObject:(NSString *)fileName // If in here, for some reason, reading of file from Application Support folder failed. // Let's check the Documents folder. - @try { id documentsObject = [NSKeyedUnarchiver unarchiveObjectWithFile:documentsFilePath]; - if (documentsObject != nil) { // Successfully read object from Documents folder. - if ([documentsObject isKindOfClass:[NSArray class]]) { [[ADJAdjustFactory logger] debug:@"Package handler read %d packages", [documentsObject count]]; } else { [[ADJAdjustFactory logger] debug:@"Read %@: %@", objectName, documentsObject]; } - // Do the file migration. [[ADJAdjustFactory logger] verbose:@"Migrating %@ file from Documents to \"Application Support/Adjust\" folder", fileName]; [ADJUtil migrateFileFromPath:documentsFilePath toPath:appSupportFilePath]; - return documentsObject; } else if (documentsObject == nil) { // [[ADJAdjustFactory logger] verbose:@"%@ file not found", documentsFilePath]; @@ -362,7 +325,6 @@ + (id)readObject:(NSString *)fileName // [[ADJAdjustFactory logger] error:@"Failed to read %@ file (%@)", documentsFilePath, ex]; [[ADJAdjustFactory logger] error:@"Failed to read %@ file from Documents folder (%@)", fileName, ex]; } - return nil; } @@ -370,12 +332,9 @@ + (void)writeObject:(id)object fileName:(NSString *)fileName objectName:(NSString *)objectName { NSString *filePath = [ADJUtil getFilePathInAppSupportDir:fileName]; - BOOL result = (filePath != nil) && [NSKeyedArchiver archiveRootObject:object toFile:filePath]; - if (result == YES) { [ADJUtil excludeFromBackup:filePath]; - if ([object isKindOfClass:[NSArray class]]) { [[ADJAdjustFactory logger] debug:@"Package handler wrote %d packages", [object count]]; } else { @@ -388,72 +347,54 @@ + (void)writeObject:(id)object + (BOOL)migrateFileFromPath:(NSString *)oldPath toPath:(NSString *)newPath { NSError *errorCopy; - [[NSFileManager defaultManager] copyItemAtPath:oldPath toPath:newPath error:&errorCopy]; - if (errorCopy != nil) { [[ADJAdjustFactory logger] error:@"Error while copying from %@ to %@", oldPath, newPath]; [[ADJAdjustFactory logger] error:[errorCopy description]]; - return NO; } - // Migration successful. return YES; } + (NSString *)getFilePathInDocumentsDir:(NSString *)fileName { // Documents directory exists by default inside app bundle, no need to check for it's presence. - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDir = [paths objectAtIndex:0]; NSString *filePath = [documentsDir stringByAppendingPathComponent:fileName]; - return filePath; } + (NSString *)getFilePathInAppSupportDir:(NSString *)fileName { // Application Support directory doesn't exist by default inside app bundle. // All Adjust files are going to be stored in Adjust sub-directory inside Application Support directory. - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); NSString *appSupportDir = [paths firstObject]; NSString *adjustDirName = @"Adjust"; - if (![ADJUtil checkForDirectoryPresenceInPath:appSupportDir forFolder:[appSupportDir lastPathComponent]]) { return nil; } - NSString *adjustDir = [appSupportDir stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@", adjustDirName]]; - if (![ADJUtil checkForDirectoryPresenceInPath:adjustDir forFolder:adjustDirName]) { return nil; } - NSString *filePath = [adjustDir stringByAppendingPathComponent:fileName]; - return filePath; } + (BOOL)checkForDirectoryPresenceInPath:(NSString *)path forFolder:(NSString *)folderName { // Check for presence of directory first. // If it doesn't exist, make one. - if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { [[ADJAdjustFactory logger] debug:@"%@ directory not present and will be created", folderName]; - NSError *error; - [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:&error]; - if (error != nil) { [[ADJAdjustFactory logger] error:@"Error while creating % directory", path]; [[ADJAdjustFactory logger] error:[error description]]; - return NO; } } - return YES; } @@ -464,13 +405,11 @@ + (NSString *)queryString:(NSDictionary *)parameters { + (NSString *)queryString:(NSDictionary *)parameters queueSize:(NSUInteger)queueSize { NSMutableArray *pairs = [NSMutableArray array]; - for (NSString *key in parameters) { NSString *value = [parameters objectForKey:key]; NSString *escapedValue = [value adjUrlEncode]; NSString *escapedKey = [key adjUrlEncode]; NSString *pair = [NSString stringWithFormat:@"%@=%@", escapedKey, escapedValue]; - [pairs addObject:pair]; } @@ -478,7 +417,6 @@ + (NSString *)queryString:(NSDictionary *)parameters NSString *dateString = [ADJUtil formatSeconds1970:now]; NSString *escapedDate = [dateString adjUrlEncode]; NSString *sentAtPair = [NSString stringWithFormat:@"%@=%@", @"sent_at", escapedDate]; - [pairs addObject:sentAtPair]; if (queueSize > 0) { @@ -486,12 +424,10 @@ + (NSString *)queryString:(NSDictionary *)parameters NSString *queueSizeString = [NSString stringWithFormat:@"%lu", queueSizeNative]; NSString *escapedQueueSize = [queueSizeString adjUrlEncode]; NSString *queueSizePair = [NSString stringWithFormat:@"%@=%@", @"queue_size", escapedQueueSize]; - [pairs addObject:queueSizePair]; } NSString *queryString = [pairs componentsJoinedByString:@"&"]; - return queryString; } @@ -507,7 +443,6 @@ + (NSString *)formatErrorMessage:(NSString *)prefixErrorMessage systemErrorMessage:(NSString *)systemErrorMessage suffixErrorMessage:(NSString *)suffixErrorMessage { NSString *errorMessage = [NSString stringWithFormat:@"%@ (%@)", prefixErrorMessage, systemErrorMessage]; - if (suffixErrorMessage == nil) { return errorMessage; } else { @@ -520,8 +455,7 @@ + (void)sendGetRequest:(NSURL *)baseUrl prefixErrorMessage:(NSString *)prefixErrorMessage activityPackage:(ADJActivityPackage *)activityPackage responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { - - NSMutableDictionary * parametersCopy = [[NSMutableDictionary alloc] initWithCapacity:[activityPackage.parameters count]]; + NSMutableDictionary *parametersCopy = [[NSMutableDictionary alloc] initWithCapacity:[activityPackage.parameters count]]; [parametersCopy addEntriesFromDictionary:activityPackage.parameters]; NSString *appSecret = [ADJUtil extractAppSecret:parametersCopy]; @@ -533,7 +467,6 @@ + (void)sendGetRequest:(NSURL *)baseUrl parameters:parametersCopy baseUrl:baseUrl basePath:basePath]; - [ADJUtil sendRequest:request prefixErrorMessage:prefixErrorMessage activityPackage:activityPackage @@ -563,8 +496,7 @@ + (void)sendPostRequest:(NSURL *)baseUrl suffixErrorMessage:(NSString *)suffixErrorMessage activityPackage:(ADJActivityPackage *)activityPackage responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { - - NSMutableDictionary * parametersCopy = [[NSMutableDictionary alloc] initWithCapacity:[activityPackage.parameters count]]; + NSMutableDictionary *parametersCopy = [[NSMutableDictionary alloc] initWithCapacity:[activityPackage.parameters count]]; [parametersCopy addEntriesFromDictionary:activityPackage.parameters]; NSString *appSecret = [ADJUtil extractAppSecret:parametersCopy]; @@ -575,7 +507,6 @@ + (void)sendPostRequest:(NSURL *)baseUrl clientSdk:activityPackage.clientSdk parameters:parametersCopy baseUrl:baseUrl queueSize:queueSize]; - [ADJUtil sendRequest:request prefixErrorMessage:prefixErrorMessage suffixErrorMessage:suffixErrorMessage @@ -592,15 +523,12 @@ + (void)sendRequest:(NSMutableURLRequest *)request appSecret:(NSString *)appSecret activityPackage:(ADJActivityPackage *)activityPackage responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { - NSString *authHeader = [ADJUtil buildAuthorizationHeader:appSecret secretId:secretId activityPackage:activityPackage]; - if (authHeader != nil) { [request setValue:authHeader forHTTPHeaderField:@"Authorization"]; } - if (userAgent != nil) { [request setValue:userAgent forHTTPHeaderField:@"User-Agent"]; } @@ -623,25 +551,19 @@ + (void)sendRequest:(NSMutableURLRequest *)request + (NSString *)extractAppSecret:(NSMutableDictionary *)parameters { NSString *appSecret = [parameters objectForKey:@"app_secret"]; - if (appSecret == nil) { return nil; } - [parameters removeObjectForKey:@"app_secret"]; - return appSecret; } + (NSString *)extractSecretId:(NSMutableDictionary *)parameters { NSString *appSecret = [parameters objectForKey:@"secret_id"]; - if (appSecret == nil) { return nil; } - [parameters removeObjectForKey:@"secret_id"]; - return appSecret; } @@ -650,7 +572,6 @@ + (void)extractEventCallbackId:(NSMutableDictionary *)parameters { if (eventCallbackId == nil) { return; } - [parameters removeObjectForKey:@"event_callback_id"]; } @@ -658,8 +579,7 @@ + (NSMutableURLRequest *)requestForGetPackage:(NSString *)path clientSdk:(NSString *)clientSdk parameters:(NSDictionary *)parameters baseUrl:(NSURL *)baseUrl - basePath:(NSString *)basePath -{ + basePath:(NSString *)basePath { NSString *queryStringParameters = [ADJUtil queryString:parameters]; NSString *relativePath; if (basePath != nil) { @@ -667,14 +587,12 @@ + (NSMutableURLRequest *)requestForGetPackage:(NSString *)path } else { relativePath = [NSString stringWithFormat:@"%@?%@", path, queryStringParameters]; } - NSURL *url = [NSURL URLWithString:relativePath relativeToURL:baseUrl]; + NSURL *url = [NSURL URLWithString:relativePath relativeToURL:baseUrl]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.timeoutInterval = kRequestTimeout; request.HTTPMethod = @"GET"; - [request setValue:clientSdk forHTTPHeaderField:@"Client-Sdk"]; - return request; } @@ -693,7 +611,6 @@ + (NSMutableURLRequest *)requestForPostPackage:(NSString *)path NSString *bodyString = [ADJUtil queryString:parameters queueSize:queueSize]; NSData *body = [NSData dataWithBytes:bodyString.UTF8String length:bodyString.length]; [request setHTTPBody:body]; - return request; } @@ -706,31 +623,25 @@ + (NSString *)buildAuthorizationHeader:(NSString *)appSecret NSMutableDictionary *parameters = activityPackage.parameters; NSString *activityKindS = [ADJActivityKindUtil activityKindToString:activityPackage.activityKind]; - - NSDictionary *signatureParameters = [ADJUtil buildSignatureParameters:parameters appSecret:appSecret activityKindS:activityKindS]; - NSMutableString *fields = [[NSMutableString alloc] initWithCapacity:5]; NSMutableString *clearSignature = [[NSMutableString alloc] initWithCapacity:5]; // signature part of header for (NSDictionary *key in signatureParameters) { [fields appendFormat:@"%@ ", key]; - NSString *value = [signatureParameters objectForKey:key]; [clearSignature appendString:value]; } - NSString * secretIdHeader = [NSString stringWithFormat:@"secret_id=\"%@\"", secretId]; - + NSString *secretIdHeader = [NSString stringWithFormat:@"secret_id=\"%@\"", secretId]; // algorithm part of header - NSString * algorithm = @"sha256"; - NSString * signature = [clearSignature adjSha256]; - NSString * signatureHeader = [NSString stringWithFormat:@"signature=\"%@\"", signature]; - - NSString * algorithmHeader = [NSString stringWithFormat:@"algorithm=\"%@\"", algorithm]; + NSString *algorithm = @"sha256"; + NSString *signature = [clearSignature adjSha256]; + NSString *signatureHeader = [NSString stringWithFormat:@"signature=\"%@\"", signature]; + NSString *algorithmHeader = [NSString stringWithFormat:@"algorithm=\"%@\"", algorithm]; // fields part of header // Remove last empty space. if (fields.length > 0) { @@ -738,13 +649,13 @@ + (NSString *)buildAuthorizationHeader:(NSString *)appSecret } NSString *fieldsHeader = [NSString stringWithFormat:@"headers=\"%@\"", fields]; - // putting it all together - NSString *authorizationHeader = [NSString stringWithFormat:@"Signature %@,%@,%@,%@", secretIdHeader, signatureHeader, algorithmHeader, fieldsHeader]; - + NSString *authorizationHeader = [NSString stringWithFormat:@"Signature %@,%@,%@,%@", + secretIdHeader, + signatureHeader, + algorithmHeader, + fieldsHeader]; [ADJAdjustFactory.logger debug:@"authorizationHeader %@", authorizationHeader]; - - return authorizationHeader; } @@ -753,20 +664,16 @@ + (NSDictionary *)buildSignatureParameters:(NSMutableDictionary *)parameters activityKindS:(NSString *)activityKindS { NSString *activityKindName = @"activity_kind"; NSString *activityKindValue = activityKindS; - NSString *createdAtName = @"created_at"; NSString *createdAtValue = [parameters objectForKey:createdAtName]; - NSString *deviceIdentifierName = [ADJUtil getValidIdentifier:parameters]; NSString *deviceIdentifierValue = [parameters objectForKey:deviceIdentifierName]; - NSMutableDictionary *signatureParameters = [[NSMutableDictionary alloc] initWithCapacity:4]; [ADJUtil checkAndAddEntry:signatureParameters key:@"app_secret" value:appSecret]; [ADJUtil checkAndAddEntry:signatureParameters key:createdAtName value:createdAtValue]; [ADJUtil checkAndAddEntry:signatureParameters key:activityKindName value:activityKindValue]; [ADJUtil checkAndAddEntry:signatureParameters key:deviceIdentifierName value:deviceIdentifierValue]; - return signatureParameters; } @@ -792,15 +699,12 @@ + (NSString *)getValidIdentifier:(NSMutableDictionary *)parameters { if ([parameters objectForKey:idfaName] != nil) { return idfaName; } - if ([parameters objectForKey:persistentUUIDName] != nil) { return persistentUUIDName; } - if ([parameters objectForKey:uuidName] != nil) { return uuidName; } - return nil; } @@ -810,7 +714,6 @@ + (void)sendNSURLSessionRequest:(NSMutableURLRequest *)request activityPackage:(ADJActivityPackage *)activityPackage responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { NSURLSession *session = [NSURLSession sessionWithConfiguration:[ADJUtil getUrlSessionConfiguration]]; - NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { @@ -820,10 +723,8 @@ + (void)sendNSURLSessionRequest:(NSMutableURLRequest *)request prefixErrorMessage:prefixErrorMessage suffixErrorMessage:suffixErrorMessage activityPackage:activityPackage]; - responseDataHandler(responseData); }]; - [task resume]; [session finishTasksAndInvalidate]; } @@ -835,21 +736,18 @@ + (void)sendNSURLConnectionRequest:(NSMutableURLRequest *)request responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { NSError *responseError = nil; NSHTTPURLResponse *urlResponse = nil; - #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&responseError]; #pragma clang diagnostic pop - ADJResponseData *responseData = [ADJUtil completionHandler:data response:(NSHTTPURLResponse *)urlResponse error:responseError prefixErrorMessage:prefixErrorMessage suffixErrorMessage:suffixErrorMessage activityPackage:activityPackage]; - responseDataHandler(responseData); } @@ -860,51 +758,41 @@ + (ADJResponseData *)completionHandler:(NSData *)data suffixErrorMessage:(NSString *)suffixErrorMessage activityPackage:(ADJActivityPackage *)activityPackage { ADJResponseData *responseData = [ADJResponseData buildResponseData:activityPackage]; - // Connection error if (responseError != nil) { NSString *errorMessage = [ADJUtil formatErrorMessage:prefixErrorMessage systemErrorMessage:responseError.localizedDescription suffixErrorMessage:suffixErrorMessage]; - [ADJAdjustFactory.logger error:errorMessage]; responseData.message = errorMessage; - return responseData; } - if ([ADJUtil isNull:data]) { NSString *errorMessage = [ADJUtil formatErrorMessage:prefixErrorMessage systemErrorMessage:@"empty error" suffixErrorMessage:suffixErrorMessage]; - [ADJAdjustFactory.logger error:errorMessage]; responseData.message = errorMessage; - return responseData; } NSString *responseString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] adjTrim]; NSInteger statusCode = urlResponse.statusCode; - [ADJAdjustFactory.logger verbose:@"Response: %@", responseString]; if (statusCode == 429) { [ADJAdjustFactory.logger error:@"Too frequent requests to the endpoint (429)"]; return responseData; } - [ADJUtil saveJsonResponse:data responseData:responseData]; - if ([ADJUtil isNull:responseData.jsonResponse]) { return responseData; } NSString *messageResponse = [responseData.jsonResponse objectForKey:@"message"]; - - responseData.message = messageResponse; - responseData.timeStamp = [responseData.jsonResponse objectForKey:@"timestamp"]; - responseData.adid = [responseData.jsonResponse objectForKey:@"adid"]; + responseData.message = messageResponse; + responseData.timeStamp = [responseData.jsonResponse objectForKey:@"timestamp"]; + responseData.adid = [responseData.jsonResponse objectForKey:@"adid"]; NSString *trackingState = [responseData.jsonResponse objectForKey:@"tracking_state"]; if (trackingState != nil) { @@ -912,28 +800,23 @@ + (ADJResponseData *)completionHandler:(NSData *)data responseData.trackingState = ADJTrackingStateOptedOut; } } - if (messageResponse == nil) { messageResponse = @"No message found"; } - if (statusCode == 200) { [ADJAdjustFactory.logger info:@"%@", messageResponse]; responseData.success = YES; } else { [ADJAdjustFactory.logger error:@"%@", messageResponse]; } - return responseData; } // Convert all values to strings, if value is dictionary -> recursive call + (NSDictionary *)convertDictionaryValues:(NSDictionary *)dictionary { NSMutableDictionary *convertedDictionary = [[NSMutableDictionary alloc] initWithCapacity:dictionary.count]; - for (NSString *key in dictionary) { id value = [dictionary objectForKey:key]; - if ([value isKindOfClass:[NSDictionary class]]) { // Dictionary value, recursive call NSDictionary *dictionaryValue = [ADJUtil convertDictionaryValues:(NSDictionary *)value]; @@ -950,7 +833,6 @@ + (NSDictionary *)convertDictionaryValues:(NSDictionary *)dictionary { [convertedDictionary setObject:stringValue forKey:key]; } } - return convertedDictionary; } @@ -961,7 +843,6 @@ + (NSString *)idfa { + (NSString *)getUpdateTime { NSDate *updateTime = nil; id logger = ADJAdjustFactory.logger; - @try { __autoreleasing NSError *error; NSString *infoPlistPath = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"]; @@ -969,23 +850,19 @@ + (NSString *)getUpdateTime { } @catch (NSException *exception) { [logger error:@"Error while trying to check update date. Exception: %@", exception]; } - return [ADJUtil formatDate:updateTime]; } + (NSString *)getInstallTime { id logger = ADJAdjustFactory.logger; - NSDate *installTime = nil; NSString *pathToCheck = nil; NSSearchPathDirectory folderToCheck = NSDocumentDirectory; #if TARGET_OS_TV folderToCheck = NSCachesDirectory; #endif - @try { NSArray *paths = NSSearchPathForDirectoriesInDomains(folderToCheck, NSUserDomainMask, YES); - if (paths.count > 0) { pathToCheck = [paths objectAtIndex:0]; } else { @@ -993,12 +870,10 @@ + (NSString *)getInstallTime { // Check app's bundle creation date instead. pathToCheck = [[NSBundle mainBundle] bundlePath]; } - installTime = [[NSFileManager defaultManager] attributesOfItemAtPath:pathToCheck error:nil][NSFileCreationDate]; } @catch (NSException *exception) { [logger error:@"Error while trying to check install date. Exception: %@", exception]; } - return [ADJUtil formatDate:installTime]; } @@ -1009,47 +884,38 @@ + (NSURL *)convertUniversalLink:(NSURL *)url scheme:(NSString *)scheme { [logger error:@"Received universal link is nil"]; return nil; } - if ([ADJUtil isNull:scheme] || [scheme length] == 0) { [logger warn:@"Non-empty scheme required, using the scheme \"AdjustUniversalScheme\""]; scheme = kDefaultScheme; } - NSString *urlString = [url absoluteString]; - if ([ADJUtil isNull:urlString]) { [logger error:@"Parsed universal link is nil"]; return nil; } - if (universalLinkRegex == nil) { [logger error:@"Universal link regex not correctly configured"]; return nil; } - if (shortUniversalLinkRegex == nil) { [logger error:@"Short Universal link regex not correctly configured"]; return nil; } NSArray *matches = [universalLinkRegex matchesInString:urlString options:0 range:NSMakeRange(0, [urlString length])]; - if ([matches count] == 0) { matches = [shortUniversalLinkRegex matchesInString:urlString options:0 range:NSMakeRange(0, [urlString length])]; - if ([matches count] == 0) { [logger error:@"Url doesn't match as universal link or short version"]; return nil; } } - if ([matches count] > 1) { [logger error:@"Url match as universal link multiple times"]; return nil; } NSTextCheckingResult *match = matches[0]; - if ([match numberOfRanges] != 2) { [logger error:@"Wrong number of ranges matched"]; return nil; @@ -1058,16 +924,12 @@ + (NSURL *)convertUniversalLink:(NSURL *)url scheme:(NSString *)scheme { NSString *tailSubString = [urlString substringWithRange:[match rangeAtIndex:1]]; NSString *finalTailSubString = [ADJUtil removeOptionalRedirect:tailSubString]; NSString *extractedUrlString = [NSString stringWithFormat:@"%@://%@", scheme, finalTailSubString]; - [logger info:@"Converted deeplink from universal link %@", extractedUrlString]; - NSURL *extractedUrl = [NSURL URLWithString:extractedUrlString]; - if ([ADJUtil isNull:extractedUrl]) { [logger error:@"Unable to parse converted deeplink from universal link %@", extractedUrlString]; return nil; } - return extractedUrl; } @@ -1078,16 +940,13 @@ + (NSString *)removeOptionalRedirect:(NSString *)tailSubString { [ADJAdjustFactory.logger error:@"Remove Optional Redirect regex not correctly configured"]; return tailSubString; } - NSArray *optionalRedirectmatches = [optionalRedirectRegex matchesInString:tailSubString options:0 range:NSMakeRange(0, [tailSubString length])]; - if ([optionalRedirectmatches count] == 0) { [logger debug:@"Universal link does not contain option adjust_redirect parameter"]; return tailSubString; } - if ([optionalRedirectmatches count] > 1) { [logger error:@"Universal link contains multiple option adjust_redirect parameters"]; return tailSubString; @@ -1095,38 +954,30 @@ + (NSString *)removeOptionalRedirect:(NSString *)tailSubString { NSTextCheckingResult *redirectMatch = optionalRedirectmatches[0]; NSRange redirectRange = [redirectMatch rangeAtIndex:0]; - NSString *beforeRedirect = [tailSubString substringToIndex:redirectRange.location]; NSString *afterRedirect = [tailSubString substringFromIndex:(redirectRange.location + redirectRange.length)]; - if (beforeRedirect.length > 0 && afterRedirect.length > 0) { NSString *lastCharacterBeforeRedirect = [beforeRedirect substringFromIndex:beforeRedirect.length - 1]; NSString *firstCharacterAfterRedirect = [afterRedirect substringToIndex:1]; - if ([@"&" isEqualToString:lastCharacterBeforeRedirect] && [@"&" isEqualToString:firstCharacterAfterRedirect]) { beforeRedirect = [beforeRedirect substringToIndex:beforeRedirect.length - 1]; } - if ([@"&" isEqualToString:lastCharacterBeforeRedirect] && [@"#" isEqualToString:firstCharacterAfterRedirect]) { beforeRedirect = [beforeRedirect substringToIndex:beforeRedirect.length - 1]; } - if ([@"?" isEqualToString:lastCharacterBeforeRedirect] && [@"#" isEqualToString:firstCharacterAfterRedirect]) { beforeRedirect = [beforeRedirect substringToIndex:beforeRedirect.length - 1]; } - if ([@"?" isEqualToString:lastCharacterBeforeRedirect] && [@"&" isEqualToString:firstCharacterAfterRedirect]) { afterRedirect = [afterRedirect substringFromIndex:1]; } - } NSString *removedRedirect = [NSString stringWithFormat:@"%@%@", beforeRedirect, afterRedirect]; - return removedRedirect; } @@ -1135,26 +986,21 @@ + (NSString *)secondsNumberFormat:(double)seconds { if (seconds < 0) { seconds = seconds * -1; } - if (secondsNumberFormatter == nil) { return nil; } - return [secondsNumberFormatter stringFromNumber:[NSNumber numberWithDouble:seconds]]; } + (double)randomInRange:(double)minRange maxRange:(double)maxRange { static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ srand48(arc4random()); }); - double random = drand48(); double range = maxRange - minRange; double scaled = random * range; double shifted = scaled + minRange; - return shifted; } @@ -1166,19 +1012,14 @@ + (NSTimeInterval)waitingTime:(NSInteger)retries // Start with base 0 NSInteger base = retries - backoffStrategy.minRetries; - // Get the exponential Time from the base: 1, 2, 4, 8, 16, ... * times the multiplier NSTimeInterval exponentialTime = pow(2.0, base) * backoffStrategy.secondMultiplier; - // Limit the maximum allowed time to wait NSTimeInterval ceilingTime = MIN(exponentialTime, backoffStrategy.maxWait); - // Add 1 to allow maximum value double randomRange = [ADJUtil randomInRange:backoffStrategy.minRange maxRange:backoffStrategy.maxRange]; - // Apply jitter factor NSTimeInterval waitingTime = ceilingTime * randomRange; - return waitingTime; } @@ -1222,12 +1063,10 @@ + (void)launchInMainThreadWithInactive:(isInactiveInjected)isInactiveblock { __block BOOL isInactive = [ADJUtil isInactive]; isInactiveblock(isInactive); }; - if ([ADJUtil isMainThread]) { block(); return; } - if (ADJAdjustFactory.testing) { [ADJAdjustFactory.logger debug:@"Launching in the background for testing"]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), block); @@ -1236,7 +1075,6 @@ + (void)launchInMainThreadWithInactive:(isInactiveInjected)isInactiveblock { } } - + (BOOL)isValidParameter:(NSString *)attribute attributeType:(NSString *)attributeType parameterName:(NSString *)parameterName { @@ -1244,12 +1082,10 @@ + (BOOL)isValidParameter:(NSString *)attribute [ADJAdjustFactory.logger error:@"%@ parameter %@ is missing", parameterName, attributeType]; return NO; } - if ([attribute isEqualToString:@""]) { [ADJAdjustFactory.logger error:@"%@ parameter %@ is empty", parameterName, attributeType]; return NO; } - return YES; } @@ -1259,24 +1095,19 @@ + (NSDictionary *)mergeParameters:(NSDictionary *)target if (target == nil) { return source; } - if (source == nil) { return target; } NSMutableDictionary *mergedParameters = [NSMutableDictionary dictionaryWithDictionary:target]; - [source enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { NSString *oldValue = [mergedParameters objectForKey:key]; - if (oldValue != nil) { [ADJAdjustFactory.logger warn:@"Key %@ with value %@ from %@ parameter was replaced by value %@", key, oldValue, parameterName, obj]; } - [mergedParameters setObject:obj forKey:key]; }]; - return (NSDictionary *)mergedParameters; } @@ -1287,14 +1118,11 @@ + (void)launchInQueue:(dispatch_queue_t)queue return; } __weak __typeof__(selfInject) weakSelf = selfInject; - dispatch_async(queue, ^{ __typeof__(selfInject) strongSelf = weakSelf; - if (strongSelf == nil) { return; } - block(strongSelf); }); } @@ -1302,31 +1130,25 @@ + (void)launchInQueue:(dispatch_queue_t)queue + (BOOL)deleteFileWithName:(NSString *)fileName { NSString *documentsFilePath = [ADJUtil getFilePathInDocumentsDir:fileName]; NSString *appSupportFilePath = [ADJUtil getFilePathInAppSupportDir:fileName]; - BOOL deletedDocumentsFilePath = [ADJUtil deleteFileInPath:documentsFilePath]; BOOL deletedAppSupportFilePath = [ADJUtil deleteFileInPath:appSupportFilePath]; - return deletedDocumentsFilePath || deletedAppSupportFilePath; } + (BOOL)deleteFileInPath:(NSString *)filePath { NSError *error; - if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) { // [[ADJAdjustFactory logger] verbose:@"File does not exist at path %@", filePath]; return YES; } BOOL deleted = [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]; - if (!deleted) { [[ADJAdjustFactory logger] verbose:@"Unable to delete file at path %@", filePath]; } - if (error) { [[ADJAdjustFactory logger] error:@"Error while deleting file at path %@", filePath]; } - return deleted; } @@ -1340,7 +1162,6 @@ + (void)launchDeepLinkMain:(NSURL *)deepLinkUrl { #pragma clang diagnostic ignored "-Wundeclared-selector" SEL openUrlSelector = @selector(openURL:options:completionHandler:); #pragma clang diagnostic pop - if ([sharedUIApplication respondsToSelector:openUrlSelector]) { /* [sharedUIApplication openURL:deepLinkUrl options:@{} completionHandler:^(BOOL success) { @@ -1349,20 +1170,16 @@ + (void)launchDeepLinkMain:(NSURL *)deepLinkUrl { } }]; */ - NSMethodSignature *methSig = [sharedUIApplication methodSignatureForSelector:openUrlSelector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methSig]; - [invocation setSelector: openUrlSelector]; [invocation setTarget: sharedUIApplication]; - NSDictionary *emptyDictionary = @{}; void (^completion)(BOOL) = ^(BOOL success) { if (!success) { [ADJAdjustFactory.logger error:@"Unable to open deep link (%@)", deepLinkUrl]; } }; - [invocation setArgument:&deepLinkUrl atIndex: 2]; [invocation setArgument:&emptyDictionary atIndex: 3]; [invocation setArgument:&completion atIndex: 4]; @@ -1372,7 +1189,6 @@ + (void)launchDeepLinkMain:(NSURL *)deepLinkUrl { #pragma clang diagnostic ignored "-Wdeprecated-declarations" BOOL success = [sharedUIApplication openURL:deepLinkUrl]; #pragma clang diagnostic pop - if (!success) { [ADJAdjustFactory.logger error:@"Unable to open deep link (%@)", deepLinkUrl]; } @@ -1392,7 +1208,6 @@ + (NSString *)convertDeviceToken:(NSData *)deviceToken { } deviceTokenString = [deviceTokenString stringByReplacingOccurrencesOfString:@" " withString:@""]; - return deviceTokenString; } @@ -1402,7 +1217,6 @@ + (BOOL)checkAttributionDetails:(NSDictionary *)attributionDetails { } NSDictionary *details = [attributionDetails objectForKey:@"Version3.1"]; - if ([ADJUtil isNull:details]) { return YES; } @@ -1416,7 +1230,6 @@ + (BOOL)checkAttributionDetails:(NSDictionary *)attributionDetails { [ADJAdjustFactory.logger debug:@"iAd attribution details has dummy common fields for both iAd3 and Apple Search Ads"]; return YES; } - // Apple Search Ads fields if ([ADJUtil contains:details key:@"iad-adgroup-id" value:@"1234567890"] && [ADJUtil contains:details key:@"iad-adgroup-name" value:@"AdgroupName"] && @@ -1424,7 +1237,6 @@ + (BOOL)checkAttributionDetails:(NSDictionary *)attributionDetails { [ADJAdjustFactory.logger debug:@"iAd attribution details has dummy Apple Search Ads fields"]; return NO; } - // iAd3 fields if ([ADJUtil contains:details key:@"iad-adgroup-id" value:@"1234567890"] && [ADJUtil contains:details key:@"iad-creative-name" value:@"CreativeName"]) { @@ -1439,11 +1251,9 @@ + (BOOL)contains:(NSDictionary *)dictionary key:(NSString *)key value:(NSString *)value { id readValue = [dictionary objectForKey:key]; - if ([ADJUtil isNull:readValue]) { return NO; } - return [value isEqualToString:[readValue description]]; } @@ -1451,7 +1261,6 @@ + (NSNumber *)readReachabilityFlags { if (reachability == nil) { return nil; } - return [reachability currentReachabilityFlags]; } @@ -1460,7 +1269,6 @@ + (NSString *)readMCC { if (carrier == nil) { return nil; } - return [carrier mobileCountryCode]; } @@ -1468,7 +1276,6 @@ + (NSString *)readMNC { if (carrier == nil) { return nil; } - return [carrier mobileNetworkCode]; } @@ -1476,18 +1283,14 @@ + (NSString *)readCurrentRadioAccessTechnology { if (networkInfo == nil) { return nil; } - SEL radioTechSelector = NSSelectorFromString(@"currentRadioAccessTechnology"); - if (![networkInfo respondsToSelector:radioTechSelector]) { return nil; } - #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" id radioTech = [networkInfo performSelector:radioTechSelector]; #pragma clang diagnostic pop - return radioTech; } #endif From 0f213f6610c512a2b6d5dd5cb48ec94503c115dc Mon Sep 17 00:00:00 2001 From: nonelse Date: Wed, 29 Aug 2018 17:12:42 +0200 Subject: [PATCH 20/27] Add callback id to web bridge --- AdjustBridge/AdjustBridge.m | 6 ++++++ AdjustBridge/AdjustBridgeRegister.m | 6 ++++++ .../AdjustExample-WebView/AdjustExample-WebView.html | 2 ++ 3 files changed, 14 insertions(+) diff --git a/AdjustBridge/AdjustBridge.m b/AdjustBridge/AdjustBridge.m index 97788a0bd..d2dfce8f5 100644 --- a/AdjustBridge/AdjustBridge.m +++ b/AdjustBridge/AdjustBridge.m @@ -73,6 +73,7 @@ - (void)adjustEventTrackingSucceeded:(ADJEventSuccess *)eventSuccessResponseData [dictionary setValue:eventSuccessResponseData.timeStamp forKey:@"timestamp"]; [dictionary setValue:eventSuccessResponseData.adid forKey:@"adid"]; [dictionary setValue:eventSuccessResponseData.eventToken forKey:@"eventToken"]; + [dictionary setValue:eventSuccessResponseData.callbackId forKey:@"callbackId"]; [dictionary setValue:eventSuccessResponseData.jsonResponse forKey:@"jsonResponse"]; self.eventSuccessCallback(dictionary); } @@ -88,6 +89,7 @@ - (void)adjustEventTrackingFailed:(ADJEventFailure *)eventFailureResponseData { [dictionary setValue:eventFailureResponseData.adid forKey:@"adid"]; [dictionary setValue:eventFailureResponseData.eventToken forKey:@"eventToken"]; [dictionary setValue:[NSNumber numberWithBool:eventFailureResponseData.willRetry] forKey:@"willRetry"]; + [dictionary setValue:eventFailureResponseData.callbackId forKey:@"callbackId"]; [dictionary setValue:eventFailureResponseData.jsonResponse forKey:@"jsonResponse"]; self.eventFailureCallback(dictionary); } @@ -306,6 +308,7 @@ - (void)loadWebViewBridge:(id)webView webViewDelegate:(id)webViewDelegate { NSString *transactionId = [data objectForKey:@"transactionId"]; id callbackParameters = [data objectForKey:@"callbackParameters"]; id partnerParameters = [data objectForKey:@"partnerParameters"]; + NSString *callbackId = [data objectForKey:@"callbackId"]; ADJEvent *adjustEvent = [ADJEvent eventWithEventToken:eventToken]; // No need to continue if adjust event is not valid @@ -330,6 +333,9 @@ - (void)loadWebViewBridge:(id)webView webViewDelegate:(id)webViewDelegate { NSString *value = [[partnerParameters objectAtIndex:(i + 1)] description]; [adjustEvent addPartnerParameter:key value:value]; } + if ([self isFieldValid:callbackId]) { + [adjustEvent setCallbackId:callbackId]; + } [Adjust trackEvent:adjustEvent]; }]; diff --git a/AdjustBridge/AdjustBridgeRegister.m b/AdjustBridge/AdjustBridgeRegister.m index 808a423af..3733fafda 100644 --- a/AdjustBridge/AdjustBridgeRegister.m +++ b/AdjustBridge/AdjustBridgeRegister.m @@ -215,6 +215,8 @@ + (NSString *)adjust_js { this.callbackParameters = []; this.partnerParameters = []; + + this.callbackId = null; }; AdjustEvent.prototype.addCallbackParameter = function(key, value) { @@ -236,6 +238,10 @@ + (NSString *)adjust_js { this.transactionId = transactionId; }; + AdjustEvent.prototype.setCallbackId = function(callbackId) { + this.callbackId = callbackId; + }; + // copied from adjust_config.js window.AdjustConfig = function (appToken, environment, legacy) { diff --git a/examples/AdjustExample-WebView/AdjustExample-WebView/AdjustExample-WebView.html b/examples/AdjustExample-WebView/AdjustExample-WebView/AdjustExample-WebView.html index 1e92c7fd9..e574eb5fb 100644 --- a/examples/AdjustExample-WebView/AdjustExample-WebView/AdjustExample-WebView.html +++ b/examples/AdjustExample-WebView/AdjustExample-WebView/AdjustExample-WebView.html @@ -43,6 +43,7 @@

Adjust Web View Demo

console.log('Message = ' + eventSuccess.message + '\n' + 'Timestamp = ' + eventSuccess.timestamp + '\n' + 'Adid = ' + eventSuccess.adid + '\n' + + 'CallbackId = ' + eventSuccess.callbackId + '\n' + 'Event token = ' + eventSuccess.eventToken) }) adjustConfig.setEventFailureCallback(function(eventFailure) { @@ -50,6 +51,7 @@

Adjust Web View Demo

'Timestamp = ' + eventFailure.timestamp + '\n' + 'Adid = ' + eventFailure.adid + '\n' + 'Event token = ' + eventFailure.eventToken + '\n' + + 'CallbackId = ' + eventSuccess.callbackId + '\n' + 'Will retry = ' + eventFailure.willRetry) }) adjustConfig.setSessionSuccessCallback(function(sessionSuccess) { From 37e0e27f59211673a4e974168ba7cf51b1e2fdba Mon Sep 17 00:00:00 2001 From: nonelse Date: Thu, 30 Aug 2018 09:53:33 +0200 Subject: [PATCH 21/27] Replace response callbacks with wvjb handlers --- AdjustBridge/AdjustBridge.m | 161 ++++++++++++++-------------- AdjustBridge/AdjustBridgeRegister.m | 50 +++++---- 2 files changed, 109 insertions(+), 102 deletions(-) diff --git a/AdjustBridge/AdjustBridge.m b/AdjustBridge/AdjustBridge.m index d2dfce8f5..b541d257a 100644 --- a/AdjustBridge/AdjustBridge.m +++ b/AdjustBridge/AdjustBridge.m @@ -19,15 +19,14 @@ @interface AdjustBridge() @property BOOL openDeferredDeeplink; -@property WVJBResponseCallback deeplinkCallback; -@property WVJBResponseCallback attributionCallback; -@property WVJBResponseCallback eventSuccessCallback; -@property WVJBResponseCallback eventFailureCallback; -@property WVJBResponseCallback sessionSuccessCallback; -@property WVJBResponseCallback sessionFailureCallback; -@property WVJBResponseCallback deferredDeeplinkCallback; @property (nonatomic, copy) NSString *fbPixelDefaultEventToken; @property (nonatomic, strong) NSMutableDictionary* fbPixelMapping; +@property (nonatomic, copy) NSString *attributionCallbackName; +@property (nonatomic, copy) NSString *eventSuccessCallbackName; +@property (nonatomic, copy) NSString *eventFailureCallbackName; +@property (nonatomic, copy) NSString *sessionSuccessCallbackName; +@property (nonatomic, copy) NSString *sessionFailureCallbackName; +@property (nonatomic, copy) NSString *deferredDeeplinkCallbackName; @end @@ -42,88 +41,84 @@ - (id)init { } _bridgeRegister = nil; - self.openDeferredDeeplink = YES; - self.attributionCallback = nil; - self.eventSuccessCallback = nil; - self.eventFailureCallback = nil; - self.sessionSuccessCallback = nil; - self.sessionFailureCallback = nil; - self.fbPixelDefaultEventToken = nil; - self.fbPixelMapping = nil; - return self; } #pragma mark - AdjustDelegate methods - (void)adjustAttributionChanged:(ADJAttribution *)attribution { - if (self.attributionCallback == nil) { + if (self.attributionCallbackName == nil) { return; } - self.attributionCallback([attribution dictionary]); + [self.bridgeRegister callHandler:self.attributionCallbackName data:[attribution dictionary]]; } - (void)adjustEventTrackingSucceeded:(ADJEventSuccess *)eventSuccessResponseData { - if (self.eventSuccessCallback == nil) { + if (self.eventSuccessCallbackName == nil) { return; } - NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; - [dictionary setValue:eventSuccessResponseData.message forKey:@"message"]; - [dictionary setValue:eventSuccessResponseData.timeStamp forKey:@"timestamp"]; - [dictionary setValue:eventSuccessResponseData.adid forKey:@"adid"]; - [dictionary setValue:eventSuccessResponseData.eventToken forKey:@"eventToken"]; - [dictionary setValue:eventSuccessResponseData.callbackId forKey:@"callbackId"]; - [dictionary setValue:eventSuccessResponseData.jsonResponse forKey:@"jsonResponse"]; - self.eventSuccessCallback(dictionary); + NSMutableDictionary *eventSuccessResponseDataDictionary = [NSMutableDictionary dictionary]; + [eventSuccessResponseDataDictionary setValue:eventSuccessResponseData.message forKey:@"message"]; + [eventSuccessResponseDataDictionary setValue:eventSuccessResponseData.timeStamp forKey:@"timestamp"]; + [eventSuccessResponseDataDictionary setValue:eventSuccessResponseData.adid forKey:@"adid"]; + [eventSuccessResponseDataDictionary setValue:eventSuccessResponseData.eventToken forKey:@"eventToken"]; + [eventSuccessResponseDataDictionary setValue:eventSuccessResponseData.callbackId forKey:@"callbackId"]; + [eventSuccessResponseDataDictionary setValue:eventSuccessResponseData.jsonResponse forKey:@"jsonResponse"]; + + [self.bridgeRegister callHandler:self.eventSuccessCallbackName data:eventSuccessResponseDataDictionary]; } - (void)adjustEventTrackingFailed:(ADJEventFailure *)eventFailureResponseData { - if (self.eventFailureCallback == nil) { + if (self.eventFailureCallbackName == nil) { return; } - NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; - [dictionary setValue:eventFailureResponseData.message forKey:@"message"]; - [dictionary setValue:eventFailureResponseData.timeStamp forKey:@"timestamp"]; - [dictionary setValue:eventFailureResponseData.adid forKey:@"adid"]; - [dictionary setValue:eventFailureResponseData.eventToken forKey:@"eventToken"]; - [dictionary setValue:[NSNumber numberWithBool:eventFailureResponseData.willRetry] forKey:@"willRetry"]; - [dictionary setValue:eventFailureResponseData.callbackId forKey:@"callbackId"]; - [dictionary setValue:eventFailureResponseData.jsonResponse forKey:@"jsonResponse"]; - self.eventFailureCallback(dictionary); + NSMutableDictionary *eventFailureResponseDataDictionary = [NSMutableDictionary dictionary]; + [eventFailureResponseDataDictionary setValue:eventFailureResponseData.message forKey:@"message"]; + [eventFailureResponseDataDictionary setValue:eventFailureResponseData.timeStamp forKey:@"timestamp"]; + [eventFailureResponseDataDictionary setValue:eventFailureResponseData.adid forKey:@"adid"]; + [eventFailureResponseDataDictionary setValue:eventFailureResponseData.eventToken forKey:@"eventToken"]; + [eventFailureResponseDataDictionary setValue:eventFailureResponseData.callbackId forKey:@"callbackId"]; + + [eventFailureResponseDataDictionary setValue:[NSNumber numberWithBool:eventFailureResponseData.willRetry] forKey:@"willRetry"]; + [eventFailureResponseDataDictionary setValue:eventFailureResponseData.jsonResponse forKey:@"jsonResponse"]; + + [self.bridgeRegister callHandler:self.eventFailureCallbackName data:eventFailureResponseDataDictionary]; } - (void)adjustSessionTrackingSucceeded:(ADJSessionSuccess *)sessionSuccessResponseData { - if (self.sessionSuccessCallback == nil) { + if (self.sessionSuccessCallbackName == nil) { return; } - NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; - [dictionary setValue:sessionSuccessResponseData.message forKey:@"message"]; - [dictionary setValue:sessionSuccessResponseData.timeStamp forKey:@"timestamp"]; - [dictionary setValue:sessionSuccessResponseData.adid forKey:@"adid"]; - [dictionary setValue:sessionSuccessResponseData.jsonResponse forKey:@"jsonResponse"]; - self.sessionSuccessCallback(dictionary); + NSMutableDictionary *sessionSuccessResponseDataDictionary = [NSMutableDictionary dictionary]; + [sessionSuccessResponseDataDictionary setValue:sessionSuccessResponseData.message forKey:@"message"]; + [sessionSuccessResponseDataDictionary setValue:sessionSuccessResponseData.timeStamp forKey:@"timestamp"]; + [sessionSuccessResponseDataDictionary setValue:sessionSuccessResponseData.adid forKey:@"adid"]; + [sessionSuccessResponseDataDictionary setValue:sessionSuccessResponseData.jsonResponse forKey:@"jsonResponse"]; + + [self.bridgeRegister callHandler:self.sessionSuccessCallbackName data:sessionSuccessResponseDataDictionary]; } - (void)adjustSessionTrackingFailed:(ADJSessionFailure *)sessionFailureResponseData { - if (self.sessionFailureCallback == nil) { + if (self.sessionFailureCallbackName == nil) { return; } - NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; - [dictionary setValue:sessionFailureResponseData.message forKey:@"message"]; - [dictionary setValue:sessionFailureResponseData.timeStamp forKey:@"timestamp"]; - [dictionary setValue:sessionFailureResponseData.adid forKey:@"adid"]; - [dictionary setValue:[NSNumber numberWithBool:sessionFailureResponseData.willRetry] forKey:@"willRetry"]; - [dictionary setValue:sessionFailureResponseData.jsonResponse forKey:@"jsonResponse"]; - self.sessionFailureCallback(dictionary); + NSMutableDictionary *sessionFailureResponseDataDictionary = [NSMutableDictionary dictionary]; + [sessionFailureResponseDataDictionary setValue:sessionFailureResponseData.message forKey:@"message"]; + [sessionFailureResponseDataDictionary setValue:sessionFailureResponseData.timeStamp forKey:@"timestamp"]; + [sessionFailureResponseDataDictionary setValue:sessionFailureResponseData.adid forKey:@"adid"]; + [sessionFailureResponseDataDictionary setValue:[NSNumber numberWithBool:sessionFailureResponseData.willRetry] forKey:@"willRetry"]; + [sessionFailureResponseDataDictionary setValue:sessionFailureResponseData.jsonResponse forKey:@"jsonResponse"]; + + [self.bridgeRegister callHandler:self.sessionFailureCallbackName data:sessionFailureResponseDataDictionary]; } - (BOOL)adjustDeeplinkResponse:(NSURL *)deeplink { - if (self.deferredDeeplinkCallback) { - self.deferredDeeplinkCallback([deeplink absoluteString]); + if (self.deferredDeeplinkCallbackName) { + [self.bridgeRegister callHandler:self.deferredDeeplinkCallbackName data:[deeplink absoluteString]]; } return self.openDeferredDeeplink; } @@ -181,27 +176,6 @@ - (void)loadWebViewBridge:(id)webView webViewDelegate:(id)webViewDelegate { _bridgeRegister = [[AdjustBridgeRegister alloc] initWithWebView:webView]; [self.bridgeRegister setWebViewDelegate:webViewDelegate]; - // Register setCallback method to save callbacks before appDidLaunch - [self.bridgeRegister registerHandler:@"adjust_setCallback" handler:^(id data, WVJBResponseCallback responseCallback) { - if (responseCallback == nil) { - return; - } - - if ([data isEqualToString:@"attributionCallback"]) { - self.attributionCallback = responseCallback; - } else if ([data isEqualToString:@"eventSuccessCallback"]) { - self.eventSuccessCallback = responseCallback; - } else if ([data isEqualToString:@"eventFailureCallback"]) { - self.eventFailureCallback = responseCallback; - } else if ([data isEqualToString:@"sessionSuccessCallback"]) { - self.sessionSuccessCallback = responseCallback; - } else if ([data isEqualToString:@"sessionFailureCallback"]) { - self.sessionFailureCallback = responseCallback; - } else if ([data isEqualToString:@"deferredDeeplinkCallback"]) { - self.deferredDeeplinkCallback = responseCallback; - } - }]; - [self.bridgeRegister registerHandler:@"adjust_appDidLaunch" handler:^(id data, WVJBResponseCallback responseCallback) { NSString *appToken = [data objectForKey:@"appToken"]; NSString *environment = [data objectForKey:@"environment"]; @@ -222,6 +196,12 @@ - (void)loadWebViewBridge:(id)webView webViewDelegate:(id)webViewDelegate { NSNumber *openDeferredDeeplink = [data objectForKey:@"openDeferredDeeplink"]; NSString *fbPixelDefaultEventToken = [data objectForKey:@"fbPixelDefaultEventToken"]; id fbPixelMapping = [data objectForKey:@"fbPixelMapping"]; + NSString * attributionCallback = [data objectForKey:@"attributionCallback"]; + NSString * eventSuccessCallback = [data objectForKey:@"eventSuccessCallback"]; + NSString * eventFailureCallback = [data objectForKey:@"eventFailureCallback"]; + NSString * sessionSuccessCallback = [data objectForKey:@"sessionSuccessCallback"]; + NSString * sessionFailureCallback = [data objectForKey:@"sessionFailureCallback"]; + NSString * deferredDeeplinkCallback = [data objectForKey:@"deferredDeeplinkCallback"]; ADJConfig *adjustConfig; if ([self isFieldValid:allowSuppressLogLevel]) { @@ -285,15 +265,34 @@ - (void)loadWebViewBridge:(id)webView webViewDelegate:(id)webViewDelegate { NSString *value = [[fbPixelMapping objectAtIndex:(i + 1)] description]; [self.fbPixelMapping setObject:value forKey:key]; } + if ([self isFieldValid:attributionCallback]) { + self.attributionCallbackName = attributionCallback; + } + if ([self isFieldValid:eventSuccessCallback]) { + self.eventSuccessCallbackName = eventSuccessCallback; + } + if ([self isFieldValid:eventFailureCallback]) { + self.eventFailureCallbackName = eventFailureCallback; + } + if ([self isFieldValid:sessionSuccessCallback]) { + self.sessionSuccessCallbackName = sessionSuccessCallback; + } + if ([self isFieldValid:sessionFailureCallback]) { + self.sessionFailureCallbackName = sessionFailureCallback; + } + if ([self isFieldValid:deferredDeeplinkCallback]) { + self.deferredDeeplinkCallbackName = deferredDeeplinkCallback; + } // Set self as delegate if any callback is configured. // Change to swifle the methods in the future. - if (self.attributionCallback != nil - || self.eventSuccessCallback != nil - || self.eventFailureCallback != nil - || self.sessionSuccessCallback != nil - || self.sessionFailureCallback != nil - || self.deferredDeeplinkCallback != nil) { + if (self.attributionCallbackName != nil + || self.eventSuccessCallbackName != nil + || self.eventFailureCallbackName != nil + || self.sessionSuccessCallbackName != nil + || self.sessionFailureCallbackName != nil + || self.deferredDeeplinkCallbackName != nil) + { [adjustConfig setDelegate:self]; } diff --git a/AdjustBridge/AdjustBridgeRegister.m b/AdjustBridge/AdjustBridgeRegister.m index 3733fafda..13b89921a 100644 --- a/AdjustBridge/AdjustBridgeRegister.m +++ b/AdjustBridge/AdjustBridgeRegister.m @@ -85,11 +85,7 @@ + (NSString *)adjust_js { appDidLaunch: function (adjustConfig) { if (WebViewJavascriptBridge) { if (adjustConfig) { - adjustConfig.iterateConfiguredCallbacks( - function(callbackName, callback) { - WebViewJavascriptBridge.callHandler('adjust_setCallback', callbackName, callback); - } - ); + adjustConfig.registerCallbackHandlers(); WebViewJavascriptBridge.callHandler('adjust_appDidLaunch', adjustConfig, null); } } @@ -277,9 +273,14 @@ + (NSString *)adjust_js { this.info3 = null; this.info4 = null; this.openDeferredDeeplink = null; - this.callbacksMap = {}; this.fbPixelDefaultEventToken = null; this.fbPixelMapping = []; + this.attributionCallback = null; + this.eventSuccessCallback = null; + this.eventFailureCallback = null; + this.sessionSuccessCallback = null; + this.sessionFailureCallback = null; + this.deferredDeeplinkCallback = null; }; AdjustConfig.EnvironmentSandbox = 'sandbox'; AdjustConfig.EnvironmentProduction = 'production'; @@ -292,15 +293,22 @@ + (NSString *)adjust_js { AdjustConfig.LogLevelAssert = 'ASSERT'; AdjustConfig.LogLevelSuppress = 'SUPPRESS'; - AdjustConfig.prototype.iterateConfiguredCallbacks = function(handleCallbackWithName) { - if (!this.callbacksMap) { - return; - } - var keysArray = Object.keys(this.callbacksMap); - for (var idx in keysArray) { - var key = keysArray[idx]; - handleCallbackWithName(key, this.callbacksMap[key]); - } + AdjustConfig.prototype.registerCallbackHandlers = function() { + var registerCallbackHandler = function (callbackName) { + var callback = this[callbackName]; + if (!callback) { + return; + } + var regiteredCallbackName = 'adjustJS_' + callbackName; + WebViewJavascriptBridge.registerHandler(regiteredCallbackName, callback); + this[callbackName] = regiteredCallbackName; + }; + registerCallbackHandler.call(this, 'attributionCallback'); + registerCallbackHandler.call(this, 'eventSuccessCallback'); + registerCallbackHandler.call(this, 'eventFailureCallback'); + registerCallbackHandler.call(this, 'sessionSuccessCallback'); + registerCallbackHandler.call(this, 'sessionFailureCallback'); + registerCallbackHandler.call(this, 'deferredDeeplinkCallback'); }; AdjustConfig.prototype.setSdkPrefix = function(sdkPrefix) { @@ -340,27 +348,27 @@ + (NSString *)adjust_js { }; AdjustConfig.prototype.setAttributionCallback = function(callback) { - this.callbacksMap['attributionCallback'] = callback; + this.attributionCallback = callback; }; AdjustConfig.prototype.setEventSuccessCallback = function(callback) { - this.callbacksMap['eventSuccessCallback'] = callback; + this.eventSuccessCallback = callback; }; AdjustConfig.prototype.setEventFailureCallback = function(callback) { - this.callbacksMap['eventFailureCallback'] = callback; + this.eventFailureCallback = callback; }; AdjustConfig.prototype.setSessionSuccessCallback = function(callback) { - this.callbacksMap['sessionSuccessCallback'] = callback; + this.sessionSuccessCallback = callback; }; AdjustConfig.prototype.setSessionFailureCallback = function(callback) { - this.callbacksMap['sessionFailureCallback'] = callback; + this.sessionFailureCallback = callback; }; AdjustConfig.prototype.setDeferredDeeplinkCallback = function(callback) { - this.callbacksMap['deferredDeeplinkCallback'] = callback; + this.deferredDeeplinkCallback = callback; }; AdjustConfig.prototype.setFbPixelDefaultEventToken = function(fbPixelDefaultEventToken) { From ba4f9e5d98d5e21cd92e0e23fbf79981f7989cc7 Mon Sep 17 00:00:00 2001 From: uerceg Date: Thu, 30 Aug 2018 12:03:29 +0200 Subject: [PATCH 22/27] New version 4.15.0 --- Adjust.podspec | 4 ++-- Adjust/ADJUtil.m | 2 +- Adjust/Adjust.h | 2 +- AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m | 2 +- AdjustTests/AdjustUnitTests/ADJPackageFields.m | 2 +- README.md | 4 ++-- VERSION | 2 +- doc/english/migrate.md | 2 +- doc/english/web_views.md | 2 +- doc/japanese/migrate_ja.md | 2 +- doc/migrate.md | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Adjust.podspec b/Adjust.podspec index 48ca88470..493637c38 100644 --- a/Adjust.podspec +++ b/Adjust.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = "Adjust" - s.version = "4.14.3" + s.version = "4.15.0" s.summary = "This is the iOS SDK of adjust. You can read more about it at http://adjust.com." s.homepage = "https://github.com/adjust/ios_sdk" s.license = { :type => 'MIT', :file => 'MIT-LICENSE' } s.author = { "Christian Wellenbrock" => "welle@adjust.com" } - s.source = { :git => "https://github.com/adjust/ios_sdk.git", :tag => "v4.14.3" } + s.source = { :git => "https://github.com/adjust/ios_sdk.git", :tag => "v4.15.0" } s.ios.deployment_target = '6.0' s.tvos.deployment_target = '9.0' s.framework = 'SystemConfiguration' diff --git a/Adjust/ADJUtil.m b/Adjust/ADJUtil.m index 60ae55a64..00a58f80a 100644 --- a/Adjust/ADJUtil.m +++ b/Adjust/ADJUtil.m @@ -39,7 +39,7 @@ static CTTelephonyNetworkInfo *networkInfo = nil; #endif -static NSString * const kClientSdk = @"ios4.14.3"; +static NSString * const kClientSdk = @"ios4.15.0"; static NSString * const kDeeplinkParam = @"deep_link="; static NSString * const kSchemeDelimiter = @"://"; static NSString * const kDefaultScheme = @"AdjustUniversalScheme"; diff --git a/Adjust/Adjust.h b/Adjust/Adjust.h index 5a453bc75..b7b20046d 100644 --- a/Adjust/Adjust.h +++ b/Adjust/Adjust.h @@ -2,7 +2,7 @@ // Adjust.h // Adjust // -// V4.14.3 +// V4.15.0 // Created by Christian Wellenbrock (wellle) on 23rd July 2013. // Copyright © 2012-2017 Adjust GmbH. All rights reserved. // diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m b/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m index e736de85c..58c65b45b 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m @@ -36,7 +36,7 @@ - (void)viewDidLoad { } - (void)startTestSession { - [self.testLibrary startTestSession:@"ios4.14.3"]; + [self.testLibrary startTestSession:@"ios4.15.0"]; } - (void)didReceiveMemoryWarning { diff --git a/AdjustTests/AdjustUnitTests/ADJPackageFields.m b/AdjustTests/AdjustUnitTests/ADJPackageFields.m index 3509cea9f..4bdd13b98 100644 --- a/AdjustTests/AdjustUnitTests/ADJPackageFields.m +++ b/AdjustTests/AdjustUnitTests/ADJPackageFields.m @@ -16,7 +16,7 @@ - (id) init { // default values self.appToken = @"qwerty123456"; - self.clientSdk = @"ios4.14.3"; + self.clientSdk = @"ios4.15.0"; self.suffix = @""; self.environment = @"sandbox"; diff --git a/README.md b/README.md index ec14b49fb..49954ba60 100644 --- a/README.md +++ b/README.md @@ -69,13 +69,13 @@ We will describe the steps to integrate the Adjust SDK into your iOS project. We If you're using [CocoaPods][cocoapods], you can add the following line to your `Podfile` and continue from [this step](#sdk-integrate): ```ruby -pod 'Adjust', '~> 4.14.3' +pod 'Adjust', '~> 4.15.0' ``` or: ```ruby -pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.14.3' +pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.15.0' ``` --- diff --git a/VERSION b/VERSION index 453b50f24..5c517bf11 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.14.3 +4.15.0 diff --git a/doc/english/migrate.md b/doc/english/migrate.md index 2c7853625..32d8245f8 100644 --- a/doc/english/migrate.md +++ b/doc/english/migrate.md @@ -1,4 +1,4 @@ -## Migrate your adjust SDK for iOS to v4.14.3 from v3.4.0 +## Migrate your adjust SDK for iOS to v4.15.0 from v3.4.0 ### Initial setup diff --git a/doc/english/web_views.md b/doc/english/web_views.md index 82e9d3f8e..a764c000b 100644 --- a/doc/english/web_views.md +++ b/doc/english/web_views.md @@ -63,7 +63,7 @@ We will describe the steps to integrate the Adjust SDK into your iOS project. We If you're using [CocoaPods][cocoapods], you can add the following line to your `Podfile` and continue from [this step](#sdk-integrate): ```ruby -pod 'Adjust/WebBridge', '~> 4.14.3' +pod 'Adjust/WebBridge', '~> 4.15.0' ``` --- diff --git a/doc/japanese/migrate_ja.md b/doc/japanese/migrate_ja.md index 667864622..f828663f4 100644 --- a/doc/japanese/migrate_ja.md +++ b/doc/japanese/migrate_ja.md @@ -1,4 +1,4 @@ -## iOS用adjust SDKのv3.4.0からv4.14.3への移行 +## iOS用adjust SDKのv3.4.0からv4.15.0への移行 ### 初期設定 diff --git a/doc/migrate.md b/doc/migrate.md index 2c7853625..32d8245f8 100644 --- a/doc/migrate.md +++ b/doc/migrate.md @@ -1,4 +1,4 @@ -## Migrate your adjust SDK for iOS to v4.14.3 from v3.4.0 +## Migrate your adjust SDK for iOS to v4.15.0 from v3.4.0 ### Initial setup From 0303acac7363e7b3a15f71466bfdaea069b48e0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uglje=C5=A1a=20Erceg?= Date: Thu, 30 Aug 2018 12:05:42 +0200 Subject: [PATCH 23/27] Update CHANGELOG.md --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b46d80dbc..d7599ea8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +### Version 4.15.0 (30th August 2018) +#### Added +- Added `setCallbackId` method on `ADJEvent` object for users to set custom ID on event object which will later be reported in event success/failure callbacks. +- Added `callbackId` property to `ADJEventSuccess` class. +- Added `callbackId` property to `ADJEventFailure` class. +- Added support for tracking Facebook Pixel events with iOS web view SDK. +- Aligned feature set of iOS web view SDK with native iOS SDK. +- Added example app which demonstrates how iOS web view SDK can be used to track Facebook Pixel events. + +#### Changed +- SDK will now fire attribution request each time upon session tracking finished in case it lacks attribution info. + +--- + ### Version 4.14.3 (16th August 2018) #### Changed - Changed deployment target of iMessage dynamic framework target back to 8.0. From b7560ebbe5e9d69e60ba880a17291a39f7d43cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uglje=C5=A1a=20Erceg?= Date: Thu, 30 Aug 2018 12:07:46 +0200 Subject: [PATCH 24/27] Update README.md --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 49954ba60..fd1947dc9 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ If your app is an app which uses web views you would like to use adjust tracking * [In-App Purchase verification](#iap-verification) * [Callback parameters](#callback-parameters) * [Partner parameters](#partner-parameters) + * [Callback identifier](#callback-id) * [Session parameters](#session-parameters) * [Session callback parameters](#session-callback-parameters) * [Session partner parameters](#session-partner-parameters) @@ -373,6 +374,19 @@ ADJEvent *event = [ADJEvent eventWithEventToken:@"abc123"]; You can read more about special partners and these integrations in our [guide to special partners][special-partners]. +### Callback identifier + +You can also add custom string identifier to each event you want to track. This identifier will later be reported in event success and/or event failure callbacks to enable you to keep track on which event was successfully tracked or not. You can set this identifier by calling the `setCallbackId` method on your `ADJEvent` instance: + + +```objc +ADJEvent *event = [ADJEvent eventWithEventToken:@"abc123"]; + +[event setCallbackId:@"Your-Custom-Id"]; + +[Adjust trackEvent:event]; +``` + ### Session parameters Some parameters are saved to be sent in every event and session of the Adjust SDK. Once you have added any of these parameters, you don't need to add them every time, since they will be saved locally. If you add the same parameter twice, there will be no effect. @@ -525,6 +539,7 @@ The delegate functions will be called after the SDK tries to send a package to t Both event response data objects contain: - `NSString eventToken` the event token, if the package tracked was an event. +- `NSString callbackid` the custom defined callback ID set on event object. If any value is unavailable, it will default to `nil`. From 8d97f6032b95a19e48daa489151132b7665ce5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uglje=C5=A1a=20Erceg?= Date: Thu, 30 Aug 2018 19:53:01 +0200 Subject: [PATCH 25/27] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7599ea8b..e37ff8e07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### Version 4.15.0 (30th August 2018) +### Version 4.15.0 (31st August 2018) #### Added - Added `setCallbackId` method on `ADJEvent` object for users to set custom ID on event object which will later be reported in event success/failure callbacks. - Added `callbackId` property to `ADJEventSuccess` class. From b31335826a1a0af8d9c96e63b0848be1ce385a3d Mon Sep 17 00:00:00 2001 From: nonelse Date: Fri, 31 Aug 2018 11:31:41 +0200 Subject: [PATCH 26/27] Add more new version 4.15.0 --- AdjustBridge/AdjustBridgeRegister.m | 2 +- doc/english/web_view_migration.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AdjustBridge/AdjustBridgeRegister.m b/AdjustBridge/AdjustBridgeRegister.m index 13b89921a..212865914 100644 --- a/AdjustBridge/AdjustBridgeRegister.m +++ b/AdjustBridge/AdjustBridgeRegister.m @@ -259,7 +259,7 @@ + (NSString *)adjust_js { } } - this.sdkPrefix = 'web-bridge4.14.0'; + this.sdkPrefix = 'web-bridge4.15.0'; this.defaultTracker = null; this.logLevel = null; this.eventBufferingEnabled = null; diff --git a/doc/english/web_view_migration.md b/doc/english/web_view_migration.md index 6036f5005..60670554b 100644 --- a/doc/english/web_view_migration.md +++ b/doc/english/web_view_migration.md @@ -1,4 +1,4 @@ -## Migrate your Adjust web bridge SDK to v4.14.0 or later from v4.9.1 or earlier +## Migrate your Adjust web bridge SDK to v4.15.0 or later from v4.9.1 or earlier ### Integration From c0aa59c64da4816d333bf64f42edc1d4af435e7c Mon Sep 17 00:00:00 2001 From: Pedro Filipe Date: Fri, 31 Aug 2018 11:39:40 +0200 Subject: [PATCH 27/27] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e37ff8e07..acd387ce3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ #### Changed - SDK will now fire attribution request each time upon session tracking finished in case it lacks attribution info. +#### Fixed +- Web bridge callbacks can now be called more than once + --- ### Version 4.14.3 (16th August 2018)