diff --git a/Analytics/Classes/Internal/SEGAnalyticsUtils.m b/Analytics/Classes/Internal/SEGAnalyticsUtils.m index 0b268fc45..a83c9059e 100644 --- a/Analytics/Classes/Internal/SEGAnalyticsUtils.m +++ b/Analytics/Classes/Internal/SEGAnalyticsUtils.m @@ -1,5 +1,5 @@ #import "SEGAnalyticsUtils.h" -#import +#import "SEGAnalytics.h" static BOOL kAnalyticsLoggerShowLogs = NO; @@ -217,23 +217,10 @@ static id SEGCoerceJSONObject(id obj) NSString *SEGIDFA() { - NSString *idForAdvertiser = nil; - Class identifierManager = NSClassFromString(@"ASIdentifierManager"); - if (identifierManager) { - SEL sharedManagerSelector = NSSelectorFromString(@"sharedManager"); - id sharedManager = - ((id (*)(id, SEL)) - [identifierManager methodForSelector:sharedManagerSelector])( - identifierManager, sharedManagerSelector); - SEL advertisingIdentifierSelector = - NSSelectorFromString(@"advertisingIdentifier"); - NSUUID *uuid = - ((NSUUID * (*)(id, SEL)) - [sharedManager methodForSelector:advertisingIdentifierSelector])( - sharedManager, advertisingIdentifierSelector); - idForAdvertiser = [uuid UUIDString]; + if ([SEGAnalytics sharedAnalytics].configuration.adSupportBlock != nil) { + return [SEGAnalytics sharedAnalytics].configuration.adSupportBlock(); } - return idForAdvertiser; + return nil; } NSString *SEGEventNameForScreenTitle(NSString *title) diff --git a/Analytics/Classes/Internal/SEGSegmentIntegration.m b/Analytics/Classes/Internal/SEGSegmentIntegration.m index a74b94487..5ef291ac9 100644 --- a/Analytics/Classes/Internal/SEGSegmentIntegration.m +++ b/Analytics/Classes/Internal/SEGSegmentIntegration.m @@ -174,7 +174,7 @@ - (NSDictionary *)staticContext if (NSClassFromString(SEGAdvertisingClassIdentifier)) { dict[@"adTrackingEnabled"] = @(GetAdTrackingEnabled()); } - if (self.configuration.enableAdvertisingTracking) { + if (self.configuration.enableAdvertisingTracking && self.configuration.adSupportBlock != nil) { NSString *idfa = SEGIDFA(); if (idfa.length) dict[@"advertisingId"] = idfa; } diff --git a/Analytics/Classes/SEGAnalyticsConfiguration.h b/Analytics/Classes/SEGAnalyticsConfiguration.h index 44e23832f..915c97d38 100644 --- a/Analytics/Classes/SEGAnalyticsConfiguration.h +++ b/Analytics/Classes/SEGAnalyticsConfiguration.h @@ -20,6 +20,7 @@ @end typedef NSMutableURLRequest *_Nonnull (^SEGRequestFactory)(NSURL *_Nonnull); +typedef NSString *_Nonnull (^SEGAdSupportBlock)(void); @protocol SEGIntegrationFactory; @protocol SEGCrypto; @@ -192,6 +193,18 @@ typedef NSMutableURLRequest *_Nonnull (^SEGRequestFactory)(NSURL *_Nonnull); */ @property (nonatomic, strong, nullable) id httpSessionDelegate; +/** + * Sets a block to be called when IDFA / AdSupport identifier is created. + * This is to allow for apps that do not want ad tracking to pass App Store guidelines in certain categories while + * still allowing apps that do ad tracking to continue to function. + * + * Example: + * configuration.adSupportBlock = ^{ + * return [[ASIdentifierManager sharedManager] advertisingIdentifier]; + * } + */ +@property (nonatomic, strong, nullable) SEGAdSupportBlock adSupportBlock; + /** Enable experimental features within the Segment Analytics-iOS library. */ diff --git a/AnalyticsTests/AnalyticsTests.swift b/AnalyticsTests/AnalyticsTests.swift index b15be213f..a9b8b2e6c 100644 --- a/AnalyticsTests/AnalyticsTests.swift +++ b/AnalyticsTests/AnalyticsTests.swift @@ -58,6 +58,20 @@ class AnalyticsTests: QuickSpec { expect(UserDefaults.standard.string(forKey: "SEGQueue")).toEventually(beNil()) } + /* TODO: Fix me when the Context object isn't so wild. + it("collects IDFA") { + testMiddleware.swallowEvent = true + analytics.configuration.enableAdvertisingTracking = true + analytics.configuration.adSupportBlock = { () -> String in + return "1234AdsNoMore!" + } + + analytics.track("test"); + + let event = testMiddleware.lastContext?.payload as? SEGTrackPayload + expect(event?.properties?["url"] as? String) == "myapp://auth?token=((redacted/my-auth))&other=stuff" + }*/ + it("persists anonymousId") { let analytics2 = SEGAnalytics(configuration: config) expect(analytics.getAnonymousId()) == analytics2.getAnonymousId()