Skip to content

Commit 8aa708d

Browse files
fix: Consent Mapping Configuration
1 parent a009cf5 commit 8aa708d

File tree

1 file changed

+88
-62
lines changed

1 file changed

+88
-62
lines changed

mParticle-Google-Analytics-Firebase-GA4/MPKitFirebaseGA4Analytics.m

Lines changed: 88 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,13 @@ @implementation MPKitFirebaseGA4Analytics
4444
static NSString *const instanceIdIntegrationKey = @"app_instance_id";
4545
static NSString *const invalidFirebaseKey = @"invalid_ga4_key";
4646

47+
// Consent Mapping Keys
4748
static NSString *const kMPFIRGA4AdStorageKey = @"ad_storage";
4849
static NSString *const kMPFIRGA4AdUserDataKey = @"ad_user_data";
4950
static NSString *const kMPFIRGA4AdPersonalizationKey = @"ad_personalization";
5051
static NSString *const kMPFIRGA4AnalyticsStorageKey = @"analytics_storage";
52+
53+
// Default Consent Keys (from mParticle UI)
5154
static NSString *const kMPFIRGA4DefaultAdStorageKey = @"defaultAdStorageConsentSDK";
5255
static NSString *const kMPFIRGA4DefaultAdUserDataKey = @"defaultAdUserDataConsentSDK";
5356
static NSString *const kMPFIRGA4DefaultAdPersonalizationKey = @"defaultAdPersonalizationConsentSDK";
@@ -87,6 +90,7 @@ - (MPKitExecStatus *)execStatus:(MPKitReturnCode)returnCode {
8790
#pragma mark MPKitInstanceProtocol methods
8891
- (MPKitExecStatus *)didFinishLaunchingWithConfiguration:(NSDictionary *)configuration {
8992
_configuration = configuration;
93+
[FIRApp configure];
9094

9195
if ([FIRApp defaultApp] == nil) {
9296
NSAssert(NO, @"There is no instance of Firebase. Check the docs and review your code.");
@@ -385,76 +389,51 @@ - (MPKitExecStatus *)setConsentState:(nullable MPConsentState *)state {
385389
}
386390

387391
- (void)updateConsent {
388-
FIRConsentStatus adStorageStatus;
389-
FIRConsentStatus adUserDataStatus;
390-
FIRConsentStatus analyticsStorageStatus;
391-
FIRConsentStatus adPersonalizationStatus;
392-
393-
// Default Consent States
394-
if (self.configuration[kMPFIRGA4DefaultAdStorageKey]) {
395-
if ([self.configuration[kMPFIRGA4DefaultAdStorageKey] isEqual: @"Granted"]) {
396-
adStorageStatus = FIRConsentStatusGranted;
397-
} else if ([self.configuration[kMPFIRGA4DefaultAdStorageKey] isEqual: @"Denied"]) {
398-
adStorageStatus = FIRConsentStatusDenied;
399-
}
400-
}
401-
if (self.configuration[kMPFIRGA4DefaultAdUserDataKey]) {
402-
if ([self.configuration[kMPFIRGA4DefaultAdUserDataKey] isEqual: @"Granted"]) {
403-
adUserDataStatus = FIRConsentStatusGranted;
404-
} else if ([self.configuration[kMPFIRGA4DefaultAdUserDataKey] isEqual: @"Denied"]) {
405-
adUserDataStatus = FIRConsentStatusDenied;
406-
}
407-
}
408-
if (self.configuration[kMPFIRGA4DefaultAnalyticsStorageKey]) {
409-
if ([self.configuration[kMPFIRGA4DefaultAnalyticsStorageKey] isEqual: @"Granted"]) {
410-
analyticsStorageStatus = FIRConsentStatusGranted;
411-
} else if ([self.configuration[kMPFIRGA4DefaultAnalyticsStorageKey] isEqual: @"Denied"]) {
412-
analyticsStorageStatus = FIRConsentStatusDenied;
413-
}
414-
}
415-
if (self.configuration[kMPFIRGA4DefaultAdPersonalizationKey]) {
416-
if ([self.configuration[kMPFIRGA4DefaultAdPersonalizationKey] isEqual: @"Granted"]) {
417-
adPersonalizationStatus = FIRConsentStatusGranted;
418-
} else if ([self.configuration[kMPFIRGA4DefaultAdPersonalizationKey] isEqual: @"Denied"]) {
419-
adPersonalizationStatus = FIRConsentStatusDenied;
420-
}
392+
NSArray<NSDictionary *> *mappings = [self mappingForKey: @"consentMappingSDK"];
393+
NSDictionary<NSString *, NSString *> *mappingsConfig;
394+
if (mappings != nil) {
395+
mappingsConfig = [self convertToKeyValuePairs: mappings];
421396
}
422397

423-
MParticleUser *currentUser = [[[MParticle sharedInstance] identity] currentUser];
424-
NSDictionary<NSString *, MPGDPRConsent *> *userConsentMap = currentUser.consentState.gdprConsentState;
425398

426-
// Update from mParticle consent
427-
if (self.configuration[kMPFIRGA4AdStorageKey] && userConsentMap[self.configuration[kMPFIRGA4AdStorageKey]]) {
428-
MPGDPRConsent *consent = userConsentMap[self.configuration[kMPFIRGA4AdStorageKey]];
429-
adStorageStatus = consent.consented ? FIRConsentStatusGranted : FIRConsentStatusDenied;
399+
MParticleUser *currentUser = [[[MParticle sharedInstance] identity] currentUser];
400+
NSDictionary<NSString *, MPGDPRConsent *> *gdprConsents = currentUser.consentState.gdprConsentState;
401+
402+
NSNumber *adStorage = [self resolvedConsentForMappingKey:kMPFIRGA4AdStorageKey
403+
defaultKey:kMPFIRGA4DefaultAdStorageKey
404+
gdprConsents:gdprConsents
405+
mappingsConfig:mappingsConfig];
406+
407+
NSNumber *adUserData = [self resolvedConsentForMappingKey:kMPFIRGA4AdUserDataKey
408+
defaultKey:kMPFIRGA4DefaultAdUserDataKey
409+
gdprConsents:gdprConsents
410+
mappingsConfig:mappingsConfig];
411+
412+
NSNumber *analyticsStorage = [self resolvedConsentForMappingKey:kMPFIRGA4AnalyticsStorageKey
413+
defaultKey:kMPFIRGA4DefaultAnalyticsStorageKey
414+
gdprConsents:gdprConsents
415+
mappingsConfig:mappingsConfig];
416+
417+
NSNumber *adPersonalization = [self resolvedConsentForMappingKey:kMPFIRGA4AdPersonalizationKey
418+
defaultKey:kMPFIRGA4DefaultAdPersonalizationKey
419+
gdprConsents:gdprConsents
420+
mappingsConfig:mappingsConfig];
421+
422+
NSMutableDictionary *uploadDict = [NSMutableDictionary dictionary];
423+
424+
if (adStorage != nil) {
425+
uploadDict[FIRConsentTypeAdStorage] = adStorage.boolValue ? FIRConsentStatusGranted : FIRConsentStatusDenied;
430426
}
431-
if (self.configuration[kMPFIRGA4AdUserDataKey] && userConsentMap[self.configuration[kMPFIRGA4AdUserDataKey]]) {
432-
MPGDPRConsent *consent = userConsentMap[self.configuration[kMPFIRGA4AdUserDataKey]];
433-
adUserDataStatus = consent.consented ? FIRConsentStatusGranted : FIRConsentStatusDenied;
427+
if (adUserData != nil) {
428+
uploadDict[FIRConsentTypeAdUserData] = adUserData.boolValue ? FIRConsentStatusGranted : FIRConsentStatusDenied;
434429
}
435-
if (self.configuration[kMPFIRGA4AnalyticsStorageKey] && userConsentMap[self.configuration[kMPFIRGA4AnalyticsStorageKey]]) {
436-
MPGDPRConsent *consent = userConsentMap[self.configuration[kMPFIRGA4AnalyticsStorageKey]];
437-
analyticsStorageStatus = consent.consented ? FIRConsentStatusGranted : FIRConsentStatusDenied;
430+
if (analyticsStorage != nil) {
431+
uploadDict[FIRConsentTypeAnalyticsStorage] = analyticsStorage.boolValue ? FIRConsentStatusGranted : FIRConsentStatusDenied;
438432
}
439-
if (self.configuration[kMPFIRGA4AdPersonalizationKey] && userConsentMap[self.configuration[kMPFIRGA4AdPersonalizationKey]]) {
440-
MPGDPRConsent *consent = userConsentMap[self.configuration[kMPFIRGA4AdPersonalizationKey]];
441-
adPersonalizationStatus = consent.consented ? FIRConsentStatusGranted : FIRConsentStatusDenied;
433+
if (adPersonalization != nil) {
434+
uploadDict[FIRConsentTypeAdPersonalization] = adPersonalization.boolValue ? FIRConsentStatusGranted : FIRConsentStatusDenied;
442435
}
443436

444-
// Construct a dictionary of consents
445-
NSMutableDictionary *uploadDict = [[NSMutableDictionary alloc] init];
446-
if (adStorageStatus) {
447-
uploadDict[FIRConsentTypeAdStorage] = adStorageStatus;
448-
}
449-
if (adUserDataStatus) {
450-
uploadDict[FIRConsentTypeAdUserData] = adUserDataStatus;
451-
}
452-
if (analyticsStorageStatus) {
453-
uploadDict[FIRConsentTypeAnalyticsStorage] = analyticsStorageStatus;
454-
}
455-
if (adPersonalizationStatus) {
456-
uploadDict[FIRConsentTypeAdPersonalization] = adPersonalizationStatus;
457-
}
458437

459438
// Update consent state with FIRAnalytics
460439
[FIRAnalytics setConsent:uploadDict];
@@ -688,4 +667,51 @@ - (void)limitDictionary:(NSMutableDictionary *)dictionary maxCount:(int)maxCount
688667
}
689668
}
690669

670+
#pragma mark - Helpers
671+
672+
- (NSNumber * _Nullable)resolvedConsentForMappingKey:(NSString *)mappingKey
673+
defaultKey:(NSString *)defaultKey
674+
gdprConsents:(NSDictionary<NSString *, MPGDPRConsent *> *)gdprConsents
675+
mappingsConfig:(NSDictionary<NSString *, NSString*> *) mapping {
676+
677+
// Prefer mParticle Consent if available
678+
NSString *purpose = mapping[mappingKey];
679+
if (purpose) {
680+
MPGDPRConsent *consent = gdprConsents[purpose];
681+
if (consent) {
682+
return @(consent.consented);
683+
}
684+
}
685+
686+
// Fallback to configuration defaults
687+
NSString *value = self->_configuration[defaultKey];
688+
if ([value isEqualToString:@"Granted"]) {
689+
return @(YES);
690+
} else if ([value isEqualToString:@"Denied"]) {
691+
return @(NO);
692+
}
693+
return nil;
694+
}
695+
696+
- (NSArray<NSDictionary *>*)mappingForKey:(NSString*)key {
697+
NSString *mappingJson = _configuration[@"consentMappingSDK"];
698+
if ([mappingJson isKindOfClass:[NSString class]]) {
699+
NSData *jsonData = [mappingJson dataUsingEncoding:NSUTF8StringEncoding];
700+
return [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
701+
}
702+
return nil;
703+
}
704+
705+
- (NSDictionary*)convertToKeyValuePairs: (NSArray<NSDictionary *>*) mappings {
706+
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
707+
for (NSDictionary *entry in mappings) {
708+
NSString *value = entry[@"value"];
709+
NSString *purpose = [entry[@"map"] lowercaseString];
710+
if (value && purpose) {
711+
dict[value] = purpose;
712+
}
713+
}
714+
return dict;
715+
}
716+
691717
@end

0 commit comments

Comments
 (0)