FIRIAMAnalyticsEventLoggerImpl.m 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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 "FIRIAMAnalyticsEventLoggerImpl.h"
  17. #import "FIRCore+InAppMessaging.h"
  18. #import "FIRIAMClearcutLogger.h"
  19. #import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
  20. #import "Interop/Analytics/Public/FIRAnalyticsInterop.h"
  21. typedef void (^FIRAUserPropertiesCallback)(NSDictionary *userProperties);
  22. @interface FIRIAMAnalyticsEventLoggerImpl ()
  23. @property(readonly, nonatomic) FIRIAMClearcutLogger *clearCutLogger;
  24. @property(readonly, nonatomic) id<FIRIAMTimeFetcher> timeFetcher;
  25. @property(nonatomic, readonly) NSUserDefaults *userDefaults;
  26. @end
  27. // in these kFAXX constants, FA represents FirebaseAnalytics
  28. static NSString *const kFIREventOriginFIAM = @"fiam";
  29. ;
  30. static NSString *const kFAEventNameForImpression = @"firebase_in_app_message_impression";
  31. static NSString *const kFAEventNameForAction = @"firebase_in_app_message_action";
  32. static NSString *const kFAEventNameForDismiss = @"firebase_in_app_message_dismiss";
  33. // In order to support tracking conversions from clicking a fiam event, we need to set
  34. // an analytics user property with the fiam message's campaign id.
  35. // This is the user property as kFIRUserPropertyLastNotification defined for FCM.
  36. // Unlike FCM, FIAM would only allow the user property to exist up to certain expiration time
  37. // after which, we stop attributing any further conversions to that fiam message click.
  38. // So we include kFAUserPropertyPrefixForFIAM as the prefix for the entry written by fiam SDK
  39. // to avoid removing entries written by FCM SDK
  40. static NSString *const kFAUserPropertyForLastNotification = @"_ln";
  41. static NSString *const kFAUserPropertyPrefixForFIAM = @"fiam:";
  42. // This user defaults key is for the entry to tell when we should remove the private user
  43. // property from a prior action url click to stop conversion attribution for a campaign
  44. static NSString *const kFIAMUserDefaualtsKeyForRemoveUserPropertyTimeInSeconds =
  45. @"firebase-iam-conversion-tracking-expires-in-seconds";
  46. @implementation FIRIAMAnalyticsEventLoggerImpl {
  47. id<FIRAnalyticsInterop> _analytics;
  48. }
  49. - (instancetype)initWithClearcutLogger:(FIRIAMClearcutLogger *)ctLogger
  50. usingTimeFetcher:(id<FIRIAMTimeFetcher>)timeFetcher
  51. usingUserDefaults:(nullable NSUserDefaults *)userDefaults
  52. analytics:(nullable id<FIRAnalyticsInterop>)analytics {
  53. if (self = [super init]) {
  54. _clearCutLogger = ctLogger;
  55. _timeFetcher = timeFetcher;
  56. _analytics = analytics;
  57. _userDefaults = userDefaults ? userDefaults : [NSUserDefaults standardUserDefaults];
  58. if (!_analytics) {
  59. FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM280002",
  60. @"Firebase In App Messaging was not configured with FirebaseAnalytics.");
  61. }
  62. }
  63. return self;
  64. }
  65. - (NSDictionary *)constructFAEventParamsWithCampaignID:(NSString *)campaignID
  66. campaignName:(NSString *)campaignName {
  67. // event parameter names are aligned with definitions in event_names_util.cc
  68. return @{
  69. @"_nmn" : campaignName ?: @"unknown",
  70. @"_nmid" : campaignID ?: @"unknown",
  71. @"_ndt" : @([self.timeFetcher currentTimestampInSeconds])
  72. };
  73. }
  74. - (void)logFAEventsForMessageImpressionWithcampaignID:(NSString *)campaignID
  75. campaignName:(NSString *)campaignName {
  76. if (_analytics) {
  77. FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM280001",
  78. @"Log campaign impression Firebase Analytics event for campaign ID %@", campaignID);
  79. NSDictionary *params = [self constructFAEventParamsWithCampaignID:campaignID
  80. campaignName:campaignName];
  81. [_analytics logEventWithOrigin:kFIREventOriginFIAM
  82. name:kFAEventNameForImpression
  83. parameters:params];
  84. }
  85. }
  86. - (BOOL)setAnalyticsUserPropertyForKey:(NSString *)key withValue:(NSString *)value {
  87. if (!_analytics || !key || !value) {
  88. return NO;
  89. }
  90. [_analytics setUserPropertyWithOrigin:kFIREventOriginFIAM name:key value:value];
  91. return YES;
  92. }
  93. - (void)logFAEventsForMessageActionWithCampaignID:(NSString *)campaignID
  94. campaignName:(NSString *)campaignName {
  95. if (_analytics) {
  96. FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM280004",
  97. @"Log action click Firebase Analytics event for campaign ID %@", campaignID);
  98. NSDictionary *params = [self constructFAEventParamsWithCampaignID:campaignID
  99. campaignName:campaignName];
  100. [_analytics logEventWithOrigin:kFIREventOriginFIAM
  101. name:kFAEventNameForAction
  102. parameters:params];
  103. }
  104. // set a special user property so that conversion events can be queried based on that
  105. // for reporting purpose
  106. NSString *conversionTrackingUserPropertyValue =
  107. [NSString stringWithFormat:@"%@%@", kFAUserPropertyPrefixForFIAM, campaignID];
  108. if ([self setAnalyticsUserPropertyForKey:kFAUserPropertyForLastNotification
  109. withValue:conversionTrackingUserPropertyValue]) {
  110. FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM280009",
  111. @"User property for conversion tracking was set for campaign %@", campaignID);
  112. }
  113. }
  114. - (void)logFAEventsForMessageDismissWithcampaignID:(NSString *)campaignID
  115. campaignName:(NSString *)campaignName {
  116. if (_analytics) {
  117. FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM280007",
  118. @"Log message dismiss Firebase Analytics event for campaign ID %@", campaignID);
  119. NSDictionary *params = [self constructFAEventParamsWithCampaignID:campaignID
  120. campaignName:campaignName];
  121. [_analytics logEventWithOrigin:kFIREventOriginFIAM
  122. name:kFAEventNameForDismiss
  123. parameters:params];
  124. }
  125. }
  126. - (void)logAnalyticsEventForType:(FIRIAMAnalyticsLogEventType)eventType
  127. forCampaignID:(NSString *)campaignID
  128. withCampaignName:(NSString *)campaignName
  129. eventTimeInMs:(nullable NSNumber *)eventTimeInMs
  130. completion:(void (^)(BOOL success))completion {
  131. // log Firebase Analytics event first
  132. if (eventType == FIRIAMAnalyticsEventMessageImpression) {
  133. [self logFAEventsForMessageImpressionWithcampaignID:campaignID campaignName:campaignName];
  134. } else if (eventType == FIRIAMAnalyticsEventActionURLFollow) {
  135. [self logFAEventsForMessageActionWithCampaignID:campaignID campaignName:campaignName];
  136. } else if (eventType == FIRIAMAnalyticsEventMessageDismissAuto ||
  137. eventType == FIRIAMAnalyticsEventMessageDismissClick) {
  138. [self logFAEventsForMessageDismissWithcampaignID:campaignID campaignName:campaignName];
  139. }
  140. // and do clearcut logging as well
  141. [self.clearCutLogger logAnalyticsEventForType:eventType
  142. forCampaignID:campaignID
  143. withCampaignName:campaignName
  144. eventTimeInMs:eventTimeInMs
  145. completion:completion];
  146. }
  147. @end