diff --git a/Analytics.xcodeproj/project.pbxproj b/Analytics.xcodeproj/project.pbxproj index af5671a13..e75b482f1 100644 --- a/Analytics.xcodeproj/project.pbxproj +++ b/Analytics.xcodeproj/project.pbxproj @@ -218,6 +218,13 @@ 6E165A1A1B54771A002C1C40 /* GAITrackedViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E165A101B54771A002C1C40 /* GAITrackedViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E165A1B1B54771A002C1C40 /* GAITracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E165A111B54771A002C1C40 /* GAITracker.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E16FFF81B33AD3400B4F7FE /* SEGFlurryIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E16FFF71B33AD3400B4F7FE /* SEGFlurryIntegrationTests.m */; }; + 6E2AFA3E1B55850C00C8A14E /* MOEHelperConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E2AFA3C1B55850C00C8A14E /* MOEHelperConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6E2AFA3F1B55850C00C8A14E /* MoEngage.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E2AFA3D1B55850C00C8A14E /* MoEngage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6E2AFA421B55852400C8A14E /* MOInbox.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E2AFA401B55852400C8A14E /* MOInbox.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6E2AFA431B55852400C8A14E /* MOInboxViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E2AFA411B55852400C8A14E /* MOInboxViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6E2AFA4B1B55863400C8A14E /* SEGMoEngageIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E2AFA491B55863400C8A14E /* SEGMoEngageIntegration.h */; }; + 6E2AFA4C1B55863400C8A14E /* SEGMoEngageIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E2AFA4A1B55863400C8A14E /* SEGMoEngageIntegration.m */; }; + 6E2AFA4D1B55863400C8A14E /* SEGMoEngageIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E2AFA4A1B55863400C8A14E /* SEGMoEngageIntegration.m */; }; 6E51469A1B3B573600F8F87C /* SEGBugsnagIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E5146991B3B573600F8F87C /* SEGBugsnagIntegrationTests.m */; }; 6E5EF3D31B1005FB001A4BA4 /* CrittercismConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E5EF3D21B1005FB001A4BA4 /* CrittercismConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E5EF3D51B10063E001A4BA4 /* OptimizelyExperimentData.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E5EF3D41B10063E001A4BA4 /* OptimizelyExperimentData.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -519,6 +526,12 @@ 6E165A101B54771A002C1C40 /* GAITrackedViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GAITrackedViewController.h; path = Pods/GoogleAnalytics/Headers/Public/GAITrackedViewController.h; sourceTree = ""; }; 6E165A111B54771A002C1C40 /* GAITracker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GAITracker.h; path = Pods/GoogleAnalytics/Headers/Public/GAITracker.h; sourceTree = ""; }; 6E16FFF71B33AD3400B4F7FE /* SEGFlurryIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SEGFlurryIntegrationTests.m; sourceTree = ""; }; + 6E2AFA3C1B55850C00C8A14E /* MOEHelperConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MOEHelperConstants.h; path = "Pods/MoEngage-iOS-SDK/Headers/MOEHelperConstants.h"; sourceTree = ""; }; + 6E2AFA3D1B55850C00C8A14E /* MoEngage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MoEngage.h; path = "Pods/MoEngage-iOS-SDK/Headers/MoEngage.h"; sourceTree = ""; }; + 6E2AFA401B55852400C8A14E /* MOInbox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MOInbox.h; path = "Pods/MoEngage-iOS-SDK/Headers/MOInbox.h"; sourceTree = ""; }; + 6E2AFA411B55852400C8A14E /* MOInboxViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MOInboxViewController.h; path = "Pods/MoEngage-iOS-SDK/Headers/MOInboxViewController.h"; sourceTree = ""; }; + 6E2AFA491B55863400C8A14E /* SEGMoEngageIntegration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SEGMoEngageIntegration.h; path = MoEngage/SEGMoEngageIntegration.h; sourceTree = ""; }; + 6E2AFA4A1B55863400C8A14E /* SEGMoEngageIntegration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SEGMoEngageIntegration.m; path = MoEngage/SEGMoEngageIntegration.m; sourceTree = ""; }; 6E5146991B3B573600F8F87C /* SEGBugsnagIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SEGBugsnagIntegrationTests.m; path = Integrations/Bugsnag/SEGBugsnagIntegrationTests.m; sourceTree = ""; }; 6E5EF3D21B1005FB001A4BA4 /* CrittercismConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CrittercismConfig.h; path = Pods/CrittercismSDK/CrittercismSDK/CrittercismConfig.h; sourceTree = ""; }; 6E5EF3D41B10063E001A4BA4 /* OptimizelyExperimentData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptimizelyExperimentData.h; path = "Pods/Optimizely-iOS-SDK/Optimizely.framework/Headers/OptimizelyExperimentData.h"; sourceTree = ""; }; @@ -787,6 +800,15 @@ name = Flurry; sourceTree = ""; }; + 6E2AFA371B55841900C8A14E /* MoEngage */ = { + isa = PBXGroup; + children = ( + 6E2AFA491B55863400C8A14E /* SEGMoEngageIntegration.h */, + 6E2AFA4A1B55863400C8A14E /* SEGMoEngageIntegration.m */, + ); + name = MoEngage; + sourceTree = ""; + }; 6E5146981B3B571D00F8F87C /* Bugsnag */ = { isa = PBXGroup; children = ( @@ -872,6 +894,10 @@ D3D35174186242B4005586E7 /* Headers */ = { isa = PBXGroup; children = ( + 6E2AFA401B55852400C8A14E /* MOInbox.h */, + 6E2AFA411B55852400C8A14E /* MOInboxViewController.h */, + 6E2AFA3C1B55850C00C8A14E /* MOEHelperConstants.h */, + 6E2AFA3D1B55850C00C8A14E /* MoEngage.h */, 6E165A081B54771A002C1C40 /* GAI.h */, 6E165A091B54771A002C1C40 /* GAIDictionaryBuilder.h */, 6E165A0A1B54771A002C1C40 /* GAIEcommerceFields.h */, @@ -1100,6 +1126,7 @@ 32F638181A81348700C65643 /* Kahuna */, D3EDB64A18C315F100A88A7E /* Localytics */, D3EDB64D18C315F100A88A7E /* Mixpanel */, + 6E2AFA371B55841900C8A14E /* MoEngage */, 32A69C1F1979CF4A00D69943 /* Optimizely */, 32A8C60419107DBD00173AE5 /* Quantcast */, D3EDB65018C315F100A88A7E /* Segmentio */, @@ -1371,8 +1398,12 @@ 6E5EF3D31B1005FB001A4BA4 /* CrittercismConfig.h in Headers */, D331BCF2185BFF49007CB22F /* CRFilter.h in Headers */, D331BCF3185BFF4A007CB22F /* CrittercismDelegate.h in Headers */, + 6E2AFA421B55852400C8A14E /* MOInbox.h in Headers */, + 6E2AFA431B55852400C8A14E /* MOInboxViewController.h in Headers */, D3EDB65818C315F100A88A7E /* SEGBugsnagIntegration.h in Headers */, D371F330185942C90053337D /* Flurry.h in Headers */, + 6E2AFA3E1B55850C00C8A14E /* MOEHelperConstants.h in Headers */, + 6E2AFA3F1B55850C00C8A14E /* MoEngage.h in Headers */, D3EDB65E18C315F100A88A7E /* SEGFlurryIntegration.h in Headers */, 32DF327A194666DA004098C1 /* SEGTaplyticsIntegration.h in Headers */, D3EDB66418C315F100A88A7E /* SEGMixpanelIntegration.h in Headers */, @@ -1387,6 +1418,7 @@ D331BD2E1860F5F0007CB22F /* TSCore.h in Headers */, 32430A7919145DA8004EFF59 /* SEGAnalyticsIntegrations.h in Headers */, 32AD185919AFCA100047D5F0 /* MPABTestDesignerChangeRequestMessage.h in Headers */, + 6E2AFA4B1B55863400C8A14E /* SEGMoEngageIntegration.h in Headers */, 32AD185A19AFCA100047D5F0 /* MPABTestDesignerChangeResponseMessage.h in Headers */, 32AD185B19AFCA100047D5F0 /* MPABTestDesignerClearRequestMessage.h in Headers */, 32AD185C19AFCA100047D5F0 /* MPABTestDesignerClearResponseMessage.h in Headers */, @@ -1764,6 +1796,7 @@ 3242C9BA1946AFD900FBE441 /* SEGGoogleAnalyticsIntegration.m in Sources */, 3242C9B91946AFD400FBE441 /* SEGFlurryIntegration.m in Sources */, 6EFAD9AE1B41A97C000664C1 /* SEGTaplyticsIntegrationTests.m in Sources */, + 6E2AFA4D1B55863400C8A14E /* SEGMoEngageIntegration.m in Sources */, 6EB2963E1B4C3B2F00805337 /* SEGTapstreamIntegrationTests.m in Sources */, 32CFF3D019AE5BCF00193D3D /* SEGAppsFlyerIntegration.m in Sources */, DAEB6FF31AC9EBCA003E7FB3 /* SEGApptimizeIntegration.m in Sources */, @@ -1810,6 +1843,7 @@ D3EDB66718C315F100A88A7E /* SEGSegmentioIntegration.m in Sources */, D3EDB65D18C315F100A88A7E /* SEGCrittercismIntegration.m in Sources */, 32E2811F1908420D00FB48D7 /* SEGBluetooth.m in Sources */, + 6E2AFA4C1B55863400C8A14E /* SEGMoEngageIntegration.m in Sources */, EAA604CA17C28C7C00911919 /* SEGAnalyticsRequest.m in Sources */, EA65F96717C2ABA600389A1A /* SEGAnalyticsIntegration.m in Sources */, 32225232199AD6D200478B1A /* SEGReachability.m in Sources */, diff --git a/Analytics/Integrations/MoEngage/SEGMoEngageIntegration.h b/Analytics/Integrations/MoEngage/SEGMoEngageIntegration.h new file mode 100644 index 000000000..6bb07fc86 --- /dev/null +++ b/Analytics/Integrations/MoEngage/SEGMoEngageIntegration.h @@ -0,0 +1,29 @@ +// +// SEGMoEngageIntegration.h +// Analytics +// +// Created by Gautam on 28/05/15. +// Copyright (c) 2015 Segment.io. All rights reserved. +// + +#import "SEGAnalyticsIntegration.h" + + +@interface SEGMoEngageIntegration : SEGAnalyticsIntegration + +@property (nonatomic, copy) NSString *name; +@property (nonatomic, assign) BOOL valid; +@property (nonatomic, assign) BOOL initialized; +@property (nonatomic, copy) NSDictionary *settings; + +@end + + +@interface SEGMoEngagePushManager : NSObject + +@property (nonatomic) NSDictionary *pushInfoDict; +@property (nonatomic) BOOL moengageInitialized; + ++ (instancetype)sharedInstance; + +@end diff --git a/Analytics/Integrations/MoEngage/SEGMoEngageIntegration.m b/Analytics/Integrations/MoEngage/SEGMoEngageIntegration.m new file mode 100644 index 000000000..a4fc64070 --- /dev/null +++ b/Analytics/Integrations/MoEngage/SEGMoEngageIntegration.m @@ -0,0 +1,292 @@ +// +// SEGMoEngageIntegration.m +// Analytics +// +// Created by Gautam on 28/05/15. +// Copyright (c) 2015 Segment.io. All rights reserved. +// + +#import "SEGMoEngageIntegration.h" +#import "SEGAnalyticsUtils.h" +#import "SEGAnalytics.h" +#import "MoEngage.h" +#import "MOEHelperConstants.h" +#import + +// Selectors that we are going to swizzle in this wrapper. +void (*selOriginalApplicationDidFailToRegisterForRemoteNotificationsWithError)(id, SEL, id, id); +void (*selOriginalApplicationDidReceiveRemoteNotification)(id, SEL, id, id); + + +@implementation SEGMoEngageIntegration +@synthesize name, valid, initialized, settings; + +- (instancetype)init +{ + if (self = [super init]) { + self.name = @"MoEngage"; + self.valid = NO; + self.initialized = NO; + } + return self; +} + ++ (void)load +{ + [SEGAnalytics registerIntegration:self withIdentifier:@"MoEngage"]; +} + +- (void)start +{ + NSString *apiKey = [self.settings objectForKey:@"apiKey"]; + if (!apiKey.length) { + SEGLog(@"MoEngage-Segment - api key not present"); + return; + } + + // We just need one call to initialize. The "start" method is called + // everytime the app comes to foreground. + if ([SEGMoEngagePushManager sharedInstance].moengageInitialized == NO) { + [[MoEngage sharedInstance] initializeWithApiKey:apiKey inApplication:[UIApplication sharedApplication] withLaunchOptions:[SEGMoEngagePushManager sharedInstance].pushInfoDict]; + + // If we have recorded any push user info, then + if ([SEGMoEngagePushManager sharedInstance].pushInfoDict != nil) { + [[MoEngage sharedInstance] didReceieveNotificationinApplication:[UIApplication sharedApplication] withInfo:[SEGMoEngagePushManager sharedInstance].pushInfoDict]; + [SEGMoEngagePushManager sharedInstance].pushInfoDict = nil; + } + + [SEGMoEngagePushManager sharedInstance].moengageInitialized = TRUE; + SEGLog(@"MoEngage-Segment - initialized."); + } + + // When this class loads we will register for the 'UIApplicationDidFinishLaunchingNotification' notification. + // To receive the notification we will use the SEGMoEngagePushManager singleton instance. + [[NSNotificationCenter defaultCenter] addObserver:[SEGMoEngagePushManager sharedInstance] + selector:@selector(didFinishLaunching:) + name:UIApplicationDidFinishLaunchingNotification + object:nil]; + [super start]; +} + +- (void)validate +{ + self.valid = [self.settings objectForKey:@"apiKey"] != nil; +} + +- (void)flush +{ + [[MoEngage sharedInstance] syncNow]; +} + +- (void)registerForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken options:(NSDictionary *)options +{ + [[MoEngage sharedInstance] registerForPush:deviceToken]; +} + +- (void)reset +{ + [[MoEngage sharedInstance] resetUser]; +} + +#pragma mark - Event and user tracking + +- (void)track:(NSString *)event properties:(NSDictionary *)properties options:(NSDictionary *)options +{ + [[MoEngage sharedInstance] trackEvent:event andPayload:[NSMutableDictionary dictionaryWithDictionary:properties]]; +} + +- (void)identify:(NSString *)userId traits:(NSDictionary *)traits options:(NSDictionary *)options +{ + if (!userId) { + NSLog(@"MoEngage-Segment - calling identify without any userId"); + } + [self setAttributes:traits]; +} + +- (void)setAttributes:(NSDictionary *)traits +{ + if ([traits objectForKey:@"id"]) { + [[MoEngage sharedInstance] setUserAttribute:[traits objectForKey:@"id"] forKey:USER_ATTRIBUTE_UNIQUE_ID]; + } + + if ([traits objectForKey:@"email"]) { + [[MoEngage sharedInstance] setUserAttribute:[traits objectForKey:@"email"] forKey:USER_ATTRIBUTE_USER_EMAIL]; + } + + if ([traits objectForKey:@"name"]) { + [[MoEngage sharedInstance] setUserAttribute:[traits objectForKey:@"username"] forKey:USER_ATTRIBUTE_USER_NAME]; + } + + if ([traits objectForKey:@"phone"]) { + [[MoEngage sharedInstance] setUserAttribute:[traits objectForKey:@"phone"] forKey:USER_ATTRIBUTE_USER_MOBILE]; + } + + if ([traits objectForKey:@"firstName"]) { + [[MoEngage sharedInstance] setUserAttribute:[traits objectForKey:@"firstName"] forKey:USER_ATTRIBUTE_USER_FIRST_NAME]; + } + + if ([traits objectForKey:@"lastName"]) { + [[MoEngage sharedInstance] setUserAttribute:[traits objectForKey:@"lastName"] forKey:USER_ATTRIBUTE_USER_LAST_NAME]; + } + + if ([traits objectForKey:@"gender"]) { + [[MoEngage sharedInstance] setUserAttribute:[traits objectForKey:@"gender"] forKey:USER_ATTRIBUTE_USER_GENDER]; + } + + if ([traits objectForKey:@"birthday"]) { + [[MoEngage sharedInstance] setUserAttribute:[traits objectForKey:@"birthday"] forKey:USER_ATTRIBUTE_USER_BDAY]; + } + + if ([traits objectForKey:@"address"]) { + [[MoEngage sharedInstance] setUserAttribute:[traits objectForKey:@"address"] forKey:@"address"]; + } + + if ([traits objectForKey:@"age"]) { + [[MoEngage sharedInstance] setUserAttribute:[traits objectForKey:@"age"] forKey:@"age"]; + } +} + +#pragma mark - App state changes + +- (void)applicationDidBecomeActive +{ + [[MoEngage sharedInstance] applicationBecameActiveinApplication:[UIApplication sharedApplication]]; +} + +- (void)applicationDidEnterBackground +{ + [[MoEngage sharedInstance] stop:[UIApplication sharedApplication]]; +} + +- (void)applicationWillTerminate +{ + [[MoEngage sharedInstance] applicationTerminated:[UIApplication sharedApplication]]; +} + +@end + +#pragma mark - Push Manager + + +@implementation SEGMoEngagePushManager + ++ (instancetype)sharedInstance +{ + static SEGMoEngagePushManager *instance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[SEGMoEngagePushManager alloc] init]; + }); + return instance; +} + +- (void)didFinishLaunching:(NSNotification *)notificationPayload +{ + NSDictionary *userInfo = notificationPayload.userInfo; + if ([userInfo valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey]) { + NSDictionary *remoteNotification = [userInfo valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; + [SEGMoEngagePushManager sharedInstance].pushInfoDict = remoteNotification; + } + + // We will also swizzle the app delegate methods now. We need this so that we can intercept the registration for device token + // and a push being received when the app is in foreground or background. + [self swizzleAppDelegateMethods]; +} + +#pragma mark - App Delegate Methods Swizzling +// App Delegate methods that deal with push notifications need to be swizzled here. That way this class will receive the delegate callbacks +// and access the necesary details from each callback. +- (void)swizzleAppDelegateMethods +{ + @try { + SEL selector = @selector(application:didFailToRegisterForRemoteNotificationsWithError:); + if ([[UIApplication sharedApplication].delegate respondsToSelector:selector]) { + selOriginalApplicationDidFailToRegisterForRemoteNotificationsWithError = (void (*)(id, SEL, id, id))[[[UIApplication sharedApplication].delegate class] instanceMethodForSelector:selector]; + } else { + Method methodSegmentWrapper = class_getInstanceMethod([self class], selector); + const char *methodTypeEncoding = method_getTypeEncoding(methodSegmentWrapper); + + IMP implementationSegmentWrapper = class_getMethodImplementation([self class], selector); + class_addMethod([[UIApplication sharedApplication].delegate class], selector, implementationSegmentWrapper, methodTypeEncoding); + } + + selector = @selector(application:didReceiveRemoteNotification:); + if ([[UIApplication sharedApplication].delegate respondsToSelector:selector]) { + selOriginalApplicationDidReceiveRemoteNotification = (void (*)(id, SEL, id, id))[[[UIApplication sharedApplication].delegate class] instanceMethodForSelector:selector]; + } else { + Method methodSegmentWrapper = class_getInstanceMethod([self class], selector); + const char *methodTypeEncoding = method_getTypeEncoding(methodSegmentWrapper); + + IMP implementationSegmentWrapper = class_getMethodImplementation([self class], selector); + class_addMethod([[UIApplication sharedApplication].delegate class], selector, implementationSegmentWrapper, methodTypeEncoding); + } + + // Swizzle the methods only if we got the original Application selector. Otherwise no point doing the swizzling. + Method newMethod = nil; + Method originalMethod = nil; + + // Swizzling didFailToRegisterForRemoteNotificationsWithError + if (selOriginalApplicationDidFailToRegisterForRemoteNotificationsWithError) { + newMethod = class_getInstanceMethod([self class], @selector(application:didFailToRegisterForRemoteNotificationsWithError:)); + originalMethod = class_getInstanceMethod([[UIApplication sharedApplication].delegate class], @selector(application:didFailToRegisterForRemoteNotificationsWithError:)); + method_exchangeImplementations(newMethod, originalMethod); + } + + // Swizzling didReceiveRemoteNotification + if (selOriginalApplicationDidReceiveRemoteNotification) { + newMethod = class_getInstanceMethod([self class], @selector(application:didReceiveRemoteNotification:)); + originalMethod = class_getInstanceMethod([[UIApplication sharedApplication].delegate class], @selector(application:didReceiveRemoteNotification:)); + method_exchangeImplementations(newMethod, originalMethod); + } + } + @catch (NSException *exception) { + NSLog(@"MoEngage-Segment Exception : %@", exception.description); + } +} + +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error +{ + @try { + if ([SEGMoEngagePushManager sharedInstance].moengageInitialized) { + [[MoEngage sharedInstance] didFailToRegisterForPush]; + } + + if (selOriginalApplicationDidFailToRegisterForRemoteNotificationsWithError) { + selOriginalApplicationDidFailToRegisterForRemoteNotificationsWithError([UIApplication sharedApplication].delegate, + @selector(application:didFailToRegisterForRemoteNotificationsWithError:), + application, + error); + } + } + @catch (NSException *exception) { + NSLog(@"MoEngage-Segment Exception : %@", exception.description); + } +} + +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo +{ + @try { + [self pushReceived:userInfo]; + if (selOriginalApplicationDidReceiveRemoteNotification) { + selOriginalApplicationDidReceiveRemoteNotification([UIApplication sharedApplication].delegate, + @selector(application:didReceiveRemoteNotification:), + application, + userInfo); + } + } + @catch (NSException *exception) { + NSLog(@"MoEngage-Segment Exception : %@", exception.description); + } +} + +- (void)pushReceived:(NSDictionary *)userInfo +{ + // When we get this notification, check if MoEngage is initialized. If not store it for future use. + if ([SEGMoEngagePushManager sharedInstance].moengageInitialized) { + [[MoEngage sharedInstance] didReceieveNotificationinApplication:[UIApplication sharedApplication] withInfo:userInfo]; + } else { + [SEGMoEngagePushManager sharedInstance].pushInfoDict = userInfo; + } +} + +@end diff --git a/Analytics/Integrations/SEGAnalyticsIntegrations.h b/Analytics/Integrations/SEGAnalyticsIntegrations.h index 6c297dc86..f863665f6 100644 --- a/Analytics/Integrations/SEGAnalyticsIntegrations.h +++ b/Analytics/Integrations/SEGAnalyticsIntegrations.h @@ -50,6 +50,10 @@ #import "SEGMixpanelIntegration.h" #endif +#if defined(USE_ANALYTICS_MOENGAGE) || defined(USE_ANALYTICS_ALL) +#import "SEGMoEngageIntegration.h" +#endif + #if defined(USE_ANALYTICS_OPTIMIZELY) || defined(USE_ANALYTICS_ALL) #import "SEGOptimizelyIntegration.h" #endif @@ -73,5 +77,3 @@ #if defined(USE_ANALYTICS_UXCAM) || defined(USE_ANALYTICS_ALL) #import "SEGUXCamIntegration.h" #endif - - diff --git a/AnalyticsTests/AnalyticsTests.m b/AnalyticsTests/AnalyticsTests.m index d687d0a3c..46b6dc70a 100644 --- a/AnalyticsTests/AnalyticsTests.m +++ b/AnalyticsTests/AnalyticsTests.m @@ -137,6 +137,9 @@ - (NSDictionary *)testSettings @"token" : @"89f86c4aa2ce5b74cb47eb5ec95ad1f9", @"initialPageview" : @NO }, + @"MoEngage" : @{ + @"apiKey" : @"89f86c4aa2ce5b74cb47eb5ec95ad1f9" + }, @"Tapstream" : @{ @"accountName" : @"segmentio-test", @"sdkSecret" : @"Rq8qqm3KQ_iDeqyOa55aqQ", @@ -160,7 +163,7 @@ - (NSDictionary *)testSettings - (void)testHasIntegrations { - XCTAssertEqual(17, self.analytics.configuration.integrations.count); + XCTAssertEqual(18, self.analytics.configuration.integrations.count); } - (void)testForwardsIdentify diff --git a/Podfile.lock b/Podfile.lock index d8e16f677..458bf4b61 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -20,6 +20,7 @@ PODS: - Mixpanel/Mixpanel (2.8.1): - Mixpanel/MPCategoryHelpers - Mixpanel/MPCategoryHelpers (2.8.1) + - MoEngage-iOS-SDK (1.4.3) - OCHamcrest (4.1.1) - OCMock (3.1.2) - OCMockito (1.4.0): @@ -47,6 +48,7 @@ DEPENDENCIES: - KahunaSDK (= 1.0.570) - Localytics (= 3.3.0) - Mixpanel (= 2.8.1) + - MoEngage-iOS-SDK (= 1.4.3) - OCMock (~> 3.1.2) - OCMockito (~> 1.4.0) - Optimizely-iOS-SDK (= 1.0.86) @@ -70,6 +72,7 @@ SPEC CHECKSUMS: KahunaSDK: ea15fdf9757c4d9bf639bf190888e20b688a30ed Localytics: 64ada284cde3f2b30fb04272d5d735d49657d0ab Mixpanel: 93c4825025e6380ced273ed7178496282e385077 + MoEngage-iOS-SDK: 81be7a433349a7d535c905a08629359eeefe0952 OCHamcrest: 6f03ffa81d12feab872638490a44ab0a6d3aca10 OCMock: a10ea9f0a6e921651f96f78b6faee95ebc813b92 OCMockito: 4981140c9a9ec06c31af40f636e3c0f25f27e6b2 diff --git a/scripts/integrations.json b/scripts/integrations.json index f033a89b6..be4aae714 100644 --- a/scripts/integrations.json +++ b/scripts/integrations.json @@ -80,6 +80,13 @@ "version": "2.8.1" }] }, + { + "name": "MoEngage", + "dependencies": [{ + "name": "MoEngage-iOS-SDK", + "version": "1.4.3" + }] + }, { "name": "Optimizely", "dependencies": [{