Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions mParticle-Rokt-Swift/MPRoktLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ public class MPRoktLayout {
}
let email = attributes?["email"]
let hashedEmail = attributes?["emailsha256"]
let hashedEmailIdentity = MPKitRokt.getHashedEmailUserIdentityType()

let userEmailIdentity = user.identities[NSNumber(value: MPIdentity.email.rawValue)]
let userHashedEmailIdentity = user.identities[NSNumber(value: MPIdentity.other.rawValue)]
let userHashedEmailIdentity = user.identities[hashedEmailIdentity]

let emailMismatch = email != nil && email != userEmailIdentity
let hashedEmailMismatch = hashedEmail != nil && hashedEmail != userHashedEmailIdentity
Expand All @@ -69,7 +70,7 @@ public class MPRoktLayout {
print("The existing hashed email on the user (\(userHashedEmailIdentity ?? "nil")) does not match the email passed in to `selectPlacements:` (\(hashedEmail ?? "nil")). Please remember to sync the email identity to mParticle as soon as you receive it. We will now identify the user before creating the layout")
}

syncIdentities(user: user, email: email, hashedEmail: hashedEmail, completion: completion)
syncIdentities(user: user, email: email, hashedEmail: hashedEmail, hashedEmailKey: hashedEmailIdentity, completion: completion)
} else {
completion()
}
Expand All @@ -79,11 +80,12 @@ public class MPRoktLayout {
user: MParticleUser,
email: String?,
hashedEmail: String?,
hashedEmailKey: NSNumber,
completion: @escaping () -> Void
) {
let identityRequest = MPIdentityApiRequest(user: user)
identityRequest.setIdentity(email, identityType: .email)
identityRequest.setIdentity(hashedEmail, identityType: .other)
identityRequest.setIdentity(hashedEmail, identityType: MPIdentity(rawValue: hashedEmailKey.uintValue) ?? .other)

mparticle.identity.identify(identityRequest) {apiResult, error in
if let error = error {
Expand Down
1 change: 1 addition & 0 deletions mParticle-Rokt/MPKitRokt.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
@property (nonatomic, unsafe_unretained, readonly) BOOL started;

+ (NSDictionary<NSString *, NSString *> * _Nonnull)prepareAttributes:(NSDictionary<NSString *, NSString *> * _Nonnull)attributes filteredUser:(FilteredMParticleUser * _Nullable)filteredUser performMapping:(BOOL)performMapping;
+ (NSNumber * _Nonnull)getRoktHashedEmailUserIdentityType;

@end
165 changes: 84 additions & 81 deletions mParticle-Rokt/MPKitRokt.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
NSString * const MPKitRoktErrorDomain = @"com.mparticle.kits.rokt";
NSString * const MPKitRoktErrorMessageKey = @"mParticle-Rokt Error";
NSString * const kMPPlacementAttributesMapping = @"placementAttributesMapping";
NSString * const kMPHashedEmailUserIdentityType = @"hashedEmailUserIdentityType";
NSInteger const kMPRoktKitCode = 181;

static __weak MPKitRokt *roktKit = nil;

@interface MPKitRokt () <MPKitProtocol>
Expand All @@ -20,7 +23,7 @@ @implementation MPKitRokt
mParticle will supply a unique kit code for you. Please contact our team
*/
+ (NSNumber *)kitCode {
return @181; // Replace with the actual kit code assigned by mParticle
return @(kMPRoktKitCode); // Replace with the actual kit code assigned by mParticle
}

+ (void)load {
Expand Down Expand Up @@ -251,7 +254,7 @@ - (RoktFrameworkType)mapMPWrapperSdkToRoktFrameworkType:(MPWrapperSdk)wrapperSdk
NSArray<NSDictionary *> *kitConfigs = [MParticle sharedInstance].kitContainer_PRIVATE.originalConfig.copy;
NSDictionary *roktKitConfig;
for (NSDictionary *kitConfig in kitConfigs) {
if (kitConfig[@"id"] != nil && [kitConfig[@"id"] integerValue] == 181) {
if (kitConfig[@"id"] != nil && [kitConfig[@"id"] integerValue] == kMPRoktKitCode) {
roktKitConfig = kitConfig;
}
}
Expand Down Expand Up @@ -361,86 +364,86 @@ + (RoktConfig *)convertMPRoktConfig:(MPRoktConfig *)mpRoktConfig {
}

+ (NSString *)stringForIdentityType:(MPIdentity)identityType {
switch (identityType) {
case MPIdentityCustomerId:
return @"customerid";

case MPIdentityEmail:
return @"email";

case MPIdentityFacebook:
return @"facebook";

case MPIdentityFacebookCustomAudienceId:
return @"facebookcustomaudienceid";

case MPIdentityGoogle:
return @"google";

case MPIdentityMicrosoft:
return @"microsoft";

case MPIdentityOther:
// As of 7/30/2025, "MPIdentityOther" is used by Rokt customers to identify based off hashed email
return @"emailsha256";

case MPIdentityTwitter:
return @"twitter";

case MPIdentityYahoo:
return @"yahoo";

case MPIdentityOther2:
return @"other2";

case MPIdentityOther3:
return @"other3";

case MPIdentityOther4:
return @"other4";

case MPIdentityOther5:
return @"other5";

case MPIdentityOther6:
return @"other6";

case MPIdentityOther7:
return @"other7";

case MPIdentityOther8:
return @"other8";

case MPIdentityOther9:
return @"other9";

case MPIdentityOther10:
return @"other10";

case MPIdentityMobileNumber:
return @"mobile_number";

case MPIdentityPhoneNumber2:
return @"phone_number_2";

case MPIdentityPhoneNumber3:
return @"phone_number_3";

case MPIdentityIOSAdvertiserId:
return @"ios_idfa";

case MPIdentityIOSVendorId:
return @"ios_idfv";

case MPIdentityPushToken:
return @"push_token";

case MPIdentityDeviceApplicationStamp:
return @"device_application_stamp";

default:
return nil;
NSNumber *hashedEmailIdentity = [MPKitRokt getRoktHashedEmailUserIdentityType];

if (hashedEmailIdentity.unsignedIntValue == identityType) {
return @"emailsha256";
}

NSDictionary<NSNumber *, NSString *> *identityStrings = @{@(MPIdentityCustomerId): @"customerid",
@(MPIdentityEmail): @"email",
@(MPIdentityFacebook): @"facebook",
@(MPIdentityFacebookCustomAudienceId): @"facebookcustomaudienceid",
@(MPIdentityGoogle): @"google",
@(MPIdentityMicrosoft): @"microsoft",
@(MPIdentityOther): @"other",
@(MPIdentityTwitter): @"twitter",
@(MPIdentityYahoo): @"yahoo",
@(MPIdentityOther2): @"other2",
@(MPIdentityOther3): @"other3",
@(MPIdentityOther4): @"other4",
@(MPIdentityOther5): @"other5",
@(MPIdentityOther6): @"other6",
@(MPIdentityOther7): @"other7",
@(MPIdentityOther8): @"other8",
@(MPIdentityOther9): @"other9",
@(MPIdentityOther10): @"other10",
@(MPIdentityMobileNumber): @"mobile_number",
@(MPIdentityPhoneNumber2): @"phone_number_2",
@(MPIdentityPhoneNumber3): @"phone_number_3",
@(MPIdentityIOSAdvertiserId): @"ios_idfa",
@(MPIdentityIOSVendorId): @"ios_idfv",
@(MPIdentityPushToken): @"push_token",
@(MPIdentityDeviceApplicationStamp): @"device_application_stamp"};

return identityStrings[@(identityType)];
}

+ (NSNumber *)identityTypeForString:(NSString *)identityString {
NSDictionary<NSString *, NSNumber *> *identityNumbers = @{@"customerid": @(MPIdentityCustomerId),
@"email": @(MPIdentityEmail),
@"facebook": @(MPIdentityFacebook),
@"facebookcustomaudienceid": @(MPIdentityFacebookCustomAudienceId),
@"google": @(MPIdentityGoogle),
@"microsoft": @(MPIdentityMicrosoft),
@"other": @(MPIdentityOther),
@"twitter": @(MPIdentityTwitter),
@"yahoo": @(MPIdentityYahoo),
@"other2": @(MPIdentityOther2),
@"other3": @(MPIdentityOther3),
@"other4": @(MPIdentityOther4),
@"other5": @(MPIdentityOther5),
@"other6": @(MPIdentityOther6),
@"other7": @(MPIdentityOther7),
@"other8": @(MPIdentityOther8),
@"other9": @(MPIdentityOther9),
@"other10": @(MPIdentityOther10),
@"mobile_number": @(MPIdentityMobileNumber),
@"phone_number_2": @(MPIdentityPhoneNumber2),
@"phone_number_3": @(MPIdentityPhoneNumber3),
@"ios_idfa": @(MPIdentityIOSAdvertiserId),
@"ios_idfv": @(MPIdentityIOSVendorId),
@"push_token": @(MPIdentityPushToken),
@"device_application_stamp": @(MPIdentityDeviceApplicationStamp)};

return identityNumbers[identityString];
}

+ (NSNumber *)getRoktHashedEmailUserIdentityType {
// Get the kit configuration
NSArray<NSDictionary *> *kitConfigs = [MParticle sharedInstance].kitContainer_PRIVATE.originalConfig.copy;
NSDictionary *roktKitConfig;
for (NSDictionary *kitConfig in kitConfigs) {
if (kitConfig[@"id"] != nil && [kitConfig[@"id"] integerValue] == kMPRoktKitCode) {
roktKitConfig = kitConfig;
}
}

// Get the string representing which identity to use and convert it to the key (NSNumber)
NSString *hashedIdentityTypeString = roktKitConfig[kMPHashedEmailUserIdentityType];
NSNumber *hashedIdentityTypeNumber = [MPKitRokt identityTypeForString:hashedIdentityTypeString.lowercaseString];

return hashedIdentityTypeNumber != nil ? hashedIdentityTypeNumber : @(MPIdentityOther);
}

- (MPKitExecStatus *)purchaseFinalized:(NSString *)placementId catalogItemId:(NSString *)catalogItemId success:(NSNumber *)success {
Expand Down
68 changes: 68 additions & 0 deletions mParticle_RoktTests/mParticle_RoktTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ + (void)addIdentityAttributes:(NSMutableDictionary<NSString *, NSString *> * _Nu

+ (void)handleHashedEmail:(NSMutableDictionary<NSString *, NSString *> * _Nullable)attributes;

+ (NSNumber *)getRoktHashedEmailUserIdentityType;

+ (RoktConfig *)convertMPRoktConfig:(MPRoktConfig *)mpRoktConfig;

+ (NSDictionary<NSString *, NSString *> *)transformValuesToString:(NSDictionary<NSString *, id> * _Nullable)originalDictionary;
Expand Down Expand Up @@ -329,6 +331,72 @@ - (void)testAddIdentityAttributesWithExistingAttributes {
XCTAssertEqualObjects(passedAttributes[@"device_application_stamp"], @"Test DAS");
}

- (void)testAddIdentityAttributesWithExistingAttributesAndOther {
NSMutableDictionary<NSString *, NSString *> *passedAttributes = [[NSMutableDictionary alloc] init];
[passedAttributes setObject:@"bar" forKey:@"foo"];
NSDictionary<NSNumber *, NSString *> *testIdentities = @{@(MPIdentityCustomerId): @"testCustomerID",
@(MPIdentityEmail): @"testEmail@gmail.com",
@(MPIdentityFacebook): @"testFacebook",
@(MPIdentityFacebookCustomAudienceId): @"testCustomAudienceID",
@(MPIdentityGoogle): @"testGoogle",
@(MPIdentityMicrosoft): @"testMicrosoft",
@(MPIdentityOther): @"testOther",
@(MPIdentityTwitter): @"testTwitter",
@(MPIdentityYahoo): @"testYahoo",
@(MPIdentityOther2): @"testOther2",
@(MPIdentityOther3): @"testOther3",
@(MPIdentityOther4): @"testOther4",
@(MPIdentityOther5): @"testOther5",
@(MPIdentityOther6): @"testOther6",
@(MPIdentityOther7): @"testOther7",
@(MPIdentityOther8): @"testOther8",
@(MPIdentityOther9): @"testOther9",
@(MPIdentityOther10): @"testOther10",
@(MPIdentityMobileNumber): @"1(234)-567-8910",
@(MPIdentityPhoneNumber2): @"1(234)-567-2222",
@(MPIdentityPhoneNumber3): @"1(234)-567-3333",
@(MPIdentityIOSAdvertiserId): @"testAdvertID",
@(MPIdentityIOSVendorId): @"testVendorID",
@(MPIdentityPushToken): @"testPushToken",
@(MPIdentityDeviceApplicationStamp): @"Test DAS"};

FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] init];
id mockfilteredUser = OCMPartialMock(filteredUser);
[[[mockfilteredUser stub] andReturn:testIdentities] userIdentities];
id mockMPKitRoktClass = OCMClassMock([MPKitRokt class]);
[[[mockMPKitRoktClass stub] andReturn:@(MPIdentityOther4)] getRoktHashedEmailUserIdentityType];

[MPKitRokt addIdentityAttributes:passedAttributes filteredUser:filteredUser];

XCTAssertEqualObjects(passedAttributes[@"foo"], @"bar");
Comment thread
BrandonStalnaker marked this conversation as resolved.
XCTAssertEqualObjects(passedAttributes[@"customerid"], @"testCustomerID");
XCTAssertEqualObjects(passedAttributes[@"email"], @"testEmail@gmail.com");
XCTAssertEqualObjects(passedAttributes[@"facebook"], @"testFacebook");
XCTAssertEqualObjects(passedAttributes[@"facebookcustomaudienceid"], @"testCustomAudienceID");
XCTAssertEqualObjects(passedAttributes[@"google"], @"testGoogle");
XCTAssertEqualObjects(passedAttributes[@"microsoft"], @"testMicrosoft");
XCTAssertEqualObjects(passedAttributes[@"other"], @"testOther");
XCTAssertEqualObjects(passedAttributes[@"emailsha256"], @"testOther4");
XCTAssertEqualObjects(passedAttributes[@"twitter"], @"testTwitter");
XCTAssertEqualObjects(passedAttributes[@"yahoo"], @"testYahoo");
XCTAssertEqualObjects(passedAttributes[@"other2"], @"testOther2");
XCTAssertEqualObjects(passedAttributes[@"other3"], @"testOther3");
XCTAssertNil(passedAttributes[@"other4"]);
XCTAssertEqualObjects(passedAttributes[@"other5"], @"testOther5");
XCTAssertEqualObjects(passedAttributes[@"other6"], @"testOther6");
XCTAssertEqualObjects(passedAttributes[@"other7"], @"testOther7");
XCTAssertEqualObjects(passedAttributes[@"other8"], @"testOther8");
XCTAssertEqualObjects(passedAttributes[@"other9"], @"testOther9");
XCTAssertEqualObjects(passedAttributes[@"other10"], @"testOther10");
XCTAssertEqualObjects(passedAttributes[@"mobile_number"], @"1(234)-567-8910");
XCTAssertEqualObjects(passedAttributes[@"phone_number_2"], @"1(234)-567-2222");
XCTAssertEqualObjects(passedAttributes[@"phone_number_3"], @"1(234)-567-3333");
XCTAssertEqualObjects(passedAttributes[@"ios_idfa"], @"testAdvertID");
XCTAssertEqualObjects(passedAttributes[@"ios_idfv"], @"testVendorID");
XCTAssertEqualObjects(passedAttributes[@"push_token"], @"testPushToken");
XCTAssertEqualObjects(passedAttributes[@"device_application_stamp"], @"Test DAS");
}

- (void)testConvertMPRoktConfig {
MPRoktConfig *mpConfig = [[MPRoktConfig alloc] init];
mpConfig.colorMode = MPColorModeDark;
Expand Down
Loading