-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Open source FIAM headless SDK (#2312)
- Loading branch information
1 parent
a43709f
commit 3905bd2
Showing
137 changed files
with
15,462 additions
and
0 deletions.
There are no files selected for viewing
61 changes: 61 additions & 0 deletions
61
Firebase/InAppMessaging/Analytics/FIRIAMAnalyticsEventLogger.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* 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 <Foundation/Foundation.h> | ||
#import "FIRIAMClientInfoFetcher.h" | ||
#import "FIRIAMTimeFetcher.h" | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
/// Values for different fiam activity types. | ||
typedef NS_ENUM(NSInteger, FIRIAMAnalyticsLogEventType) { | ||
|
||
FIRIAMAnalyticsLogEventUnknown = -1, | ||
|
||
FIRIAMAnalyticsEventMessageImpression = 0, | ||
FIRIAMAnalyticsEventActionURLFollow = 1, | ||
FIRIAMAnalyticsEventMessageDismissAuto = 2, | ||
FIRIAMAnalyticsEventMessageDismissClick = 3, | ||
FIRIAMAnalyticsEventMessageDismissSwipe = 4, | ||
|
||
// category: errors happened | ||
FIRIAMAnalyticsEventImageFetchError = 11, | ||
FIRIAMAnalyticsEventImageFormatUnsupported = 12, | ||
|
||
FIRIAMAnalyticsEventFetchAPINetworkError = 13, | ||
FIRIAMAnalyticsEventFetchAPIClientError = 14, // server returns 4xx status code | ||
FIRIAMAnalyticsEventFetchAPIServerError = 15, // server returns 5xx status code | ||
|
||
// Events for test messages | ||
FIRIAMAnalyticsEventTestMessageImpression = 16, | ||
FIRIAMAnalyticsEventTestMessageClick = 17, | ||
}; | ||
|
||
// a protocol for collecting Analytics log records. It's implementation will decide | ||
// what to do with that analytics log record | ||
@protocol FIRIAMAnalyticsEventLogger | ||
/** | ||
* Adds an analytics log record. | ||
* @param eventTimeInMs the timestamp in ms for when the event happened. | ||
* if it's nil, the implementation will use the current system for this info. | ||
*/ | ||
- (void)logAnalyticsEventForType:(FIRIAMAnalyticsLogEventType)eventType | ||
forCampaignID:(NSString *)campaignID | ||
withCampaignName:(NSString *)campaignName | ||
eventTimeInMs:(nullable NSNumber *)eventTimeInMs | ||
completion:(void (^)(BOOL success))completion; | ||
@end | ||
NS_ASSUME_NONNULL_END |
45 changes: 45 additions & 0 deletions
45
Firebase/InAppMessaging/Analytics/FIRIAMAnalyticsEventLoggerImpl.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
* 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 <Foundation/Foundation.h> | ||
|
||
#import "FIRIAMAnalyticsEventLogger.h" | ||
|
||
@class FIRIAMClearcutLogger; | ||
@protocol FIRIAMTimeFetcher; | ||
@protocol FIRAnalyticsInterop; | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
/** | ||
* Implementation of protocol FIRIAMAnalyticsEventLogger by doing two things | ||
* 1 Firing Firebase Analytics Events for impressions and clicks and dismisses | ||
* 2 Making clearcut logging for all other types of analytics events | ||
*/ | ||
@interface FIRIAMAnalyticsEventLoggerImpl : NSObject <FIRIAMAnalyticsEventLogger> | ||
- (instancetype)init NS_UNAVAILABLE; | ||
|
||
/** | ||
* | ||
* @param userDefaults needed for tracking upload timing info persistently.If nil, using | ||
* NSUserDefaults standardUserDefaults. It's defined as a parameter to help with | ||
* unit testing mocking | ||
*/ | ||
- (instancetype)initWithClearcutLogger:(FIRIAMClearcutLogger *)ctLogger | ||
usingTimeFetcher:(id<FIRIAMTimeFetcher>)timeFetcher | ||
usingUserDefaults:(nullable NSUserDefaults *)userDefaults | ||
analytics:(nullable id<FIRAnalyticsInterop>)analytics; | ||
@end | ||
NS_ASSUME_NONNULL_END |
170 changes: 170 additions & 0 deletions
170
Firebase/InAppMessaging/Analytics/FIRIAMAnalyticsEventLoggerImpl.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
/* | ||
* 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 "FIRIAMAnalyticsEventLoggerImpl.h" | ||
|
||
#import <FirebaseAnalyticsInterop/FIRAnalyticsInterop.h> | ||
#import <FirebaseCore/FIRLogger.h> | ||
#import "FIRCore+InAppMessaging.h" | ||
#import "FIRIAMClearcutLogger.h" | ||
|
||
typedef void (^FIRAUserPropertiesCallback)(NSDictionary *userProperties); | ||
|
||
@interface FIRIAMAnalyticsEventLoggerImpl () | ||
@property(readonly, nonatomic) FIRIAMClearcutLogger *clearCutLogger; | ||
@property(readonly, nonatomic) id<FIRIAMTimeFetcher> timeFetcher; | ||
@property(nonatomic, readonly) NSUserDefaults *userDefaults; | ||
@end | ||
|
||
// in these kFAXX constants, FA represents FirebaseAnalytics | ||
static NSString *const kFIREventOriginFIAM = @"fiam"; | ||
; | ||
static NSString *const kFAEventNameForImpression = @"firebase_in_app_message_impression"; | ||
static NSString *const kFAEventNameForAction = @"firebase_in_app_message_action"; | ||
static NSString *const kFAEventNameForDismiss = @"firebase_in_app_message_dismiss"; | ||
|
||
// In order to support tracking conversions from clicking a fiam event, we need to set | ||
// an analytics user property with the fiam message's campaign id. | ||
// This is the user property as kFIRUserPropertyLastNotification defined for FCM. | ||
// Unlike FCM, FIAM would only allow the user property to exist up to certain expiration time | ||
// after which, we stop attributing any further conversions to that fiam message click. | ||
// So we include kFAUserPropertyPrefixForFIAM as the prefix for the entry written by fiam SDK | ||
// to avoid removing entries written by FCM SDK | ||
static NSString *const kFAUserPropertyForLastNotification = @"_ln"; | ||
static NSString *const kFAUserPropertyPrefixForFIAM = @"fiam:"; | ||
|
||
// This user defaults key is for the entry to tell when we should remove the private user | ||
// property from a prior action url click to stop conversion attribution for a campaign | ||
static NSString *const kFIAMUserDefaualtsKeyForRemoveUserPropertyTimeInSeconds = | ||
@"firebase-iam-conversion-tracking-expires-in-seconds"; | ||
|
||
@implementation FIRIAMAnalyticsEventLoggerImpl { | ||
id<FIRAnalyticsInterop> _analytics; | ||
} | ||
|
||
- (instancetype)initWithClearcutLogger:(FIRIAMClearcutLogger *)ctLogger | ||
usingTimeFetcher:(id<FIRIAMTimeFetcher>)timeFetcher | ||
usingUserDefaults:(nullable NSUserDefaults *)userDefaults | ||
analytics:(nullable id<FIRAnalyticsInterop>)analytics { | ||
if (self = [super init]) { | ||
_clearCutLogger = ctLogger; | ||
_timeFetcher = timeFetcher; | ||
_analytics = analytics; | ||
_userDefaults = userDefaults ? userDefaults : [NSUserDefaults standardUserDefaults]; | ||
|
||
if (!_analytics) { | ||
FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM280002", | ||
@"Firebase In App Messaging was not configured with FirebaseAnalytics."); | ||
} | ||
} | ||
return self; | ||
} | ||
|
||
- (NSDictionary *)constructFAEventParamsWithCampaignID:(NSString *)campaignID | ||
campaignName:(NSString *)campaignName { | ||
// event parameter names are aligned with definitions in event_names_util.cc | ||
return @{ | ||
@"_nmn" : campaignName ?: @"unknown", | ||
@"_nmid" : campaignID ?: @"unknown", | ||
@"_ndt" : @([self.timeFetcher currentTimestampInSeconds]) | ||
}; | ||
} | ||
|
||
- (void)logFAEventsForMessageImpressionWithcampaignID:(NSString *)campaignID | ||
campaignName:(NSString *)campaignName { | ||
if (_analytics) { | ||
FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM280001", | ||
@"Log campaign impression Firebase Analytics event for campaign ID %@", campaignID); | ||
|
||
NSDictionary *params = [self constructFAEventParamsWithCampaignID:campaignID | ||
campaignName:campaignName]; | ||
[_analytics logEventWithOrigin:kFIREventOriginFIAM | ||
name:kFAEventNameForImpression | ||
parameters:params]; | ||
} | ||
} | ||
|
||
- (BOOL)setAnalyticsUserPropertyForKey:(NSString *)key withValue:(NSString *)value { | ||
if (!_analytics || !key || !value) { | ||
return NO; | ||
} | ||
[_analytics setUserPropertyWithOrigin:kFIREventOriginFIAM name:key value:value]; | ||
return YES; | ||
} | ||
|
||
- (void)logFAEventsForMessageActionWithCampaignID:(NSString *)campaignID | ||
campaignName:(NSString *)campaignName { | ||
if (_analytics) { | ||
FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM280004", | ||
@"Log action click Firebase Analytics event for campaign ID %@", campaignID); | ||
|
||
NSDictionary *params = [self constructFAEventParamsWithCampaignID:campaignID | ||
campaignName:campaignName]; | ||
|
||
[_analytics logEventWithOrigin:kFIREventOriginFIAM | ||
name:kFAEventNameForAction | ||
parameters:params]; | ||
} | ||
|
||
// set a special user property so that conversion events can be queried based on that | ||
// for reporting purpose | ||
NSString *conversionTrackingUserPropertyValue = | ||
[NSString stringWithFormat:@"%@%@", kFAUserPropertyPrefixForFIAM, campaignID]; | ||
|
||
if ([self setAnalyticsUserPropertyForKey:kFAUserPropertyForLastNotification | ||
withValue:conversionTrackingUserPropertyValue]) { | ||
FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM280009", | ||
@"User property for conversion tracking was set for campaign %@", campaignID); | ||
} | ||
} | ||
|
||
- (void)logFAEventsForMessageDismissWithcampaignID:(NSString *)campaignID | ||
campaignName:(NSString *)campaignName { | ||
if (_analytics) { | ||
FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM280007", | ||
@"Log message dismiss Firebase Analytics event for campaign ID %@", campaignID); | ||
|
||
NSDictionary *params = [self constructFAEventParamsWithCampaignID:campaignID | ||
campaignName:campaignName]; | ||
[_analytics logEventWithOrigin:kFIREventOriginFIAM | ||
name:kFAEventNameForDismiss | ||
parameters:params]; | ||
} | ||
} | ||
|
||
- (void)logAnalyticsEventForType:(FIRIAMAnalyticsLogEventType)eventType | ||
forCampaignID:(NSString *)campaignID | ||
withCampaignName:(NSString *)campaignName | ||
eventTimeInMs:(nullable NSNumber *)eventTimeInMs | ||
completion:(void (^)(BOOL success))completion { | ||
// log Firebase Analytics event first | ||
if (eventType == FIRIAMAnalyticsEventMessageImpression) { | ||
[self logFAEventsForMessageImpressionWithcampaignID:campaignID campaignName:campaignName]; | ||
} else if (eventType == FIRIAMAnalyticsEventActionURLFollow) { | ||
[self logFAEventsForMessageActionWithCampaignID:campaignID campaignName:campaignName]; | ||
} else if (eventType == FIRIAMAnalyticsEventMessageDismissAuto || | ||
eventType == FIRIAMAnalyticsEventMessageDismissClick) { | ||
[self logFAEventsForMessageDismissWithcampaignID:campaignID campaignName:campaignName]; | ||
} | ||
|
||
// and do clearcut logging as well | ||
[self.clearCutLogger logAnalyticsEventForType:eventType | ||
forCampaignID:campaignID | ||
withCampaignName:campaignName | ||
eventTimeInMs:eventTimeInMs | ||
completion:completion]; | ||
} | ||
@end |
51 changes: 51 additions & 0 deletions
51
Firebase/InAppMessaging/Analytics/FIRIAMClearcutHttpRequestSender.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* 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 <Foundation/Foundation.h> | ||
|
||
@class FIRIAMClearcutLogRecord; | ||
@protocol FIRIAMTimeFetcher; | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
// class for sending requests to clearcut over its http API | ||
@interface FIRIAMClearcutHttpRequestSender : NSObject | ||
|
||
/** | ||
* Create an FIRIAMClearcutHttpRequestSender instance with specified clearcut server. | ||
* | ||
* @param serverHost API server host. | ||
* @param osMajorVersion detected iOS major version of the current device | ||
*/ | ||
- (instancetype)initWithClearcutHost:(NSString *)serverHost | ||
usingTimeFetcher:(id<FIRIAMTimeFetcher>)timeFetcher | ||
withOSMajorVersion:(NSString *)osMajorVersion; | ||
|
||
/** | ||
* Sends a batch of FIRIAMClearcutLogRecord records to clearcut server. | ||
* @param logs an array of log records to be sent. | ||
* @param completion is the handler to triggered upon completion. 'success' is a bool | ||
* to indicate if the sending is successful. 'shouldRetryLogs' indicates if these | ||
* logs need to be retried later on. On success case, waitTimeInMills is the value | ||
* returned from clearcut server to indicate the minimal wait time before another | ||
* send request can be attempted. | ||
*/ | ||
|
||
- (void)sendClearcutHttpRequestForLogs:(NSArray<FIRIAMClearcutLogRecord *> *)logs | ||
withCompletion:(void (^)(BOOL success, | ||
BOOL shouldRetryLogs, | ||
int64_t waitTimeInMills))completion; | ||
@end | ||
NS_ASSUME_NONNULL_END |
Oops, something went wrong.