FIRIAMAnalyticsEventLoggerImpl.m 7.8 KB

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