diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fd2f0ccf..5a40d6db7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,14 @@ For each release, **Core** (main SDK) changes are listed first, followed by **Ki ## [Unreleased] +### Kits + +#### Rokt + +##### Added + +- Report non-sensitive mParticle public API usage diagnostics when the Rokt kit is active. + ## [9.3.4] - 2026-08-07 ### Kits diff --git a/Kits/rokt/rokt/Package.swift b/Kits/rokt/rokt/Package.swift index 4472a2644..6ca3a9c07 100644 --- a/Kits/rokt/rokt/Package.swift +++ b/Kits/rokt/rokt/Package.swift @@ -9,7 +9,7 @@ let useLocalVersion = ProcessInfo.processInfo.environment["USE_LOCAL_VERSION"] ! let mParticleAppleSDK: Package.Dependency = { if useLocalVersion { - return .package(path: "../../../") + return .package(name: "mparticle-apple-sdk", path: "../../../") } let url = "https://github.com/mParticle/mparticle-apple-sdk" @@ -32,7 +32,7 @@ let package = Package( mParticleAppleSDK, .package( url: "https://github.com/ROKT/rokt-sdk-ios", - .upToNextMajor(from: "5.3.0") + .upToNextMajor(from: "5.3.2") ), .package( url: "https://github.com/ROKT/rokt-contracts-apple.git", diff --git a/Kits/rokt/rokt/Sources/mParticle-Rokt/MPKitRokt.m b/Kits/rokt/rokt/Sources/mParticle-Rokt/MPKitRokt.m index f9c5d4495..20787102b 100644 --- a/Kits/rokt/rokt/Sources/mParticle-Rokt/MPKitRokt.m +++ b/Kits/rokt/rokt/Sources/mParticle-Rokt/MPKitRokt.m @@ -579,6 +579,11 @@ - (NSString *)getSessionId { return [Rokt getSessionId]; } +/// Forwards a bounded public-API-usage diagnostic code from mParticle core into the Rokt SDK. +- (void)logMParticleApiDiagnostic:(NSString *)code { + [Rokt logMParticleApiCall:code additionalInfo:@{}]; +} + + (void)MPLog:(NSString *)string { NSString *msg = [NSString stringWithFormat:@"%@%@", @"MPRokt -> ", string]; if ([[MParticle sharedInstance] environment] == MPEnvironmentDevelopment) { diff --git a/Kits/rokt/rokt/Tests/mParticle-RoktObjCTests/mParticle_RoktTests.m b/Kits/rokt/rokt/Tests/mParticle-RoktObjCTests/mParticle_RoktTests.m index 467e8f75f..ce3de2006 100644 --- a/Kits/rokt/rokt/Tests/mParticle-RoktObjCTests/mParticle_RoktTests.m +++ b/Kits/rokt/rokt/Tests/mParticle-RoktObjCTests/mParticle_RoktTests.m @@ -130,6 +130,16 @@ - (void)testStopResetsKitState { [mockRoktSDK stopMocking]; } +- (void)testLogMParticleApiDiagnostic_forwardsCode { + id mockRoktSDK = OCMClassMock([Rokt class]); + OCMExpect([mockRoktSDK logMParticleApiCall:@"LOG_EVENT" additionalInfo:@{}]); + + [self.kitInstance logMParticleApiDiagnostic:@"LOG_EVENT"]; + + OCMVerifyAll(mockRoktSDK); + [mockRoktSDK stopMocking]; +} + - (void)testStartCanBeCalledAgainAfterStop { id mockRoktSDK = OCMClassMock([Rokt class]); OCMStub([mockRoktSDK close]); diff --git a/Kits/rokt/rokt/mParticle-Rokt.podspec b/Kits/rokt/rokt/mParticle-Rokt.podspec index 54a702de8..ce18fcc4e 100644 --- a/Kits/rokt/rokt/mParticle-Rokt.podspec +++ b/Kits/rokt/rokt/mParticle-Rokt.podspec @@ -15,5 +15,5 @@ Pod::Spec.new do |s| s.ios.resource_bundles = { 'mParticle-Rokt-Privacy' => ['Sources/mParticle-Rokt/PrivacyInfo.xcprivacy'] } s.ios.dependency 'mParticle-Apple-SDK', '~> 9.1' s.ios.dependency 'RoktContracts', '~> 2.0' - s.ios.dependency 'Rokt-Widget', '~> 5.3' + s.ios.dependency 'Rokt-Widget', '~> 5.3.2' end diff --git a/Kits/rokt/rokt/mParticle-Rokt.xcodeproj/project.pbxproj b/Kits/rokt/rokt/mParticle-Rokt.xcodeproj/project.pbxproj index cb03d2299..b80895e75 100644 --- a/Kits/rokt/rokt/mParticle-Rokt.xcodeproj/project.pbxproj +++ b/Kits/rokt/rokt/mParticle-Rokt.xcodeproj/project.pbxproj @@ -382,7 +382,7 @@ repositoryURL = "https://github.com/ROKT/rokt-sdk-ios"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 5.0.0; + minimumVersion = 5.3.2; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/UnitTests/ObjCTests/MPRoktTests.m b/UnitTests/ObjCTests/MPRoktTests.m index 98d69ab6b..ebea29f85 100644 --- a/UnitTests/ObjCTests/MPRoktTests.m +++ b/UnitTests/ObjCTests/MPRoktTests.m @@ -17,9 +17,11 @@ // Test helper class that simulates a kit with getSessionId and handleURLCallback methods @interface MPRoktTestKitInstance : NSObject @property (nonatomic, copy) NSString *sessionIdToReturn; +@property (nonatomic, copy) NSString *lastDiagnosticCode; @property (nonatomic, assign) BOOL handleURLCallbackReturn; @property (nonatomic, strong) NSURL *lastHandleURLCallbackURL; - (NSString *)getSessionId; +- (void)logMParticleApiDiagnostic:(NSString *)code; - (BOOL)handleURLCallback:(NSURL *)url; @end @@ -27,6 +29,9 @@ @implementation MPRoktTestKitInstance - (NSString *)getSessionId { return self.sessionIdToReturn; } +- (void)logMParticleApiDiagnostic:(NSString *)code { + self.lastDiagnosticCode = code; +} - (BOOL)handleURLCallback:(NSURL *)url { self.lastHandleURLCallbackURL = url; return self.handleURLCallbackReturn; @@ -43,6 +48,7 @@ - (void)confirmUser:(NSDictionary *)attributes user:(MPa @end @interface MPRokt (Testing) +- (void)logRoktApiDiagnostic:(NSString *)code; @end @interface MParticle () @@ -1122,6 +1128,39 @@ - (void)testSetSessionIdForwardsToKitContainer { OCMVerifyAll(self.mockContainer); } +#pragma mark - Public API Diagnostics Tests + +- (void)testLogRoktApiDiagnosticForwardsToActiveRoktKit { + MParticle *instance = [MParticle sharedInstance]; + self.mockInstance = OCMPartialMock(instance); + self.mockContainer = OCMClassMock([MPKitContainer_PRIVATE class]); + [[[self.mockInstance stub] andReturn:self.mockContainer] kitContainer_PRIVATE]; + [[[self.mockInstance stub] andReturn:self.mockInstance] sharedInstance]; + + id mockKitRegister = OCMProtocolMock(@protocol(MPExtensionKitProtocol)); + OCMStub([(id)mockKitRegister code]).andReturn(kTestRoktKitId); + MPRoktTestKitInstance *kitInstance = [[MPRoktTestKitInstance alloc] init]; + OCMStub([mockKitRegister wrapperInstance]).andReturn(kitInstance); + OCMStub([self.mockContainer activeKitsRegistry]).andReturn(@[mockKitRegister]); + + [self.rokt logRoktApiDiagnostic:@"LOG_EVENT"]; + + XCTAssertEqualObjects(kitInstance.lastDiagnosticCode, @"LOG_EVENT"); +} + +- (void)testLogRoktApiDiagnosticDoesNothingWithoutActiveRoktKit { + MParticle *instance = [MParticle sharedInstance]; + self.mockInstance = OCMPartialMock(instance); + self.mockContainer = OCMClassMock([MPKitContainer_PRIVATE class]); + [[[self.mockInstance stub] andReturn:self.mockContainer] kitContainer_PRIVATE]; + [[[self.mockInstance stub] andReturn:self.mockInstance] sharedInstance]; + OCMStub([self.mockContainer activeKitsRegistry]).andReturn(@[]); + + [self.rokt logRoktApiDiagnostic:@"LOG_EVENT"]; + + OCMVerify([self.mockContainer activeKitsRegistry]); +} + #pragma mark - getSessionId Tests - (void)testGetSessionIdReturnsSessionIdFromKit { diff --git a/mParticle-Apple-SDK/Identity/MPIdentityApi.m b/mParticle-Apple-SDK/Identity/MPIdentityApi.m index faf0ab1ff..b37d1aade 100644 --- a/mParticle-Apple-SDK/Identity/MPIdentityApi.m +++ b/mParticle-Apple-SDK/Identity/MPIdentityApi.m @@ -15,6 +15,7 @@ #import "MPKitContainer.h" #import "MPUpload.h" #import "MPUserDefaultsConnector.h" +#import "../MPRokt+MParticlePrivate.h" @import mParticle_Apple_SDK_Swift; typedef NS_ENUM(NSUInteger, MPIdentityRequestType) { @@ -351,6 +352,7 @@ - (MParticleUser *)getUser:(NSNumber *)mpId { } - (NSArray *)getAllUsers { + [[MParticle sharedInstance].rokt logRoktApiDiagnostic:@"GET_USERS"]; MPUserDefaults *userDefaults = MPUserDefaultsConnector.userDefaults; NSMutableArray *userArray = [[NSMutableArray alloc] init]; @@ -375,6 +377,7 @@ - (void)identifyNoDispatch:(MPIdentityApiRequest *)identifyRequest completion:(n } - (void)identify:(MPIdentityApiRequest *)identifyRequest completion:(nullable MPIdentityApiResultCallback)completion { + [[MParticle sharedInstance].rokt logRoktApiDiagnostic:@"IDENTIFY"]; MPIdentityApiResultCallback wrappedCompletion = ^(MPIdentityApiResult * _Nullable apiResult, NSError * _Nullable error) { if (completion) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -392,6 +395,7 @@ - (void)identifyWithCompletion:(nullable MPIdentityApiResultCallback)completion } - (void)login:(MPIdentityApiRequest *)loginRequest completion:(nullable MPIdentityApiResultCallback)completion { + [[MParticle sharedInstance].rokt logRoktApiDiagnostic:@"LOGIN"]; MPIdentityApiResultCallback wrappedCompletion = ^(MPIdentityApiResult *_Nullable apiResult, NSError *_Nullable error) { if (completion) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -414,6 +418,7 @@ - (void)loginWithCompletion:(nullable MPIdentityApiResultCallback)completion { } - (void)logout:(MPIdentityApiRequest *)logoutRequest completion:(nullable MPIdentityApiResultCallback)completion { + [[MParticle sharedInstance].rokt logRoktApiDiagnostic:@"LOGOUT"]; MPIdentityApiResultCallback wrappedCompletion = ^(MPIdentityApiResult *_Nullable apiResult, NSError *_Nullable error) { if (completion) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -434,6 +439,7 @@ - (void)logoutWithCompletion:(nullable MPIdentityApiResultCallback)completion { } - (void)modify:(MPIdentityApiRequest *)modifyRequest completion:(nullable MPModifyApiResultCallback)completion { + [[MParticle sharedInstance].rokt logRoktApiDiagnostic:@"MODIFY"]; MPModifyApiResultCallback wrappedCompletion = ^(MPModifyApiResult *_Nullable apiResult, NSError *_Nullable error) { if (completion) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -449,6 +455,7 @@ - (void)modify:(MPIdentityApiRequest *)modifyRequest completion:(nullable MPModi } - (BOOL)aliasUsers:(MPAliasRequest *)aliasRequest { + [[MParticle sharedInstance].rokt logRoktApiDiagnostic:@"ALIAS_USERS"]; if (aliasRequest.sourceMPID == nil || aliasRequest.destinationMPID == nil || aliasRequest.sourceMPID.longLongValue == 0 || aliasRequest.destinationMPID.longLongValue == 0 || [aliasRequest.sourceMPID isEqual:aliasRequest.destinationMPID]) { MPILogError(@"Invalid alias request - both users must exist and not be equal."); return NO; diff --git a/mParticle-Apple-SDK/Identity/MParticleUser.m b/mParticle-Apple-SDK/Identity/MParticleUser.m index 7eae171e0..ef8dab1be 100644 --- a/mParticle-Apple-SDK/Identity/MParticleUser.m +++ b/mParticle-Apple-SDK/Identity/MParticleUser.m @@ -11,6 +11,7 @@ #import "MPIConstants.h" #import "MPKitContainer.h" #import "MPUserDefaultsConnector.h" +#import "../MPRokt+MParticlePrivate.h" @import mParticle_Apple_SDK_Swift; @interface MParticleUser () @@ -216,6 +217,7 @@ - (BOOL)forwardLegacyUserIdentityToKitContainer:(NSString *)identityString ident } - (nullable NSNumber *)incrementUserAttribute:(NSString *)key byValue:(NSNumber *)value { + [[MParticle sharedInstance].rokt logRoktApiDiagnostic:@"INCREMENT_USER_ATTRIBUTE"]; dispatch_async([MParticle messageQueue], ^{ MPStateMachine_PRIVATE *stateMachine = [MParticle sharedInstance].stateMachine; if (stateMachine.optOut) { @@ -312,6 +314,7 @@ - (void)setUserAttribute:(nonnull NSString *)key value:(nonnull id)value { } - (void)setUserAttributeList:(nonnull NSString *)key values:(nonnull NSArray *)values { + [[MParticle sharedInstance].rokt logRoktApiDiagnostic:@"SET_USER_ATTRIBUTE_LIST"]; if (values.count == 0) { MPILogDebug(@"User attribute not updated. Please use removeUserAttribute."); return; @@ -364,6 +367,7 @@ - (void)setUserAttributeList:(nonnull NSString *)key values:(nonnull NSArray *currentAudiences, NSError * _Nullable error))completionHandler { + [[MParticle sharedInstance].rokt logRoktApiDiagnostic:@"GET_USER_AUDIENCES"]; if ([MParticle sharedInstance].stateMachine.enableAudienceAPI) { dispatch_async([MParticle messageQueue], ^{ [self.backendController fetchAudiencesWithCompletionHandler:completionHandler]; @@ -451,7 +457,8 @@ - (void)getUserAudiencesWithCompletionHandler:(void (^)(NSArray *c #pragma mark - Consent State - (void)setConsentState:(MPConsentState *)state { - + [[MParticle sharedInstance].rokt logRoktApiDiagnostic:@"SET_CONSENT_STATE"]; + [MPPersistenceController_PRIVATE setConsentState:state forMpid:self.userId]; NSArray *kitConfig = [[MParticle sharedInstance].kitContainer_PRIVATE.originalConfig copy]; @@ -474,6 +481,7 @@ - (void)setConsentState:(MPConsentState *)state { } - (nullable MPConsentState *)consentState { + [[MParticle sharedInstance].rokt logRoktApiDiagnostic:@"GET_CONSENT_STATE"]; return [MPPersistenceController_PRIVATE consentStateForMpid:self.userId]; } diff --git a/mParticle-Apple-SDK/Include/MPKitProtocol.h b/mParticle-Apple-SDK/Include/MPKitProtocol.h index 3e00e2cdc..6ffd410ba 100644 --- a/mParticle-Apple-SDK/Include/MPKitProtocol.h +++ b/mParticle-Apple-SDK/Include/MPKitProtocol.h @@ -155,6 +155,10 @@ filteredUser:(FilteredMParticleUser * _Nonnull)filteredUser; - (BOOL)handleURLCallback:(NSURL * _Nonnull)url; +/// Forward a bounded, non-PII public-API-usage diagnostic code (e.g. "LOG_EVENT") to the kit. +/// Implemented by the Rokt kit only; records which public mParticle API a partner called. +- (void)logMParticleApiDiagnostic:(NSString * _Nonnull)code; + @end #endif diff --git a/mParticle-Apple-SDK/MPRokt+MParticlePrivate.h b/mParticle-Apple-SDK/MPRokt+MParticlePrivate.h new file mode 100644 index 000000000..4cdd1036f --- /dev/null +++ b/mParticle-Apple-SDK/MPRokt+MParticlePrivate.h @@ -0,0 +1,17 @@ +// +// MPRokt+MParticlePrivate.h +// mParticle-Apple-SDK +// +// Internal forwarder used by mParticle core to record public-API usage into the Rokt kit. +// Not partner-facing — deliberately kept out of the public MPRokt.h. +// + +#import "MPRokt.h" + +@interface MPRokt (MParticlePrivate) + +/// Forwards a bounded, non-PII public-API-usage diagnostic code (uppercase SNAKE_CASE, e.g. +/// "LOG_EVENT") to the Rokt kit — only when the kit is active, no-op otherwise. +- (void)logRoktApiDiagnostic:(NSString * _Nonnull)code; + +@end diff --git a/mParticle-Apple-SDK/MPRokt.m b/mParticle-Apple-SDK/MPRokt.m index a5c867751..980f88cdc 100644 --- a/mParticle-Apple-SDK/MPRokt.m +++ b/mParticle-Apple-SDK/MPRokt.m @@ -59,6 +59,7 @@ - (void)selectPlacements:(NSString *)identifier embeddedViews:(NSDictionary * _Nullable)embeddedViews config:(RoktConfig * _Nullable)config onEvent:(void (^ _Nullable)(RoktEvent * _Nonnull))onEvent { + [self logRoktApiDiagnostic:@"SELECT_PLACEMENTS"]; MPILogDebug(@"MPRokt selectPlacements (full) called - identifier: %@, attributes count: %lu, embeddedViews count: %lu, config: %@, onEvent: %@", identifier, (unsigned long)attributes.count, @@ -125,6 +126,7 @@ - (void)selectPlacements:(NSString *)identifier /// - catalogItemId: The identifier of the catalog item that was purchased /// - success: Whether the purchase was successful (YES) or failed (NO) - (void)purchaseFinalized:(NSString * _Nonnull)identifier catalogItemId:(NSString * _Nonnull)catalogItemId success:(BOOL)success { + [self logRoktApiDiagnostic:@"PURCHASE_FINALIZED"]; MPILogDebug(@"MPRokt purchaseFinalized - identifier: %@, catalogItemId: %@, success: %@", identifier, catalogItemId, success ? @"YES" : @"NO"); dispatch_async(dispatch_get_main_queue(), ^{ @@ -149,6 +151,7 @@ - (void)purchaseFinalized:(NSString * _Nonnull)identifier catalogItemId:(NSStrin /// - identifier: The Rokt placement identifier to listen for events from /// - onEvent: Callback block that receives RoktEvent objects when placement events occur - (void)events:(NSString * _Nonnull)identifier onEvent:(void (^ _Nullable)(RoktEvent * _Nonnull))onEvent { + [self logRoktApiDiagnostic:@"ROKT_EVENTS"]; MPILogDebug(@"MPRokt events called - identifier: %@, onEvent: %@", identifier, onEvent ? @"present" : @"nil"); dispatch_async(dispatch_get_main_queue(), ^{ @@ -172,6 +175,7 @@ - (void)events:(NSString * _Nonnull)identifier onEvent:(void (^ _Nullable)(RoktE /// - Parameters: /// - onEvent: Callback block that receives RoktEvent objects when events occur - (void)globalEvents:(void (^ _Nonnull)(RoktEvent * _Nonnull))onEvent { + [self logRoktApiDiagnostic:@"ROKT_GLOBAL_EVENTS"]; dispatch_async(dispatch_get_main_queue(), ^{ // Forwarding call to kits MPForwardQueueParameters *queueParameters = [[MPForwardQueueParameters alloc] init]; @@ -190,6 +194,7 @@ - (void)globalEvents:(void (^ _Nonnull)(RoktEvent * _Nonnull))onEvent { /// Closes any currently displayed Rokt placement. /// Call this method to programmatically dismiss an active Rokt overlay or embedded placement. - (void)close { + [self logRoktApiDiagnostic:@"ROKT_CLOSE"]; MPILogDebug(@"MPRokt close called"); dispatch_async(dispatch_get_main_queue(), ^{ // Forwarding call to kits @@ -209,6 +214,7 @@ - (void)close { /// - Parameters: /// - sessionId: The session id to be set. Must be a non-empty string. - (void)setSessionId:(NSString * _Nonnull)sessionId { + [self logRoktApiDiagnostic:@"ROKT_SET_SESSION_ID"]; MPILogDebug(@"MPRokt setSessionId called - sessionId: %@", sessionId ? @"present" : @"nil"); dispatch_async(dispatch_get_main_queue(), ^{ MPForwardQueueParameters *queueParameters = [[MPForwardQueueParameters alloc] init]; @@ -226,6 +232,7 @@ - (void)setSessionId:(NSString * _Nonnull)sessionId { /// Get the session id to use within a non-native integration e.g. WebView. /// - Returns: The session id or nil if no session is present. - (NSString * _Nullable)getSessionId { + [self logRoktApiDiagnostic:@"ROKT_GET_SESSION_ID"]; MPILogDebug(@"MPRokt getSessionId called"); __block NSString *result = nil; @@ -256,6 +263,22 @@ - (NSString * _Nullable)getSessionId { return result; } +- (void)logRoktApiDiagnostic:(NSString *)code { + if (code.length == 0) { + return; + } + NSArray> *activeKits = [[MParticle sharedInstance].kitContainer_PRIVATE activeKitsRegistry]; + for (id kitRegister in activeKits) { + if ([kitRegister.code integerValue] == kMPRoktKitId) { + id kitInstance = kitRegister.wrapperInstance; + if (kitInstance && [kitInstance respondsToSelector:@selector(logMParticleApiDiagnostic:)]) { + [kitInstance logMParticleApiDiagnostic:code]; + } + break; + } + } +} + /** * Registers a payment extension for Shoppable Ads. * The payment extension handles payment processing (e.g., Apple Pay via Stripe). @@ -267,6 +290,7 @@ - (NSString * _Nullable)getSessionId { * @param paymentExtension An object conforming to RoktPaymentExtension (PaymentExtension in Swift; from RoktContracts) */ - (void)registerPaymentExtension:(id _Nonnull)paymentExtension { + [self logRoktApiDiagnostic:@"REGISTER_PAYMENT_EXTENSION"]; dispatch_async([MParticle messageQueue], ^{ MPILogDebug(@"MPRokt forwarding to kit - registerPaymentExtension: %@", paymentExtension); @@ -310,6 +334,7 @@ - (void)selectShoppableAds:(NSString * _Nonnull)identifier attributes:(NSDictionary * _Nonnull)attributes config:(RoktConfig * _Nullable)config onEvent:(void (^ _Nullable)(RoktEvent * _Nonnull))onEvent { + [self logRoktApiDiagnostic:@"SELECT_SHOPPABLE_ADS"]; MPILogDebug(@"MPRokt selectShoppableAds (full) called - identifier: %@, attributes count: %lu, config: %@, onEvent: %@", identifier, (unsigned long)attributes.count, @@ -367,6 +392,7 @@ - (void)selectShoppableAds:(NSString * _Nonnull)identifier /// - Parameter url: The URL received by the app's URL handler. /// - Returns: YES if a registered payment extension claimed the URL; NO otherwise (including when the Rokt Kit is not registered). - (BOOL)handleURLCallback:(NSURL * _Nonnull)url { + [self logRoktApiDiagnostic:@"ROKT_HANDLE_URL_CALLBACK"]; MPILogDebug(@"MPRokt handleURLCallback called - url: %@", url); if (!url) { return NO; diff --git a/mParticle-Apple-SDK/mParticle.m b/mParticle-Apple-SDK/mParticle.m index f59b46e84..8334905c1 100644 --- a/mParticle-Apple-SDK/mParticle.m +++ b/mParticle-Apple-SDK/mParticle.m @@ -22,6 +22,7 @@ #import "MPConvertJS.h" #import "MPUserDefaultsConnector.h" #import "SceneDelegateHandler.h" +#import "MPRokt+MParticlePrivate.h" @import mParticle_Apple_SDK_Swift; @@ -248,11 +249,13 @@ - (MPILogLevel)logLevel { } - (void)setCustomLogger:(void (^)(NSString * _Nonnull))customLogger { + [self.rokt logRoktApiDiagnostic:@"SET_CUSTOM_LOGGER"]; _customLogger = customLogger; logger.customLogger = customLogger; } - (void)setLogLevel:(MPILogLevel)logLevel { + [self.rokt logRoktApiDiagnostic:@"SET_LOG_LEVEL"]; logger.logLevel = [MPLog fromRawValue: logLevel]; self.stateMachine.logLevel = logLevel; } @@ -272,6 +275,7 @@ - (void)setOptOutCompletion:(MPExecStatus)execStatus optOut:(BOOL)optOut { } - (void)setOptOut:(BOOL)optOut { + [self.rokt logRoktApiDiagnostic:@"SET_OPT_OUT"]; if (self.stateMachine.optOut == optOut) { return; } @@ -302,6 +306,7 @@ - (MPConsentState *)deviceConsentState { } - (void)setDeviceConsentState:(MPConsentState *)deviceConsentState { + [self.rokt logRoktApiDiagnostic:@"SET_DEVICE_CONSENT_STATE"]; [MPPersistenceController_PRIVATE setDeviceConsentState:deviceConsentState]; NSArray *kitConfig = [self.kitContainer_PRIVATE.originalConfig copy]; @@ -331,6 +336,7 @@ - (NSString *)uniqueIdentifier { } - (void)setUploadInterval:(NSTimeInterval)uploadInterval { + [self.rokt logRoktApiDiagnostic:@"SET_UPLOAD_INTERVAL"]; if (uploadInterval >= 1.0 && uploadInterval != self.backendController.uploadInterval) { [self upload]; self.backendController.uploadInterval = uploadInterval; @@ -620,6 +626,7 @@ - (void)resetForSwitchingWorkspaces:(void (^)(void))completion { } - (void)switchWorkspaceWithOptions:(MParticleOptions *)options { + [self.rokt logRoktApiDiagnostic:@"SWITCH_WORKSPACE"]; void (^finishReset)(void) = ^void(void) { // Reset SDK (config, database--except uploads, user defaults, kits, etc) [self resetForSwitchingWorkspaces:^{ @@ -657,51 +664,60 @@ - (NSData *)pushNotificationToken { } - (void)setPushNotificationToken:(NSData *)pushNotificationToken { + [self.rokt logRoktApiDiagnostic:@"SET_PUSH_NOTIFICATION_TOKEN"]; if (![self.appEnvironmentProvider isAppExtension]) { [self.notificationController setDeviceToken:pushNotificationToken]; } } - (void)didReceiveRemoteNotification:(NSDictionary *)userInfo { + [self.rokt logRoktApiDiagnostic:@"DID_RECEIVE_REMOTE_NOTIFICATION"]; if (![self.appEnvironmentProvider isAppExtension]) { [self.appNotificationHandler didReceiveRemoteNotification:userInfo]; } } - (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + [self.rokt logRoktApiDiagnostic:@"PUSH_REGISTRATION_FAILED"]; if (![self.appEnvironmentProvider isAppExtension]) { [self.appNotificationHandler didFailToRegisterForRemoteNotificationsWithError:error]; } } - (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + [self.rokt logRoktApiDiagnostic:@"DID_REGISTER_FOR_REMOTE_NOTIFICATIONS"]; if (![self.appEnvironmentProvider isAppExtension]) { [self.appNotificationHandler didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; } } - (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo { + [self.rokt logRoktApiDiagnostic:@"HANDLE_ACTION_FOR_REMOTE_NOTIFICATION"]; if (![self.appEnvironmentProvider isAppExtension]) { [self.appNotificationHandler handleActionWithIdentifier:identifier forRemoteNotification:userInfo]; } } - (void)handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(nullable NSDictionary *)userInfo withResponseInfo:(nonnull NSDictionary *)responseInfo { + [self.rokt logRoktApiDiagnostic:@"HANDLE_ACTION_FOR_REMOTE_NOTIFICATION"]; if (![self.appEnvironmentProvider isAppExtension]) { [self.appNotificationHandler handleActionWithIdentifier:identifier forRemoteNotification:userInfo withResponseInfo:responseInfo]; } } - (void)handleURLContext:(UIOpenURLContext *)urlContext API_AVAILABLE(ios(13.0)) { + [self.rokt logRoktApiDiagnostic:@"HANDLE_URL_CONTEXT"]; [self.sceneDelegateHandler handleURLContext:urlContext]; } #endif - (void)handleUserActivity:(NSUserActivity *)userActivity { + [self.rokt logRoktApiDiagnostic:@"HANDLE_USER_ACTIVITY"]; [self.sceneDelegateHandler handleUserActivity:userActivity]; } - (void)reset:(void (^)(void))completion { + [self.rokt logRoktApiDiagnostic:@"RESET"]; [executor executeOnMessage:^{ [self.kitContainer flushSerializedKits]; [self.kitContainer removeAllSideloadedKits]; @@ -718,6 +734,7 @@ - (void)reset:(void (^)(void))completion { } - (void)reset { + [self.rokt logRoktApiDiagnostic:@"RESET"]; [executor executeOnMessageSync:^{ [MPUserDefaultsConnector.userDefaults resetDefaults]; [[MParticle sharedInstance].persistenceController resetDatabase]; @@ -727,6 +744,7 @@ - (void)reset { #pragma mark Basic tracking - (nullable NSSet *)activeTimedEvents { + [self.rokt logRoktApiDiagnostic:@"GET_ACTIVE_TIMED_EVENTS"]; return self.backendController.eventSet; } @@ -754,6 +772,7 @@ - (void)beginTimedEventCompletionHandler:(MPEvent *)event execStatus:(MPExecStat } - (void)beginTimedEvent:(MPEvent *)event { + [self.rokt logRoktApiDiagnostic:@"BEGIN_TIMED_EVENT"]; [self.backendController beginTimedEvent:event completionHandler:^(MPEvent *event, MPExecStatus execStatus) { [self beginTimedEventCompletionHandler:event execStatus:execStatus]; @@ -788,6 +807,7 @@ - (void)logEventCallback:(MPEvent *)event execStatus:(MPExecStatus)execStatus { } - (void)endTimedEvent:(MPEvent *)event { + [self.rokt logRoktApiDiagnostic:@"END_TIMED_EVENT"]; [event endTiming]; [executor executeOnMessage: ^{ [self.backendController logEvent:event @@ -798,16 +818,18 @@ - (void)endTimedEvent:(MPEvent *)event { } - (MPEvent *)eventWithName:(NSString *)eventName { + [self.rokt logRoktApiDiagnostic:@"GET_TIMED_EVENT"]; return [self.backendController eventWithName:eventName]; } - (void)logEvent:(MPBaseEvent *)event { + [self.rokt logRoktApiDiagnostic:@"LOG_EVENT"]; if ([event isKindOfClass:[MPEvent class]]) { [self logCustomEvent:(MPEvent *)event]; } else if ([event isKindOfClass:[MPCommerceEvent class]]) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [self logCommerceEvent:(MPCommerceEvent *)event]; + [self logCommerceEventWithoutDiagnostic:(MPCommerceEvent *)event]; #pragma clang diagnostic pop } else { [executor executeOnMessage: ^{ @@ -945,6 +967,7 @@ - (void)logScreenCallback:(MPEvent *)event execStatus:(MPExecStatus)execStatus { } - (void)logScreenEvent:(MPEvent *)event { + [self.rokt logRoktApiDiagnostic:@"LOG_SCREEN"]; [executor executeOnMessage: ^{ [self.backendController logScreen:event completionHandler:^(MPEvent *event, MPExecStatus execStatus) { @@ -975,6 +998,7 @@ - (void)logScreen:(NSString *)screenName eventInfo:(NSDictionary } - (void)setATTStatus:(MPATTAuthorizationStatus)status withATTStatusTimestampMillis:(NSNumber *)attStatusTimestampMillis { + [self.rokt logRoktApiDiagnostic:@"SET_ATT_STATUS"]; NSNumber *currentStatus = self.stateMachine.attAuthorizationStatus; if (currentStatus == nil || currentStatus.integerValue != status) { self.stateMachine.attAuthorizationStatus = @(status); @@ -999,6 +1023,7 @@ - (void)setATTStatus:(MPATTAuthorizationStatus)status withATTStatusTimestampMill #pragma mark Attribution - (nullable NSDictionary *)attributionInfo { + [self.rokt logRoktApiDiagnostic:@"GET_ATTRIBUTION_INFO"]; return [self.kitContainer.attributionInfo copy]; } @@ -1031,6 +1056,7 @@ - (void)leaveBreadcrumbCallback:(MPEvent *)event execStatus:(MPExecStatus)execSt } - (void)leaveBreadcrumb:(NSString *)breadcrumbName eventInfo:(NSDictionary *)eventInfo { + [self.rokt logRoktApiDiagnostic:@"LEAVE_BREADCRUMB"]; if (!breadcrumbName) { [logger error:@"Breadcrumb name is required."]; return; @@ -1079,6 +1105,7 @@ - (void)logErrorCallback:(NSDictionary * _Nullable)eventInfo exec } - (void)logError:(NSString *)message eventInfo:(NSDictionary *)eventInfo { + [self.rokt logRoktApiDiagnostic:@"LOG_ERROR"]; if ([message isEqual: @""]) { NSString *message = [NSString stringWithFormat:@"'message' is required for %@", NSStringFromSelector(_cmd)]; [logger error:message]; @@ -1119,6 +1146,7 @@ - (void)logExceptionCallback:(NSException * _Nonnull)exception execStatus:(MPExe } - (void)logException:(NSException *)exception topmostContext:(id)topmostContext { + [self.rokt logRoktApiDiagnostic:@"LOG_EXCEPTION"]; [executor executeOnMessage: ^{ [self.backendController logError:nil exception:exception @@ -1141,6 +1169,7 @@ - (void)logCrash:(nullable NSString *)message stackTrace:(nullable NSString *)stackTrace plCrashReport:(NSString *)plCrashReport { + [self.rokt logRoktApiDiagnostic:@"LOG_CRASH"]; if (!plCrashReport) { NSString *message = [NSString stringWithFormat:@"'plCrashReport' is required for %@", NSStringFromSelector(_cmd)]; [logger error:message]; @@ -1167,6 +1196,11 @@ - (void)logCommerceEventCallback:(MPCommerceEvent *)commerceEvent execStatus:(MP } - (void)logCommerceEvent:(MPCommerceEvent *)commerceEvent { + [self.rokt logRoktApiDiagnostic:@"LOG_COMMERCE_EVENT"]; + [self logCommerceEventWithoutDiagnostic:commerceEvent]; +} + +- (void)logCommerceEventWithoutDiagnostic:(MPCommerceEvent *)commerceEvent { if (!commerceEvent.timestamp) { commerceEvent.timestamp = [NSDate date]; } @@ -1213,6 +1247,7 @@ - (void)logLTVIncreaseCallback:(MPEvent *)event execStatus:(MPExecStatus)execSta } - (void)logLTVIncrease:(double)increaseAmount eventName:(NSString *)eventName eventInfo:(NSDictionary *)eventInfo { + [self.rokt logRoktApiDiagnostic:@"LOG_LTV_INCREASE"]; NSMutableDictionary *eventDictionary = [@{@"$Amount":@(increaseAmount), kMPMethodName:@"LogLTVIncrease"} mutableCopy]; @@ -1244,6 +1279,7 @@ + (BOOL)registerExtension:(nonnull id)extension { #pragma mark Integration attributes - (nonnull MPKitExecStatus *)setIntegrationAttributes:(nonnull NSDictionary *)attributes forKit:(nonnull NSNumber *)integrationId { + [self.rokt logRoktApiDiagnostic:@"SET_INTEGRATION_ATTRIBUTES"]; __block MPKitReturnCode returnCode = MPKitReturnCodeSuccess; MPIntegrationAttributes *integrationAttributes = [[MPIntegrationAttributes alloc] initWithIntegrationId:integrationId attributes:attributes]; @@ -1261,6 +1297,7 @@ - (nonnull MPKitExecStatus *)setIntegrationAttributes:(nonnull NSDictionary= __IPHONE_10_0 - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification { + [self.rokt logRoktApiDiagnostic:@"WILL_PRESENT_NOTIFICATION"]; if (!notification.request.content.userInfo) { return; } @@ -1446,6 +1496,7 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNot } - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response { + [self.rokt logRoktApiDiagnostic:@"DID_RECEIVE_NOTIFICATION_RESPONSE"]; if (!response.notification.request.content.userInfo) { return; } @@ -1489,6 +1540,7 @@ - (NSString *)bridgeVersion { #if TARGET_OS_IOS == 1 - (void)initializeWKWebView:(WKWebView *)webView bridgeName:(NSString *)bridgeName { + [self.rokt logRoktApiDiagnostic:@"REGISTER_WEBVIEW"]; NSString *bridgeValue = [self webviewBridgeValueWithCustomerBridgeName:bridgeName]; if (bridgeValue == nil) { [logger error:@"Unable to initialize webview due to missing or invalid bridgeName"]; @@ -1714,6 +1766,7 @@ - (void)handleWebviewCommand:(NSString *)command dictionary:(NSDictionary *)dict Logs a Notification event for a notification that has been reviewed but not acted upon. This is a convenience method for manually logging Notification events; Set trackNotifications to false on MParticleOptions to disable automatic tracking of Notifications and only set Notification manually: */ - (void)logNotificationReceivedWithUserInfo:(nonnull NSDictionary *)userInfo { + [self.rokt logRoktApiDiagnostic:@"LOG_NOTIFICATION"]; if (userInfo == nil) { return; } @@ -1724,6 +1777,7 @@ - (void)logNotificationReceivedWithUserInfo:(nonnull NSDictionary *)userInfo { Logs a Notification event for a notification that has been reviewed and acted upon. This is a convenience method for manually logging Notification events; Set trackNotifications to false on MParticleOptions to disable automatic tracking of Notifications and only set Notification manually: */ - (void)logNotificationOpenedWithUserInfo:(nonnull NSDictionary *)userInfo andActionIdentifier:(nullable NSString *)actionIdentifier { + [self.rokt logRoktApiDiagnostic:@"LOG_NOTIFICATION_OPENED"]; if (userInfo == nil) { return; }