diff --git a/CHANGELOG.md b/CHANGELOG.md index ac58021..12f7fcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,27 @@ +## 3.0.0 + +##### Breaking +- Log separate purchases for each product in the `products` array in a `track` call. + - In the past we used the event name as the product ID. + - Now if a `track` call has the event name `Order Completed` or the key `revenue` included in `properties` and also has a `products` array, we will log each object in the array as a separate purchase using `productId` as the product ID. `price` and `quantity` will be read from the individual array if available. All non-Braze recognized fields from the high level `properties` and each individual product will be combined and sent as event properties. + - If there is no `products` array we will continue using the event name as the product ID if the key `revenue` is included in `properties`. + +##### Added +- Added a push delegate method for apps using the `UserNotification` framework. + - Follow our [documentation](https://www.braze.com/docs/developer_guide/platform_integration_guides/ios/push_notifications/integration/#using-usernotification-framework-ios-10) for registering for push notifications using the `UserNotification` framework. + - In `userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler` add the following block of code: + ``` + if ([Appboy sharedInstance] == nil) { + [[SEGAppboyIntegrationFactory instance].appboyHelper saveUserNotificationCenter:center + notificationResponse:response]; + } + [[SEGAppboyIntegrationFactory instance].appboyHelper userNotificationCenter:center + receivedNotificationResponse:response]; + if (completionHandler) { + completionHandler(); + } + ``` + ## 2.3.0 ##### Changed diff --git a/Example/Segment-Appboy.xcodeproj/project.pbxproj b/Example/Segment-Appboy.xcodeproj/project.pbxproj index 750833a..83b289c 100644 --- a/Example/Segment-Appboy.xcodeproj/project.pbxproj +++ b/Example/Segment-Appboy.xcodeproj/project.pbxproj @@ -267,8 +267,43 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, + de, + he, + ar, + "zh-Hans", + ja, + "zh-TW", + "zh-HK", + nb, + es, + da, + "es-419", + et, + it, + ms, + sv, + km, + ko, + fil, + "zh-Hant", + my, + pl, + vi, + lo, + "es-MX", + ru, + fr, + fi, + id, + nl, + th, + pt, + "pt-PT", + hi, + zh, ); mainGroup = 6003F581195388D10070C39A; productRefGroup = 6003F58B195388D20070C39A /* Products */; diff --git a/Example/Segment-Appboy/SEGAppDelegate.h b/Example/Segment-Appboy/SEGAppDelegate.h index 4fa9e2b..2fa2ec5 100644 --- a/Example/Segment-Appboy/SEGAppDelegate.h +++ b/Example/Segment-Appboy/SEGAppDelegate.h @@ -1,6 +1,7 @@ @import UIKit; +#import -@interface SEGAppDelegate : UIResponder +@interface SEGAppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; diff --git a/Example/Segment-Appboy/SEGAppDelegate.m b/Example/Segment-Appboy/SEGAppDelegate.m index 047163b..b350510 100644 --- a/Example/Segment-Appboy/SEGAppDelegate.m +++ b/Example/Segment-Appboy/SEGAppDelegate.m @@ -5,8 +5,7 @@ @implementation SEGAppDelegate -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { SEGAnalyticsConfiguration *config = [SEGAnalyticsConfiguration configurationWithWriteKey:@"xNAmGpyITen4FEZg9C2ES6r2iYm8Ommk"]; [config use:[SEGAppboyIntegrationFactory instance]]; [[SEGAppboyIntegrationFactory instance] saveLaunchOptions:launchOptions]; @@ -45,8 +44,7 @@ - (void)applicationWillTerminate:(UIApplication *)application // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo -{ +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { [[SEGAnalytics sharedAnalytics] receivedRemoteNotification:userInfo]; } @@ -58,13 +56,25 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N completionHandler(UIBackgroundFetchResultNoData); } -- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken -{ +- (void)userNotificationCenter:(UNUserNotificationCenter *)center +didReceiveNotificationResponse:(UNNotificationResponse *)response + withCompletionHandler:(void (^)(void))completionHandler { + if ([Appboy sharedInstance] == nil) { + [[SEGAppboyIntegrationFactory instance].appboyHelper saveUserNotificationCenter:center + notificationResponse:response]; + } + [[SEGAppboyIntegrationFactory instance].appboyHelper userNotificationCenter:center + receivedNotificationResponse:response]; + if (completionHandler) { + completionHandler(); + } +} + +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [[SEGAnalytics sharedAnalytics] registeredForRemoteNotificationsWithDeviceToken:deviceToken]; } -- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler -{ +- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler { if ([Appboy sharedInstance] == nil) { [[SEGAppboyIntegrationFactory instance] saveRemoteNotification:userInfo]; } @@ -92,8 +102,24 @@ - (void)setupPushCategories { [likeCategory setActions:@[likeAction, unlikeAction] forContext:UIUserNotificationActionContextDefault]; NSSet *categories = [NSSet setWithObjects:likeCategory, nil]; - UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeAlert | UIUserNotificationTypeSound) categories:categories]; - [[UIApplication sharedApplication] registerForRemoteNotifications]; - [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; + + if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) { + UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; + center.delegate = self; + UNAuthorizationOptions options = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge; + if (@available(iOS 12.0, *)) { + options = options | UNAuthorizationOptionProvisional; + } + [center requestAuthorizationWithOptions:options + completionHandler:^(BOOL granted, NSError * _Nullable error) { + [[Appboy sharedInstance] pushAuthorizationFromUserNotificationCenter:granted]; + }]; + [[UIApplication sharedApplication] registerForRemoteNotifications]; + } else { + UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound) categories:categories]; + [[UIApplication sharedApplication] registerForRemoteNotifications]; + [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; + } } + @end diff --git a/Example/Segment-Appboy/SEGViewController.m b/Example/Segment-Appboy/SEGViewController.m index 41e6bc8..3ad9365 100644 --- a/Example/Segment-Appboy/SEGViewController.m +++ b/Example/Segment-Appboy/SEGViewController.m @@ -75,6 +75,32 @@ - (IBAction)trackButtonPress:(id)sender { properties:@{ @"currency": @"CNY", @"revenue" : numberRevenue, @"property" : @"milky white rabbit"}]; [[SEGAnalytics sharedAnalytics] track:@"Purchase" properties:@{ @"currency": @"CNY", @"revenue" : stringRevenue, @"property" : @"myProperty"}]; + [[SEGAnalytics sharedAnalytics] track:@"Order Completed" + properties:@{@"currency": @"CNY", + @"revenue" : numberRevenue, + @"products" : @[@{@"productId" : @"cookies", + @"price" : @"72.3", + @"quantity" : @(29), + @"cookieType" : @"chocolateChip" + }, + @{@"productId" : @"muffins", + @"price" : @"24.2", + @"quantity" : @(17), + @"muffinType" : @"blueberry" + }], + @"purchaseType" : @"productsArray" + }]; + [[SEGAnalytics sharedAnalytics] track:@"Order Completed" + properties:@{@"currency" : @"USD", + @"products" : @[@{@"productId" : @"phone", + @"price" : @"199.99", + @"quantity" : @(2), + @"phoneType" : @"iPhoneX"}, + @{@"productId" : @"tablet", + @"price" : @"149.99", + @"quantity" : @(3), + @"tabletType" : @"iPad"}], + @"store" : @"appleStore"}]; [[SEGAnalytics sharedAnalytics] track:@"Install Attributed" properties: @{@"provider" : @"Tune/Kochava/Branch", @"campaign" : @{@"source" : @"Network/FB/AdWords/MoPub/Source", diff --git a/Example/Tests/SEGAppboyIntegrationTest.m b/Example/Tests/SEGAppboyIntegrationTest.m index c879bc6..732ebb2 100644 --- a/Example/Tests/SEGAppboyIntegrationTest.m +++ b/Example/Tests/SEGAppboyIntegrationTest.m @@ -11,7 +11,7 @@ it(@"initializes appboy if an apiKey is passed", ^{ NSDictionary *settings = @{@"apiKey":@"foo"}; id appboyMock = OCMClassMock([Appboy class]); - OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil]); + OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil withAppboyOptions:[OCMArg any]]); SEGAppboyIntegration *appboyIntegration = [[SEGAppboyIntegration alloc] initWithSettings:settings]; OCMVerifyAllWithDelay(appboyMock, 2); }); @@ -29,7 +29,7 @@ id appboyUserMock = OCMClassMock([ABKUser class]); OCMStub([appboyMock sharedInstance]).andReturn(appboyMock); OCMStub([appboyMock user]).andReturn(appboyUserMock); - OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil]); + OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil withAppboyOptions:[OCMArg any]]); OCMExpect([appboyMock changeUser:@"testUser"]); OCMExpect([appboyUserMock setDateOfBirth:testDate]); OCMExpect([appboyUserMock setEmail:@"brian@appboy.com"]); @@ -72,7 +72,7 @@ id appboyUserMock = OCMClassMock([ABKUser class]); OCMStub([appboyMock sharedInstance]).andReturn(appboyMock); OCMStub([appboyMock user]).andReturn(appboyUserMock); - OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil]); + OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil withAppboyOptions:[OCMArg any]]); OCMExpect([appboyMock changeUser:@"testUser"]); SEGAppboyIntegration *appboyIntegration = [[SEGAppboyIntegration alloc] initWithSettings:settings]; @@ -104,7 +104,7 @@ NSDictionary *settings = @{@"apiKey":@"foo"}; id appboyMock = OCMClassMock([Appboy class]); OCMStub([appboyMock sharedInstance]).andReturn(appboyMock); - OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil]); + OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil withAppboyOptions:[OCMArg any]]); OCMExpect([appboyMock logPurchase:@"testPurchase" inCurrency:@"USD" atPrice:[NSDecimalNumber decimalNumberWithString:@"55.5"] withQuantity:1 andProperties:@{@"extraProperty" : @"extraValue"}]); @@ -123,12 +123,42 @@ [appboyIntegration track:trackPayload]; OCMVerifyAllWithDelay(appboyMock, 2); }); + + it(@"calls logPurchase for each product in the products array", ^{ + NSDictionary *settings = @{@"apiKey":@"foo"}; + id appboyMock = OCMClassMock([Appboy class]); + OCMStub([appboyMock sharedInstance]).andReturn(appboyMock); + OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil withAppboyOptions:[OCMArg any]]); + OCMExpect(([appboyMock logPurchase:@"product1" inCurrency:@"USD" atPrice:[NSDecimalNumber decimalNumberWithString:@"72.3"] + withQuantity:29 andProperties:@{@"extraProperty" : @"extraValue", + @"productProperty" : @"productValue" + }])); + + SEGAppboyIntegration *appboyIntegration = [[SEGAppboyIntegration alloc] initWithSettings:settings]; + + NSDictionary *properties = @{ + @"currency" : @"USD", + @"extraProperty" : @"extraValue", + @"products" : @[@{@"productId" : @"product1", + @"price" : @"72.3", + @"quantity" : @(29), + @"productProperty" : @"productValue" + }] + }; + + SEGTrackPayload *trackPayload = [[SEGTrackPayload alloc] initWithEvent:@"Order Completed" + properties:properties + context:nil + integrations:nil]; + [appboyIntegration track:trackPayload]; + OCMVerifyAllWithDelay(appboyMock, 2); + }); it(@"logs an event if there isn't revenue", ^{ NSDictionary *settings = @{@"apiKey":@"foo"}; id appboyMock = OCMClassMock([Appboy class]); OCMStub([appboyMock sharedInstance]).andReturn(appboyMock); - OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil]); + OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil withAppboyOptions:[OCMArg any]]); NSDictionary *propertiesDictionary = @{ @"asdf" : @1, @"extraProperty" : @"extraValue"}; OCMExpect([appboyMock logCustomEvent:@"testEvent" withProperties:propertiesDictionary]); @@ -147,13 +177,12 @@ }); }); - describe(@"flush", ^{ it(@"calls [[Appboy sharedInstance] flushDataAndProcessRequestQueue]", ^{ NSDictionary *settings = @{@"apiKey":@"foo"}; id appboyMock = OCMClassMock([Appboy class]); OCMStub([appboyMock sharedInstance]).andReturn(appboyMock); - OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil]); + OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil withAppboyOptions:[OCMArg any]]); OCMExpect([appboyMock flushDataAndProcessRequestQueue]); SEGAppboyIntegration *appboyIntegration = [[SEGAppboyIntegration alloc] initWithSettings:settings]; [appboyIntegration flush]; @@ -167,8 +196,8 @@ NSData *registerData = [[NSData alloc] init]; id appboyMock = OCMClassMock([Appboy class]); OCMStub([appboyMock sharedInstance]).andReturn(appboyMock); - OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil]); - OCMExpect([appboyMock registerPushToken:[OCMArg any]]); + OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil withAppboyOptions:[OCMArg any]]); + OCMExpect([appboyMock registerDeviceToken:[OCMArg any]]); SEGAppboyIntegration *appboyIntegration = [[SEGAppboyIntegration alloc] initWithSettings:settings]; [appboyIntegration registeredForRemoteNotificationsWithDeviceToken:registerData]; OCMVerifyAllWithDelay(appboyMock, 2); @@ -181,7 +210,7 @@ NSDictionary *userInfo = @{@"test":@"userInfo"}; id appboyMock = OCMClassMock([Appboy class]); OCMStub([appboyMock sharedInstance]).andReturn(appboyMock); - OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil]); + OCMExpect([appboyMock startWithApiKey:@"foo" inApplication:[OCMArg any] withLaunchOptions:nil withAppboyOptions:[OCMArg any]]); OCMExpect([appboyMock registerApplication:[OCMArg any] didReceiveRemoteNotification:userInfo]); SEGAppboyIntegration *appboyIntegration = [[SEGAppboyIntegration alloc] initWithSettings:settings]; [appboyIntegration receivedRemoteNotification:userInfo]; diff --git a/Example/fastlane/README.md b/Example/fastlane/README.md new file mode 100644 index 0000000..096886b --- /dev/null +++ b/Example/fastlane/README.md @@ -0,0 +1,33 @@ +fastlane documentation +================ +# Installation + +Make sure you have the latest version of the Xcode command line tools installed: + +``` +xcode-select --install +``` + +Install _fastlane_ using +``` +[sudo] gem install fastlane -NV +``` +or alternatively using `brew cask install fastlane` + +# Available Actions +### matchFullAccess +``` +fastlane matchFullAccess +``` + +### matchReadOnly +``` +fastlane matchReadOnly +``` + + +---- + +This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. +More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). +The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). diff --git a/Example/fastlane/report.xml b/Example/fastlane/report.xml new file mode 100644 index 0000000..aeded9d --- /dev/null +++ b/Example/fastlane/report.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pod/Classes/SEGAppboyHelper.h b/Pod/Classes/SEGAppboyHelper.h new file mode 100644 index 0000000..6b3db4e --- /dev/null +++ b/Pod/Classes/SEGAppboyHelper.h @@ -0,0 +1,12 @@ +#import +#import + +@interface SEGAppboyHelper : NSObject + +- (void)applicationDidFinishLaunching; +- (void)saveUserNotificationCenter:(UNUserNotificationCenter *)center + notificationResponse:(UNNotificationResponse *)response NS_AVAILABLE_IOS(10_0); +- (void)userNotificationCenter:(UNUserNotificationCenter *)center + receivedNotificationResponse:(UNNotificationResponse *)response NS_AVAILABLE_IOS(10_0); + +@end diff --git a/Pod/Classes/SEGAppboyHelper.m b/Pod/Classes/SEGAppboyHelper.m new file mode 100644 index 0000000..17f6e7b --- /dev/null +++ b/Pod/Classes/SEGAppboyHelper.m @@ -0,0 +1,54 @@ +#import "SEGAppboyHelper.h" +#import "SEGAppboyIntegration.h" +#if defined(__has_include) && __has_include() +#import +#else +#import "Appboy-iOS-SDK/AppboyKit.h" +#endif + +@interface SEGAppboyHelper () + +@property UNUserNotificationCenter *center NS_AVAILABLE_IOS(10_0); +@property UNNotificationResponse *response NS_AVAILABLE_IOS(10_0); + +@end + +@implementation SEGAppboyHelper + +- (void)applicationDidFinishLaunching NS_AVAILABLE_IOS(10_0) { + [self logUNPushIfComesInBeforeAppboyInitialized]; +} + +- (void)saveUserNotificationCenter:(UNUserNotificationCenter *)center + notificationResponse:(UNNotificationResponse *)response { + self.center = center; + self.response = response; +} + +- (void)userNotificationCenter:(UNUserNotificationCenter *)center + receivedNotificationResponse:(UNNotificationResponse *)response { + if (![self logUNPushIfComesInBeforeAppboyInitialized]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [[Appboy sharedInstance] userNotificationCenter:center + didReceiveNotificationResponse:response + withCompletionHandler:nil]; + }); + } +} + +- (BOOL)logUNPushIfComesInBeforeAppboyInitialized NS_AVAILABLE_IOS(10_0) { + if (self.center != nil && self.response != nil) { + // The existence of a saved notification response indicates that the push was received when + // Appboy was not initialized yet, and thus the push was received in the inactive state. + if ([[Appboy sharedInstance] respondsToSelector:@selector(userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:)]) { + [[Appboy sharedInstance] userNotificationCenter:self.center + didReceiveNotificationResponse:self.response + withCompletionHandler:nil]; + [self saveUserNotificationCenter:nil notificationResponse:nil]; + return YES; + } + } + return NO; +} + +@end diff --git a/Pod/Classes/SEGAppboyIntegration.h b/Pod/Classes/SEGAppboyIntegration.h index 02ae92d..a77a6b2 100644 --- a/Pod/Classes/SEGAppboyIntegration.h +++ b/Pod/Classes/SEGAppboyIntegration.h @@ -7,4 +7,4 @@ - (id)initWithSettings:(NSDictionary *)settings; -@end \ No newline at end of file +@end diff --git a/Pod/Classes/SEGAppboyIntegration.m b/Pod/Classes/SEGAppboyIntegration.m index 511751b..6daf400 100644 --- a/Pod/Classes/SEGAppboyIntegration.m +++ b/Pod/Classes/SEGAppboyIntegration.m @@ -12,6 +12,7 @@ #import "SEGAppboyIntegrationFactory.h" @interface Appboy(Segment) + - (void) handleRemotePushNotification:(NSDictionary *)notification withIdentifier:(NSString *)identifier completionHandler:(void (^)(UIBackgroundFetchResult))completionHandler @@ -185,7 +186,7 @@ - (void)track:(SEGTrackPayload *)payload } NSDecimalNumber *revenue = [SEGAppboyIntegration extractRevenue:payload.properties withKey:@"revenue"]; - if (revenue) { + if (revenue || [payload.event isEqualToString:@"Order Completed"]) { NSString *currency = @"USD"; // Make USD as the default currency. if ([payload.properties[@"currency"] isKindOfClass:[NSString class]] && [(NSString *)payload.properties[@"currency"] length] == 3) { // Currency should be an ISO 4217 currency code. @@ -196,7 +197,26 @@ - (void)track:(SEGTrackPayload *)payload NSMutableDictionary *appboyProperties = [NSMutableDictionary dictionaryWithDictionary:payload.properties]; appboyProperties[@"currency"] = nil; appboyProperties[@"revenue"] = nil; - [[Appboy sharedInstance] logPurchase:payload.event inCurrency:currency atPrice:revenue withQuantity:1 andProperties:appboyProperties]; + + if (appboyProperties[@"products"]) { + NSArray *products = [appboyProperties[@"products"] copy]; + appboyProperties[@"products"] = nil; + + for (NSDictionary *product in products) { + NSMutableDictionary *productDictionary = [product mutableCopy]; + NSString *productId = productDictionary[@"productId"]; + NSDecimalNumber *productRevenue = [SEGAppboyIntegration extractRevenue:productDictionary withKey:@"price"]; + NSUInteger productQuantity = [productDictionary[@"quantity"] unsignedIntegerValue]; + productDictionary[@"productId"] = nil; + productDictionary[@"price"] = nil; + productDictionary[@"quantity"] = nil; + NSMutableDictionary *productProperties = [appboyProperties mutableCopy]; + [productProperties addEntriesFromDictionary:productDictionary]; + [[Appboy sharedInstance] logPurchase:productId inCurrency:currency atPrice:productRevenue withQuantity:productQuantity andProperties:productProperties]; + } + } else { + [[Appboy sharedInstance] logPurchase:payload.event inCurrency:currency atPrice:revenue withQuantity:1 andProperties:appboyProperties]; + } } else { [[Appboy sharedInstance] logPurchase:payload.event inCurrency:currency atPrice:revenue withQuantity:1]; } @@ -241,6 +261,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { if (![[UIApplication sharedApplication].delegate respondsToSelector:@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:)]) { [self logPushIfComesInBeforeAppboyInitializedWithIdentifier:nil]; } + [[SEGAppboyIntegrationFactory instance].appboyHelper applicationDidFinishLaunching]; }); } @@ -260,7 +281,7 @@ - (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification: SEGLog(@"[[Appboy sharedInstance] getActionWithIdentifier: forRemoteNotification: completionHandler:]"); } -- (BOOL) logPushIfComesInBeforeAppboyInitializedWithIdentifier:(NSString *)identifier { +- (BOOL)logPushIfComesInBeforeAppboyInitializedWithIdentifier:(NSString *)identifier { NSDictionary *pushDictionary = [[SEGAppboyIntegrationFactory instance] getPushPayload]; if (pushDictionary != nil && pushDictionary.count > 0) { // The existence of a push payload saved on the factory indicates that the push was received when @@ -276,4 +297,5 @@ - (BOOL) logPushIfComesInBeforeAppboyInitializedWithIdentifier:(NSString *)ident } return NO; } + @end diff --git a/Pod/Classes/SEGAppboyIntegrationFactory.h b/Pod/Classes/SEGAppboyIntegrationFactory.h index c289205..57a42cc 100644 --- a/Pod/Classes/SEGAppboyIntegrationFactory.h +++ b/Pod/Classes/SEGAppboyIntegrationFactory.h @@ -1,10 +1,14 @@ #import #import +#import "SEGAppboyHelper.h" @interface SEGAppboyIntegrationFactory : NSObject +@property (readonly) SEGAppboyHelper *appboyHelper; + + (instancetype)instance; - (void)saveLaunchOptions:(NSDictionary *)launchOptions; - (void)saveRemoteNotification:(NSDictionary *)userInfo; -@end \ No newline at end of file + +@end diff --git a/Pod/Classes/SEGAppboyIntegrationFactory.m b/Pod/Classes/SEGAppboyIntegrationFactory.m index ce497c0..3807bd8 100644 --- a/Pod/Classes/SEGAppboyIntegrationFactory.m +++ b/Pod/Classes/SEGAppboyIntegrationFactory.m @@ -1,8 +1,16 @@ #import "SEGAppboyIntegrationFactory.h" #import "SEGAppboyIntegration.h" +#if defined(__has_include) && __has_include() +#import +#else +#import "Appboy-iOS-SDK/AppboyKit.h" +#endif @interface SEGAppboyIntegrationFactory () + @property NSDictionary *savedPushPayload; +@property (readwrite) SEGAppboyHelper *appboyHelper; + @end @implementation SEGAppboyIntegrationFactory @@ -17,9 +25,10 @@ + (instancetype)instance return sharedInstance; } -- (id)init -{ - self = [super init]; +- (id)init { + if (self = [super init]) { + self.appboyHelper = [[SEGAppboyHelper alloc] init]; + } return self; } @@ -33,7 +42,7 @@ - (NSString *)key return @"Appboy"; } -- (void) saveLaunchOptions:(NSDictionary *)launchOptions { +- (void)saveLaunchOptions:(NSDictionary *)launchOptions { NSDictionary *pushPayLoad = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]; if (pushPayLoad != nil && pushPayLoad.count > 0) { self.savedPushPayload = [pushPayLoad copy]; @@ -47,4 +56,5 @@ - (void)saveRemoteNotification:(NSDictionary *)userInfo { - (NSDictionary *) getPushPayload { return self.savedPushPayload; } -@end \ No newline at end of file + +@end diff --git a/Segment-Appboy.podspec b/Segment-Appboy.podspec index 1399470..570606f 100644 --- a/Segment-Appboy.podspec +++ b/Segment-Appboy.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Segment-Appboy" - s.version = "2.3.0" + s.version = "3.0.0" s.summary = "Braze Integration for Segment's analytics-ios library." s.description = <<-DESC