@@ -42,10 +42,13 @@ @implementation MPKitFirebaseAnalytics
4242static NSString *const aToZCharacters = @" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
4343static NSString *const instanceIdIntegrationKey = @" app_instance_id" ;
4444
45- static NSString *const kMPFIRGA4AdStorageKey = @" ad_storage" ;
46- static NSString *const kMPFIRGA4AdUserDataKey = @" ad_user_data" ;
47- static NSString *const kMPFIRGA4AdPersonalizationKey = @" ad_personalization" ;
48- static NSString *const kMPFIRGA4AnalyticsStorageKey = @" analytics_storage" ;
45+ // Consent Mapping Keys
46+ static NSString *const kMPFIRGAAdStorageKey = @" ad_storage" ;
47+ static NSString *const kMPFIRGAAdUserDataKey = @" ad_user_data" ;
48+ static NSString *const kMPFIRGAAdPersonalizationKey = @" ad_personalization" ;
49+ static NSString *const kMPFIRGAAnalyticsStorageKey = @" analytics_storage" ;
50+
51+ // Default Consent Keys (from mParticle UI)
4952static NSString *const kMPFIRGA4DefaultAdStorageKey = @" defaultAdStorageConsentSDK" ;
5053static NSString *const kMPFIRGA4DefaultAdUserDataKey = @" defaultAdUserDataConsentSDK" ;
5154static NSString *const kMPFIRGA4DefaultAdPersonalizationKey = @" defaultAdPersonalizationConsentSDK" ;
@@ -359,77 +362,52 @@ - (MPKitExecStatus *)setConsentState:(nullable MPConsentState *)state {
359362}
360363
361364- (void )updateConsent {
362- FIRConsentStatus adStorageStatus;
363- FIRConsentStatus adUserDataStatus;
364- FIRConsentStatus analyticsStorageStatus;
365- FIRConsentStatus adPersonalizationStatus;
366-
367- // Default Consent States
368- if (self.configuration [kMPFIRGA4DefaultAdStorageKey ]) {
369- if ([self .configuration[kMPFIRGA4DefaultAdStorageKey ] isEqual: @" Granted" ]) {
370- adStorageStatus = FIRConsentStatusGranted;
371- } else if ([self .configuration[kMPFIRGA4DefaultAdStorageKey ] isEqual: @" Denied" ]) {
372- adStorageStatus = FIRConsentStatusDenied;
373- }
374- }
375- if (self.configuration [kMPFIRGA4DefaultAdUserDataKey ]) {
376- if ([self .configuration[kMPFIRGA4DefaultAdUserDataKey ] isEqual: @" Granted" ]) {
377- adUserDataStatus = FIRConsentStatusGranted;
378- } else if ([self .configuration[kMPFIRGA4DefaultAdUserDataKey ] isEqual: @" Denied" ]) {
379- adUserDataStatus = FIRConsentStatusDenied;
380- }
381- }
382- if (self.configuration [kMPFIRGA4DefaultAnalyticsStorageKey ]) {
383- if ([self .configuration[kMPFIRGA4DefaultAnalyticsStorageKey ] isEqual: @" Granted" ]) {
384- analyticsStorageStatus = FIRConsentStatusGranted;
385- } else if ([self .configuration[kMPFIRGA4DefaultAnalyticsStorageKey ] isEqual: @" Denied" ]) {
386- analyticsStorageStatus = FIRConsentStatusDenied;
387- }
365+ NSArray <NSDictionary *> *mappings = [self mappingForKey: @" consentMappingSDK" ];
366+ NSDictionary <NSString *, NSString *> *mappingsConfig;
367+ if (mappings != nil ) {
368+ mappingsConfig = [self convertToKeyValuePairs: mappings];
388369 }
389- if (self.configuration [kMPFIRGA4DefaultAdPersonalizationKey ]) {
390- if ([self .configuration[kMPFIRGA4DefaultAdPersonalizationKey ] isEqual: @" Granted" ]) {
391- adPersonalizationStatus = FIRConsentStatusGranted;
392- } else if ([self .configuration[kMPFIRGA4DefaultAdPersonalizationKey ] isEqual: @" Denied" ]) {
393- adPersonalizationStatus = FIRConsentStatusDenied;
394- }
395- }
396-
370+
371+
397372 MParticleUser *currentUser = [[[MParticle sharedInstance ] identity ] currentUser ];
398- NSDictionary <NSString *, MPGDPRConsent *> *userConsentMap = currentUser.consentState .gdprConsentState ;
373+ NSDictionary <NSString *, MPGDPRConsent *> *gdprConsents = currentUser.consentState .gdprConsentState ;
399374
400- // Update from mParticle consent
401- if (self.configuration [kMPFIRGA4AdStorageKey ] && userConsentMap[self .configuration[kMPFIRGA4AdStorageKey ]]) {
402- MPGDPRConsent *consent = userConsentMap[self .configuration[kMPFIRGA4AdStorageKey ]];
403- adStorageStatus = consent.consented ? FIRConsentStatusGranted : FIRConsentStatusDenied;
404- }
405- if (self.configuration [kMPFIRGA4AdUserDataKey ] && userConsentMap[self .configuration[kMPFIRGA4AdUserDataKey ]]) {
406- MPGDPRConsent *consent = userConsentMap[self .configuration[kMPFIRGA4AdUserDataKey ]];
407- adUserDataStatus = consent.consented ? FIRConsentStatusGranted : FIRConsentStatusDenied;
408- }
409- if (self.configuration [kMPFIRGA4AnalyticsStorageKey ] && userConsentMap[self .configuration[kMPFIRGA4AnalyticsStorageKey ]]) {
410- MPGDPRConsent *consent = userConsentMap[self .configuration[kMPFIRGA4AnalyticsStorageKey ]];
411- analyticsStorageStatus = consent.consented ? FIRConsentStatusGranted : FIRConsentStatusDenied;
412- }
413- if (self.configuration [kMPFIRGA4AdPersonalizationKey ] && userConsentMap[self .configuration[kMPFIRGA4AdPersonalizationKey ]]) {
414- MPGDPRConsent *consent = userConsentMap[self .configuration[kMPFIRGA4AdPersonalizationKey ]];
415- adPersonalizationStatus = consent.consented ? FIRConsentStatusGranted : FIRConsentStatusDenied;
416- }
375+ NSNumber *adStorage = [self resolvedConsentForMappingKey: kMPFIRGAAdStorageKey
376+ defaultKey: kMPFIRGA4DefaultAdStorageKey
377+ gdprConsents: gdprConsents
378+ mapping: mappingsConfig];
379+
380+ NSNumber *adUserData = [self resolvedConsentForMappingKey: kMPFIRGAAdUserDataKey
381+ defaultKey: kMPFIRGA4DefaultAdUserDataKey
382+ gdprConsents: gdprConsents
383+ mapping: mappingsConfig];
417384
418- // Construct a dictionary of consents
419- NSMutableDictionary *uploadDict = [[NSMutableDictionary alloc ] init ];
420- if (adStorageStatus) {
421- uploadDict[FIRConsentTypeAdStorage] = adStorageStatus;
385+ NSNumber *analyticsStorage = [self resolvedConsentForMappingKey: kMPFIRGAAnalyticsStorageKey
386+ defaultKey: kMPFIRGA4DefaultAnalyticsStorageKey
387+ gdprConsents: gdprConsents
388+ mapping: mappingsConfig];
389+
390+ NSNumber *adPersonalization = [self resolvedConsentForMappingKey: kMPFIRGAAdPersonalizationKey
391+ defaultKey: kMPFIRGA4DefaultAdPersonalizationKey
392+ gdprConsents: gdprConsents
393+ mapping: mappingsConfig];
394+
395+ NSMutableDictionary *uploadDict = [NSMutableDictionary dictionary ];
396+
397+ if (adStorage != nil ) {
398+ uploadDict[FIRConsentTypeAdStorage] = adStorage.boolValue ? FIRConsentStatusGranted : FIRConsentStatusDenied;
422399 }
423- if (adUserDataStatus ) {
424- uploadDict[FIRConsentTypeAdUserData] = adUserDataStatus ;
400+ if (adUserData != nil ) {
401+ uploadDict[FIRConsentTypeAdUserData] = adUserData. boolValue ? FIRConsentStatusGranted : FIRConsentStatusDenied ;
425402 }
426- if (analyticsStorageStatus ) {
427- uploadDict[FIRConsentTypeAnalyticsStorage] = analyticsStorageStatus ;
403+ if (analyticsStorage != nil ) {
404+ uploadDict[FIRConsentTypeAnalyticsStorage] = analyticsStorage. boolValue ? FIRConsentStatusGranted : FIRConsentStatusDenied ;
428405 }
429- if (adPersonalizationStatus ) {
430- uploadDict[FIRConsentTypeAdPersonalization] = adPersonalizationStatus ;
406+ if (adPersonalization != nil ) {
407+ uploadDict[FIRConsentTypeAdPersonalization] = adPersonalization. boolValue ? FIRConsentStatusGranted : FIRConsentStatusDenied ;
431408 }
432-
409+
410+
433411 // Update consent state with FIRAnalytics
434412 [FIRAnalytics setConsent: uploadDict];
435413}
@@ -654,4 +632,60 @@ - (void)updateInstanceIDIntegration {
654632 }
655633}
656634
635+ #pragma mark - Helpers
636+
637+ - (NSNumber * _Nullable)resolvedConsentForMappingKey : (NSString *)mappingKey
638+ defaultKey : (NSString *)defaultKey
639+ gdprConsents : (NSDictionary <NSString *, MPGDPRConsent *> *)gdprConsents
640+ mapping : (NSDictionary <NSString *, NSString*> *) mapping {
641+
642+ // Prefer mParticle Consent if available
643+ NSString *purpose = mapping[mappingKey];
644+ if (purpose) {
645+ MPGDPRConsent *consent = gdprConsents[purpose];
646+ if (consent) {
647+ return @(consent.consented );
648+ }
649+ }
650+
651+ // Fallback to configuration defaults
652+ NSString *value = self->_configuration [defaultKey];
653+ if ([value isEqualToString: @" Granted" ]) {
654+ return @(YES );
655+ } else if ([value isEqualToString: @" Denied" ]) {
656+ return @(NO );
657+ }
658+ return nil ;
659+ }
660+
661+ - (NSArray <NSDictionary *>*)mappingForKey : (NSString *)key {
662+ NSString *mappingJson = _configuration[@" consentMappingSDK" ];
663+ if (![mappingJson isKindOfClass: [NSString class ]]) {
664+ return nil ;
665+ }
666+
667+ NSData *jsonData = [mappingJson dataUsingEncoding: NSUTF8StringEncoding];
668+ NSError *error;
669+ NSArray *result = [NSJSONSerialization JSONObjectWithData: jsonData options: 0 error: &error];
670+
671+ if (error) {
672+ NSLog (@" Failed to parse consent mapping JSON: %@ " , error.localizedDescription );
673+ return nil ;
674+ }
675+
676+ return result;
677+ }
678+
679+ - (NSDictionary *)convertToKeyValuePairs : (NSArray <NSDictionary *>*) mappings {
680+ NSMutableDictionary *dict = [NSMutableDictionary dictionary ];
681+ for (NSDictionary *entry in mappings) {
682+ NSString *value = entry[@" value" ];
683+ NSString *purpose = [entry[@" map" ] lowercaseString ];
684+ if (value && purpose) {
685+ dict[value] = purpose;
686+ }
687+ }
688+ return dict;
689+ }
690+
657691@end
0 commit comments