Skip to content

Commit 78d898b

Browse files
feat: Support Google Consent (#26)
* feat: Support Google Consent
1 parent 47d37d1 commit 78d898b

File tree

2 files changed

+97
-2
lines changed

2 files changed

+97
-2
lines changed

mParticle-Google-Analytics-Firebase-GA4.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ Pod::Spec.new do |s|
1919
s.ios.dependency 'mParticle-Apple-SDK/mParticle', '~> 8.0'
2020
s.ios.frameworks = 'CoreTelephony', 'SystemConfiguration'
2121
s.libraries = 'z'
22-
s.ios.dependency 'Firebase/Core', '~> 10.6'
22+
s.ios.dependency 'Firebase/Core', '~> 10.23'
2323

2424
s.tvos.deployment_target = "12.0"
2525
s.tvos.source_files = 'mParticle-Google-Analytics-Firebase-GA4/*.{h,m,mm}'
2626
s.tvos.dependency 'mParticle-Apple-SDK/mParticle', '~> 8.0'
2727
s.tvos.frameworks = 'SystemConfiguration'
2828
s.libraries = 'z'
29-
s.tvos.dependency 'Firebase/Core', '~> 10.6'
29+
s.tvos.dependency 'Firebase/Core', '~> 10.23'
3030

3131
end

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

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
#if __has_include(<FirebaseCore/FirebaseCore.h>)
66
#import <FirebaseCore/FirebaseCore.h>
77
#import <FirebaseAnalytics/FIRAnalytics.h>
8+
#import <FirebaseAnalytics/FIRAnalytics+Consent.h>
89
#else
910
#import "FirebaseCore/FirebaseCore.h"
1011
#import "FirebaseAnalytics/FIRAnalytics.h"
12+
#import "FirebaseAnalytics/FIRAnalytics+Consent.h"
1113
#endif
1214
#endif
1315

@@ -42,6 +44,15 @@ @implementation MPKitFirebaseGA4Analytics
4244
static NSString *const instanceIdIntegrationKey = @"app_instance_id";
4345
static NSString *const invalidFirebaseKey = @"invalid_ga4_key";
4446

47+
static NSString *const kMPFIRGA4AdStorageKey = @"ad_storage";
48+
static NSString *const kMPFIRGA4AdUserDataKey = @"ad_user_data";
49+
static NSString *const kMPFIRGA4AdPersonalizationKey = @"ad_personalization";
50+
static NSString *const kMPFIRGA4AnalyticsStorageKey = @"analytics_storage";
51+
static NSString *const kMPFIRGA4DefaultAdStorageKey = @"defaultAdStorageConsentSDK";
52+
static NSString *const kMPFIRGA4DefaultAdUserDataKey = @"defaultAdUserDataConsentSDK";
53+
static NSString *const kMPFIRGA4DefaultAdPersonalizationKey = @"defaultAdPersonalizationConsentSDK";
54+
static NSString *const kMPFIRGA4DefaultAnalyticsStorageKey = @"defaultAnalyticsStorageConsentSDK";
55+
4556
// Following limits are based off Google Analytics 360 limits, docs here "https://support.google.com/analytics/answer/11202874?sjid=14644072134282618832-NA#limits"
4657
const NSInteger FIR_MAX_CHARACTERS_EVENT_NAME = 40;
4758
const NSInteger FIR_MAX_CHARACTERS_IDENTITY_NAME = 24;
@@ -87,6 +98,8 @@ - (MPKitExecStatus *)didFinishLaunchingWithConfiguration:(NSDictionary *)configu
8798

8899
[self updateInstanceIDIntegration];
89100

101+
[self updateConsent];
102+
90103
_started = YES;
91104

92105
dispatch_async(dispatch_get_main_queue(), ^{
@@ -358,6 +371,88 @@ - (void)logUserAttributes:(NSDictionary<NSString *, id> *)userAttributes {
358371
}
359372
}
360373

374+
- (MPKitExecStatus *)setConsentState:(nullable MPConsentState *)state {
375+
[self updateConsent];
376+
377+
return [self execStatus:MPKitReturnCodeSuccess];
378+
}
379+
380+
- (void)updateConsent {
381+
FIRConsentStatus adStorageStatus;
382+
FIRConsentStatus adUserDataStatus;
383+
FIRConsentStatus analyticsStorageStatus;
384+
FIRConsentStatus adPersonalizationStatus;
385+
386+
// Default Consent States
387+
if (self.configuration[kMPFIRGA4DefaultAdStorageKey]) {
388+
if ([self.configuration[kMPFIRGA4DefaultAdStorageKey] isEqual: @"Granted"]) {
389+
adStorageStatus = FIRConsentStatusGranted;
390+
} else if ([self.configuration[kMPFIRGA4DefaultAdStorageKey] isEqual: @"Denied"]) {
391+
adStorageStatus = FIRConsentStatusDenied;
392+
}
393+
}
394+
if (self.configuration[kMPFIRGA4DefaultAdUserDataKey]) {
395+
if ([self.configuration[kMPFIRGA4DefaultAdUserDataKey] isEqual: @"Granted"]) {
396+
adUserDataStatus = FIRConsentStatusGranted;
397+
} else if ([self.configuration[kMPFIRGA4DefaultAdUserDataKey] isEqual: @"Denied"]) {
398+
adUserDataStatus = FIRConsentStatusDenied;
399+
}
400+
}
401+
if (self.configuration[kMPFIRGA4DefaultAnalyticsStorageKey]) {
402+
if ([self.configuration[kMPFIRGA4DefaultAnalyticsStorageKey] isEqual: @"Granted"]) {
403+
analyticsStorageStatus = FIRConsentStatusGranted;
404+
} else if ([self.configuration[kMPFIRGA4DefaultAnalyticsStorageKey] isEqual: @"Denied"]) {
405+
analyticsStorageStatus = FIRConsentStatusDenied;
406+
}
407+
}
408+
if (self.configuration[kMPFIRGA4DefaultAdPersonalizationKey]) {
409+
if ([self.configuration[kMPFIRGA4DefaultAdPersonalizationKey] isEqual: @"Granted"]) {
410+
adPersonalizationStatus = FIRConsentStatusGranted;
411+
} else if ([self.configuration[kMPFIRGA4DefaultAdPersonalizationKey] isEqual: @"Denied"]) {
412+
adPersonalizationStatus = FIRConsentStatusDenied;
413+
}
414+
}
415+
416+
MParticleUser *currentUser = [[[MParticle sharedInstance] identity] currentUser];
417+
NSDictionary<NSString *, MPGDPRConsent *> *userConsentMap = currentUser.consentState.gdprConsentState;
418+
419+
// Update from mParticle consent
420+
if (self.configuration[kMPFIRGA4AdStorageKey] && userConsentMap[self.configuration[kMPFIRGA4AdStorageKey]]) {
421+
MPGDPRConsent *consent = userConsentMap[self.configuration[kMPFIRGA4AdStorageKey]];
422+
adStorageStatus = consent.consented ? FIRConsentStatusGranted : FIRConsentStatusDenied;
423+
}
424+
if (self.configuration[kMPFIRGA4AdUserDataKey] && userConsentMap[self.configuration[kMPFIRGA4AdUserDataKey]]) {
425+
MPGDPRConsent *consent = userConsentMap[self.configuration[kMPFIRGA4AdUserDataKey]];
426+
adUserDataStatus = consent.consented ? FIRConsentStatusGranted : FIRConsentStatusDenied;
427+
}
428+
if (self.configuration[kMPFIRGA4AnalyticsStorageKey] && userConsentMap[self.configuration[kMPFIRGA4AnalyticsStorageKey]]) {
429+
MPGDPRConsent *consent = userConsentMap[self.configuration[kMPFIRGA4AnalyticsStorageKey]];
430+
analyticsStorageStatus = consent.consented ? FIRConsentStatusGranted : FIRConsentStatusDenied;
431+
}
432+
if (self.configuration[kMPFIRGA4AdPersonalizationKey] && userConsentMap[self.configuration[kMPFIRGA4AdPersonalizationKey]]) {
433+
MPGDPRConsent *consent = userConsentMap[self.configuration[kMPFIRGA4AdPersonalizationKey]];
434+
adPersonalizationStatus = consent.consented ? FIRConsentStatusGranted : FIRConsentStatusDenied;
435+
}
436+
437+
// Construct a dictionary of consents
438+
NSMutableDictionary *uploadDict = [[NSMutableDictionary alloc] init];
439+
if (adStorageStatus) {
440+
uploadDict[FIRConsentTypeAdStorage] = adStorageStatus;
441+
}
442+
if (adUserDataStatus) {
443+
uploadDict[FIRConsentTypeAdUserData] = adUserDataStatus;
444+
}
445+
if (analyticsStorageStatus) {
446+
uploadDict[FIRConsentTypeAnalyticsStorage] = analyticsStorageStatus;
447+
}
448+
if (adPersonalizationStatus) {
449+
uploadDict[FIRConsentTypeAdPersonalization] = adPersonalizationStatus;
450+
}
451+
452+
// Update consent state with FIRAnalytics
453+
[FIRAnalytics setConsent:uploadDict];
454+
}
455+
361456
- (NSString *)getEventNameForCommerceEvent:(MPCommerceEvent *)commerceEvent parameters:(NSDictionary<NSString *, id> *)parameters {
362457
switch (commerceEvent.action) {
363458
case MPCommerceEventActionAddToCart:

0 commit comments

Comments
 (0)