After installing and initializing the SDK, verify that events are being sent correctly before releasing to production.
Enable Debug Logging
Enable debug logging to see SDK activity in the Xcode console:
guard let options = Options (
apiKey : "<your-api-key>" ,
organisationId : "<your-organisation-id>" ,
workspaceId : "<your-workspace-id>"
) else { return }
// Enable all log messages
options. logModes = LogMode. all
Permutive. shared . start ( with : options) { error in
// ...
}
PermutiveOptions *options = [[PermutiveOptions alloc]
initWithApiKey:@"<your-api-key>"
organisationId:@"<your-organisation-id>"
workspaceId:@"<your-workspace-id>"];
// Enable all log messages
options.logModes = PermutiveLogModeAll;
[[Permutive shared] startWith:options context:nil completion:^(NSError *error) {
// ...
}];
What to Look For
Successful Initialization
When the SDK initializes successfully, you’ll see:
Permutive: [info] SDK ready
Successful Event Tracking
When events are accepted by Permutive servers:
Permutive: [info] Accepted: 1 / 1
The format is Accepted: X / Y where X is the number of events accepted and Y is the total sent.
Schema Validation Errors
If event properties don’t match your schema:
Permutive: [error] Encountered 1 event rejection!
Permutive: [error] Error 1: A validation check carried out by the server did not succeed.(1007)
Permutive: [error] Error 1: Schema validation failed with reason(s): [#: 1 schema violations found;#: extraneous key [invalid_key] is not permitted]
Schema validation errors mean events are being rejected. Fix the property names or types to match your event schema in the Permutive dashboard.
Verification Checklist
SDK Initializes
Look for SDK ready in the console after app launch.
Events Are Sent
Navigate through your app and look for Accepted: X / X messages.
No Rejections
Ensure there are no event rejection error messages.
Check Dashboard
Log into your Permutive dashboard and verify events appear (may take up to 5 minutes).
Verification Code Example
Add this verification helper during development:
import Permutive_iOS
class PermutiveVerification {
static func verify () {
// Check user ID
let userId = Permutive. shared . currentUserId
print ( "✅ Permutive User ID: \( userId ) " )
// Check cohorts
let cohorts = Permutive. shared . cohorts
print ( "✅ Current cohorts: \( cohorts ) " )
// Check activations
let activations = Permutive. shared . activations
print ( "✅ Activations: \( activations ) " )
// Track a test event
do {
let properties = try EventProperties ([
"verification_test" : true ,
"timestamp" : Date (). timeIntervalSince1970
])
try Permutive. shared . track ( event : "VerificationTest" , properties : properties)
print ( "✅ Test event sent" )
} catch {
print ( "❌ Failed to send test event: \( error ) " )
}
}
}
// Call after initialization completes
Permutive. shared . start ( with : options) { error in
guard error == nil else { return }
PermutiveVerification. verify ()
}
@import Permutive_iOS;
@interface PermutiveVerification : NSObject
+ (void)verify;
@end
@implementation PermutiveVerification
+ (void)verify {
// Check user ID
NSString *userId = [[Permutive shared] currentUserId];
NSLog(@"✅ Permutive User ID: %@", userId);
// Check cohorts
NSSet *cohorts = [[Permutive shared] cohorts];
NSLog(@"✅ Current cohorts: %@", cohorts);
// Check activations
NSDictionary *activations = [[Permutive shared] activations];
NSLog(@"✅ Activations: %@", activations);
// Track a test event
NSError *error = nil;
PermutiveEventProperties *properties = [[PermutiveEventProperties alloc]
init:@{@"verification_test": @YES}
error:&error];
[[Permutive shared] trackWithEvent:@"VerificationTest"
properties:properties
error:&error];
if (error == nil) {
NSLog(@"✅ Test event sent");
} else {
NSLog(@"❌ Failed to send test event: %@", error);
}
}
@end
PageTracker Verification
Verify PageTracker is working correctly:
class TestViewController : UIViewController {
private var pageTracker: PageTrackerProtocol?
override func viewDidLoad () {
super . viewDidLoad ()
let properties = try ? EventProperties ([ "test_page" : true ])
let context = Context (
title : "Verification Test Page" ,
url : URL ( string : "https://example.com/test" ),
referrer : nil
)
pageTracker = try ? Permutive. shared . createPageTracker (
properties : properties,
context : context
)
print ( "✅ PageTracker created" )
}
override func viewDidAppear ( _ animated : Bool ) {
super . viewDidAppear (animated)
do {
try pageTracker?. resume ()
print ( "✅ PageTracker resumed - Pageview event should be sent" )
} catch {
print ( "❌ PageTracker resume failed: \( error ) " )
}
}
override func viewDidDisappear ( _ animated : Bool ) {
super . viewDidDisappear (animated)
pageTracker?. pause ()
print ( "✅ PageTracker paused" )
}
deinit {
pageTracker?. stop ()
print ( "✅ PageTracker stopped - PageViewComplete event should be sent" )
}
}
@interface TestViewController ()
@property (nonatomic, strong) NSObject<PermutivePageTrackerProtocol> *pageTracker;
@end
@implementation TestViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSError *error = nil;
PermutiveEventProperties *properties = [[PermutiveEventProperties alloc]
init:@{@"test_page": @YES}
error:&error];
PermutiveContext *context = [[PermutiveContext alloc]
initWithTitle:@"Verification Test Page"
url:[NSURL URLWithString:@"https://example.com/test"]
referrer:nil];
self.pageTracker = [[Permutive shared]
createPageTrackerWithProperties:properties
context:context
error:&error];
NSLog(@"✅ PageTracker created");
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSError *error = nil;
[self.pageTracker resumeAndReturnError:&error];
if (error == nil) {
NSLog(@"✅ PageTracker resumed");
} else {
NSLog(@"❌ PageTracker resume failed: %@", error);
}
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self.pageTracker pause];
NSLog(@"✅ PageTracker paused");
}
- (void)dealloc {
[self.pageTracker stop];
NSLog(@"✅ PageTracker stopped");
}
@end
Common Verification Issues
Problem: Console is silent, no Permutive logs appear.Solutions:
Confirm logModes = LogMode.all is set before calling start()
Check Xcode console filter isn’t hiding messages
Verify SDK is actually being initialized (add a breakpoint)
Events rejected with schema error
Problem: Events sent but rejected by server.Solutions:
Check event name matches schema (alphanumeric and underscores only)
Verify property names and types match your Permutive dashboard schema
Remove any extra properties not in the schema
Events not appearing in dashboard
Problem: Console shows Accepted but events not in dashboard.Solutions:
Wait up to 5 minutes for events to process
Verify you’re looking at the correct workspace
Check the date range filter in the dashboard
Confirm credentials match the dashboard environment
Problem: cohorts returns an empty set.Solutions:
Cohorts are evaluated server-side and may take time to populate
Ensure you’ve tracked sufficient events to qualify for cohorts
Check with your Customer Success Manager that cohorts are configured
Disable Logging for Production
Always disable debug logging before releasing to production to avoid performance overhead and prevent sensitive data from appearing in device logs.
# if DEBUG
options. logModes = LogMode. all
# else
options. logModes = LogMode. none
# endif
#ifdef DEBUG
options.logModes = PermutiveLogModeAll;
#else
options.logModes = PermutiveLogModeNone;
#endif
Next Steps
Once verification passes:
Page Tracking Implement page tracking throughout your app
Identity Management Set up user identity tracking
Google Ad Manager Integrate with GAM for ad targeting
Issues Troubleshoot common problems