FIRIAMAnalyticsEventLoggerImpl.m 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * Copyright 2018 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <TargetConditionals.h>
  17. #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_VISION
  18. #import <GoogleUtilities/GULUserDefaults.h>
  19. #import "FirebaseInAppMessaging/Sources/Analytics/FIRIAMAnalyticsEventLoggerImpl.h"
  20. #import "FirebaseCore/Extension/FirebaseCoreInternal.h"
  21. #import "FirebaseInAppMessaging/Sources/FIRCore+InAppMessaging.h"
  22. #import "FirebaseInAppMessaging/Sources/Private/Analytics/FIRIAMClearcutLogger.h"
  23. #import "Interop/Analytics/Public/FIRAnalyticsInterop.h"
  24. typedef void (^FIRAUserPropertiesCallback)(NSDictionary *userProperties);
  25. @interface FIRIAMAnalyticsEventLoggerImpl ()
  26. @property(readonly, nonatomic) FIRIAMClearcutLogger *clearCutLogger;
  27. @property(readonly, nonatomic) id<FIRIAMTimeFetcher> timeFetcher;
  28. @property(nonatomic, readonly) GULUserDefaults *userDefaults;
  29. @end
  30. // in these kFAXX constants, FA represents FirebaseAnalytics
  31. static NSString *const kFIREventOriginFIAM = @"fiam";
  32. ;
  33. static NSString *const kFAEventNameForImpression = @"firebase_in_app_message_impression";
  34. static NSString *const kFAEventNameForAction = @"firebase_in_app_message_action";
  35. static NSString *const kFAEventNameForDismiss = @"firebase_in_app_message_dismiss";
  36. // In order to support tracking conversions from clicking a fiam event, we need to set
  37. // an analytics user property with the fiam message's campaign id.
  38. // This is the user property as kFIRUserPropertyLastNotification defined for FCM.
  39. // Unlike FCM, FIAM would only allow the user property to exist up to certain expiration time
  40. // after which, we stop attributing any further conversions to that fiam message click.
  41. // So we include kFAUserPropertyPrefixForFIAM as the prefix for the entry written by fiam SDK
  42. // to avoid removing entries written by FCM SDK
  43. static NSString *const kFAUserPropertyForLastNotification = @"_ln";
  44. static NSString *const kFAUserPropertyPrefixForFIAM = @"fiam:";
  45. @implementation FIRIAMAnalyticsEventLoggerImpl {
  46. id<FIRAnalyticsInterop> _analytics;
  47. }
  48. - (instancetype)initWithClearcutLogger:(FIRIAMClearcutLogger *)ctLogger
  49. usingTimeFetcher:(id<FIRIAMTimeFetcher>)timeFetcher
  50. usingUserDefaults:(nullable GULUserDefaults *)userDefaults
  51. analytics:(nullable id<FIRAnalyticsInterop>)analytics {
  52. if (self = [super init]) {
  53. _clearCutLogger = ctLogger;
  54. _timeFetcher = timeFetcher;
  55. _analytics = analytics;
  56. _userDefaults = userDefaults ? userDefaults : [GULUserDefaults standardUserDefaults];
  57. if (!_analytics) {
  58. FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM280002",
  59. @"Firebase In App Messaging was not configured with FirebaseAnalytics.");
  60. }
  61. }
  62. return self;
  63. }
  64. - (NSDictionary *)constructFAEventParamsWithCampaignID:(NSString *)campaignID
  65. campaignName:(NSString *)campaignName {
  66. // event parameter names are aligned with definitions in event_names_util.cc
  67. return @{
  68. @"_nmn" : campaignName ?: @"unknown",
  69. @"_nmid" : campaignID ?: @"unknown",
  70. @"_ndt" : @([self.timeFetcher currentTimestampInSeconds])
  71. };
  72. }
  73. - (void)logFAEventsForMessageImpressionWithcampaignID:(NSString *)campaignID
  74. campaignName:(NSString *)campaignName {
  75. if (_analytics) {
  76. FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM280001",
  77. @"Log campaign impression Firebase Analytics event for campaign ID %@", campaignID);
  78. NSDictionary *params = [self constructFAEventParamsWithCampaignID:campaignID
  79. campaignName:campaignName];
  80. [_analytics logEventWithOrigin:kFIREventOriginFIAM
  81. name:kFAEventNameForImpression
  82. parameters:params];
  83. }
  84. }
  85. - (BOOL)setAnalyticsUserPropertyForKey:(NSString *)key withValue:(NSString *)value {
  86. if (!_analytics || !key || !value) {
  87. return NO;
  88. }
  89. [_analytics setUserPropertyWithOrigin:kFIREventOriginFIAM name:key value:value];
  90. return YES;
  91. }
  92. - (void)logFAEventsForMessageActionWithCampaignID:(NSString *)campaignID
  93. campaignName:(NSString *)campaignName {
  94. if (_analytics) {
  95. FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM280004",
  96. @"Log action click Firebase Analytics event for campaign ID %@", campaignID);
  97. NSDictionary *params = [self constructFAEventParamsWithCampaignID:campaignID
  98. campaignName:campaignName];
  99. [_analytics logEventWithOrigin:kFIREventOriginFIAM
  100. name:kFAEventNameForAction
  101. parameters:params];
  102. }
  103. }
  104. - (void)logConversionTrackingEventForCampaignID:(NSString *)campaignID {
  105. // Set a special user property so that conversion events can be queried based on that
  106. // for reporting purposes.
  107. NSString *conversionTrackingUserPropertyValue =
  108. [NSString stringWithFormat:@"%@%@", kFAUserPropertyPrefixForFIAM, campaignID];
  109. if ([self setAnalyticsUserPropertyForKey:kFAUserPropertyForLastNotification
  110. withValue:conversionTrackingUserPropertyValue]) {
  111. FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM280009",
  112. @"User property for conversion tracking was set for campaign %@", campaignID);
  113. }
  114. }
  115. - (void)logFAEventsForMessageDismissWithcampaignID:(NSString *)campaignID
  116. campaignName:(NSString *)campaignName {
  117. if (_analytics) {
  118. FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM280007",
  119. @"Log message dismiss Firebase Analytics event for campaign ID %@", campaignID);
  120. NSDictionary *params = [self constructFAEventParamsWithCampaignID:campaignID
  121. campaignName:campaignName];
  122. [_analytics logEventWithOrigin:kFIREventOriginFIAM
  123. name:kFAEventNameForDismiss
  124. parameters:params];
  125. }
  126. }
  127. - (void)logAnalyticsEventForType:(FIRIAMAnalyticsLogEventType)eventType
  128. forCampaignID:(NSString *)campaignID
  129. withCampaignName:(NSString *)campaignName
  130. eventTimeInMs:(nullable NSNumber *)eventTimeInMs
  131. completion:(void (^)(BOOL success))completion {
  132. // log Firebase Analytics event first
  133. if (eventType == FIRIAMAnalyticsEventMessageImpression) {
  134. [self logFAEventsForMessageImpressionWithcampaignID:campaignID campaignName:campaignName];
  135. } else if (eventType == FIRIAMAnalyticsEventActionURLFollow) {
  136. [self logFAEventsForMessageActionWithCampaignID:campaignID campaignName:campaignName];
  137. } else if (eventType == FIRIAMAnalyticsEventMessageDismissAuto ||
  138. eventType == FIRIAMAnalyticsEventMessageDismissClick) {
  139. [self logFAEventsForMessageDismissWithcampaignID:campaignID campaignName:campaignName];
  140. }
  141. // and do clearcut logging as well
  142. [self.clearCutLogger logAnalyticsEventForType:eventType
  143. forCampaignID:campaignID
  144. withCampaignName:campaignName
  145. eventTimeInMs:eventTimeInMs
  146. completion:completion];
  147. }
  148. @end
  149. #endif // TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_VISION