You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
8.3 KiB
218 lines
8.3 KiB
/*
|
|
* 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/GULAppEnvironmentUtil.h>
|
|
#import <GoogleUtilities/GULAppDelegateSwizzler.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
|