| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- /*
- * Copyright 2018 Google
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #import "Firebase/Messaging/FIRMessagingAnalytics.h"
- #import <FirebaseAnalyticsInterop/FIRInteropEventNames.h>
- #import <FirebaseAnalyticsInterop/FIRInteropParameterNames.h>
- #import <GoogleUtilities/GULAppDelegateSwizzler.h>
- #import <GoogleUtilities/GULAppEnvironmentUtil.h>
- #import "Firebase/Messaging/FIRMessagingLogger.h"
- static NSString *const kLogTag = @"FIRMessagingAnalytics";
- // aps Key
- static NSString *const kApsKey = @"aps";
- static NSString *const kApsAlertKey = @"alert";
- static NSString *const kApsSoundKey = @"sound";
- static NSString *const kApsBadgeKey = @"badge";
- static NSString *const kApsContentAvailableKey = @"badge";
- // Data Key
- static NSString *const kDataKey = @"data";
- // Messaging From Key
- static NSString *const kFIRMessagingFromKey = @"from";
- static NSString *const kFIRParameterLabel = @"label";
- static NSString *const kReengagementSource = @"Firebase";
- static NSString *const kReengagementMedium = @"notification";
- // Analytics
- static NSString *const kAnalyticsEnabled = @"google.c.a."
- @"e";
- static NSString *const kAnalyticsComposerIdentifier = @"google.c.a."
- @"c_id";
- static NSString *const kAnalyticsComposerLabel = @"google.c.a."
- @"c_l";
- static NSString *const kAnalyticsMessageLabel = @"google.c.a."
- @"m_l";
- static NSString *const kAnalyticsMessageTimestamp = @"google.c.a."
- @"ts";
- static NSString *const kAnalyticsMessageUseDeviceTime = @"google.c.a."
- @"udt";
- static NSString *const kAnalyticsTrackConversions = @"google.c.a."
- @"tc";
- @implementation FIRMessagingAnalytics
- + (BOOL)canLogNotification:(NSDictionary *)notification {
- if (!notification.count) {
- // Payload is empty
- return NO;
- }
- NSString *isAnalyticsLoggingEnabled = notification[kAnalyticsEnabled];
- if (![isAnalyticsLoggingEnabled isKindOfClass:[NSString class]] ||
- ![isAnalyticsLoggingEnabled isEqualToString:@"1"]) {
- // Analytics logging is not enabled
- FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics001,
- @"Analytics logging is disabled. Do not log event.");
- return NO;
- }
- return YES;
- }
- + (void)logOpenNotification:(NSDictionary *)notification
- toAnalytics:(id<FIRAnalyticsInterop> _Nullable)analytics {
- [self logUserPropertyForConversionTracking:notification toAnalytics:analytics];
- [self logEvent:kFIRIEventNotificationOpen withNotification:notification toAnalytics:analytics];
- }
- + (void)logForegroundNotification:(NSDictionary *)notification
- toAnalytics:(id<FIRAnalyticsInterop> _Nullable)analytics {
- [self logEvent:kFIRIEventNotificationForeground
- withNotification:notification
- toAnalytics:analytics];
- }
- + (void)logEvent:(NSString *)event
- withNotification:(NSDictionary *)notification
- toAnalytics:(id<FIRAnalyticsInterop> _Nullable)analytics {
- if (!event.length) {
- FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalyticsInvalidEvent,
- @"Can't log analytics with empty event.");
- return;
- }
- NSMutableDictionary *params = [self paramsForEvent:event withNotification:notification];
- [analytics logEventWithOrigin:@"fcm" name:event parameters:params];
- FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics005, @"%@: Sending event: %@ params: %@",
- kLogTag, event, params);
- }
- + (NSMutableDictionary *)paramsForEvent:(NSString *)event
- withNotification:(NSDictionary *)notification {
- NSDictionary *analyticsDataMap = notification;
- if (!analyticsDataMap.count) {
- FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics000,
- @"No data found in notification. Will not log any analytics events.");
- return nil;
- }
- if (![self canLogNotification:analyticsDataMap]) {
- return nil;
- }
- NSMutableDictionary *params = [NSMutableDictionary dictionary];
- NSString *composerIdentifier = analyticsDataMap[kAnalyticsComposerIdentifier];
- if ([composerIdentifier isKindOfClass:[NSString class]] && composerIdentifier.length) {
- params[kFIRIParameterMessageIdentifier] = [composerIdentifier copy];
- }
- NSString *composerLabel = analyticsDataMap[kAnalyticsComposerLabel];
- if ([composerLabel isKindOfClass:[NSString class]] && composerLabel.length) {
- params[kFIRIParameterMessageName] = [composerLabel copy];
- }
- NSString *messageLabel = analyticsDataMap[kAnalyticsMessageLabel];
- if ([messageLabel isKindOfClass:[NSString class]] && messageLabel.length) {
- params[kFIRParameterLabel] = [messageLabel copy];
- }
- NSString *from = analyticsDataMap[kFIRMessagingFromKey];
- if ([from isKindOfClass:[NSString class]] && [from containsString:@"/topics/"]) {
- params[kFIRIParameterTopic] = [from copy];
- }
- id timestamp = analyticsDataMap[kAnalyticsMessageTimestamp];
- if ([timestamp respondsToSelector:@selector(longLongValue)]) {
- int64_t timestampValue = [timestamp longLongValue];
- if (timestampValue != 0) {
- params[kFIRIParameterMessageTime] = @(timestampValue);
- }
- }
- if (analyticsDataMap[kAnalyticsMessageUseDeviceTime]) {
- params[kFIRIParameterMessageDeviceTime] = analyticsDataMap[kAnalyticsMessageUseDeviceTime];
- }
- return params;
- }
- + (void)logUserPropertyForConversionTracking:(NSDictionary *)notification
- toAnalytics:(id<FIRAnalyticsInterop> _Nullable)analytics {
- NSInteger shouldTrackConversions = [notification[kAnalyticsTrackConversions] integerValue];
- if (shouldTrackConversions != 1) {
- return;
- }
- NSString *composerIdentifier = notification[kAnalyticsComposerIdentifier];
- if ([composerIdentifier isKindOfClass:[NSString class]] && composerIdentifier.length) {
- // Set user property for event.
- [analytics setUserPropertyWithOrigin:@"fcm"
- name:kFIRIUserPropertyLastNotification
- value:composerIdentifier];
- // Set the re-engagement attribution properties.
- NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:3];
- params[kFIRIParameterSource] = kReengagementSource;
- params[kFIRIParameterMedium] = kReengagementMedium;
- params[kFIRIParameterCampaign] = composerIdentifier;
- [analytics logEventWithOrigin:@"fcm" name:kFIRIEventFirebaseCampaign parameters:params];
- FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics003,
- @"%@: Sending event: %@ params: %@", kLogTag,
- kFIRIEventFirebaseCampaign, params);
- } else {
- FIRMessagingLoggerDebug(kFIRMessagingMessageCodeAnalytics004,
- @"%@: Failed to set user property: %@ value: %@", kLogTag,
- kFIRIUserPropertyLastNotification, composerIdentifier);
- }
- }
- + (void)logMessage:(NSDictionary *)notification
- toAnalytics:(id<FIRAnalyticsInterop> _Nullable)analytics {
- // iOS onlly because Analytics doesn't support tvOS.
- #if TARGET_OS_IOS
- if (![self canLogNotification:notification]) {
- return;
- }
- UIApplication *application = [GULAppDelegateSwizzler sharedApplication];
- if (!application) {
- return;
- }
- UIApplicationState applicationState = application.applicationState;
- switch (applicationState) {
- case UIApplicationStateInactive:
- // App was either in background(suspended) or inactive and user tapped on a display
- // notification.
- [self logOpenNotification:notification toAnalytics:analytics];
- break;
- case UIApplicationStateActive:
- // App was in foreground when it received the notification.
- [self logForegroundNotification:notification toAnalytics:analytics];
- break;
- default:
- // Only a silent notification (i.e. 'content-available' is true) can be received while the app
- // is in the background. These messages aren't loggable anyway.
- break;
- }
- #endif
- }
- @end
|