Teak Features
Login
Teak’s functionality depends on knowing when a user plays and on what device they play.
At every game launch, send the player’s ID to Teak using login:withConfiguration:
// ...
let playerConfiguration = TeakUserConfiguration()
Teak.login(YOUR_PLAYER_ID, with:playerConfiguration)
Make sure that your player ID is a unique ID for the player in your game.
|
What Player ID should you use?
Your game probably has a user ID to store progress, coin balances, and other useful data. Use that ID with Teak too.
Having a consistent ID between your game and Teak makes customer support easier, and makes life easier for your analytics team. |
Player Configuration
Additional data, such as a player’s email address and Facebook ID, can be passed to Teak by setting the appropriate fields on the TeakUserConfiguration object passed to login:withConfiguration:
If you need to update any of this additional data during a game session, call Teak.login() with an appropriately configured TeakUserConfiguration object. Teak.login() will never clear or remove information about a player, and fields that are not set on the TeakUserConfiguration object will be ignored.
// ....
let playerConfiguration = TeakUserConfiguration()
playerConfiguration.email = "YOUR_PLAYER_EMAIL"
playerConfiguration.facebookId = "YOUR_PLAYER_FACEBOOK_ID"
Teak.login("YOUR_PLAYER_ID", with:playerConfiguration)
User Configuration
In addition to email and Facebook id, TeakUserConfiguration carries per-user data collection opt-outs, set at login time. These are distinct from a player’s channel opt-in/out preferences — see Notification Channels and Opt-Out Preferences.
| Property | Effect |
|---|---|
|
Opts out of IDFA collection for this user. See Disabling Automatic Data Collection for the app-wide equivalent. |
|
Opts out of Push Key (push token) collection for this user. See Disabling Automatic Data Collection for the app-wide equivalent. |
|
Deprecated — see SDK 5 Behaviors. |
let playerConfiguration = TeakUserConfiguration()
playerConfiguration.optOutIdfa = true
Teak.login("YOUR_PLAYER_ID", with:playerConfiguration)
Disabling Automatic Data Collection
In addition to the per-user opt-outs above, you can disable IDFA, Push Key, or Facebook access token collection for your whole app by adding the following keys to your Info.plist:
<key>TeakEnableIDFA</key>
<false/>
<key>TeakEnablePushKey</key>
<false/>
<key>TeakEnableFacebook</key>
<false/>
Each key defaults to true (collection enabled) when absent. IDFA collection is also subject to the OS-level advertising tracking authorization, regardless of this setting. TeakEnableFacebook only has an effect when TeakSDK5Behaviors has been set to false — see SDK 5 Behaviors.
Push Token Refresh
By default, Teak automatically re-registers for remote notifications at every app launch (silently, with no permission prompt) so its push token stays current. To take over this responsibility yourself, add the TeakDoNotRefreshPushToken boolean key to your Info.plist and set it to true, then call refreshPushTokenIfAuthorized whenever you want Teak to refresh its push token.
<key>TeakDoNotRefreshPushToken</key>
<true/>
Logging Out
When a player logs out of your game, tell Teak with logout. This is a client-side call: it doesn’t clear the device’s association with the player, but it does stop Teak from associating any further events — like a notification click — with that player until you call Teak.login() again.
Teak.sharedInstance()?.logout()
Rewards
Whenever your game should grant a reward to a player Teak will let you know by posting a notification to the default notification center with the name Notification.Name(TeakOnReward)
Teak does not provide any in-game UI to inform a player if they received a reward or not. You should
add an observer for the Notification.Name(TeakOnReward) notification which detects if the reward was granted or
denied, and informs the player what happened.
This callback will be concurrent with the Teak Reward Endpoint server to server call.
NotificationCenter.default.addObserver(forName: Notification.Name(TeakOnReward), object: nil, queue: nil, using:{notification in
let rewardStatus = notification.userInfo!["status"] as! String
let rewardId = notification.userInfo!["teakRewardId"] as! String
switch rewardStatus {
case "grant_reward":
let reward = notification.userInfo!["reward"]! as! Dictionary<String, NSNumber>
print("Reward with id \(rewardId) Granted! \(reward)")
case "already_clicked":
print("You already claimed this reward!")
case "expired":
print("The reward has expired")
case "too_many_clicks":
print("Too many other players already claimed this reward")
case "exceed_max_clicks_for_day":
print("You've already claimed too many rewards today")
case "not_for_you":
print("This reward is restricted to a different player")
case "invalid_post":
print("The reward id was not recognized")
default:
print("Unknown status")
}
})
Request Notification Permissions
To use push notifications you are required to ask the player if you can send them notifications. Do that with the requestNotificationPermissions: call.
// ...
Teak.requestNotificationPermissions({accepted, error in
print("User accepted notifications: \(accepted)")
})
You can still make this call even if the player cannot be prompted for permissions again. In that case the callback will be called with the current notification state.
Notifications
Scheduling a Notification
You can schedule a notification to be delivered for the current player by using scheduleNotificationForCreative:secondsFromNow:personalizationData:. The optional personalizationData dictionary is sent along for templating the notification’s content on the dashboard.
This corresponds to a Local Schedule on the dashboard — see Local Notification Tags for how the personalizationData keys you send become template tags in the Message.
| Don’t use client-scheduled notifications for new-player or lapsing-player flows — have your marketing team set up a Triggered Schedule for those instead. |
NSDictionary* personalizationData = @{
@"test_data": @"hello there",
@"other_data": @"straight from the app"
};
TeakOperation* op = [TeakNotification scheduleNotificationForCreative:@"my_creative_id"
secondsFromNow:5
personalizationData:personalizationData];
let personalizationData: [String: Any] = [
"test_data": "hello there",
"other_data": "straight from the app"
]
let op = TeakNotification.scheduleNotification(forCreative: "my_creative_id",
secondsFromNow: 5,
personalizationData: personalizationData)
This returns a TeakOperation, a plain NSOperation. Read the result by attaching a dependent operation — Teak enqueues op internally before returning it, so a completion block set directly on op would race.
NSBlockOperation* whenDone = [NSBlockOperation blockOperationWithBlock:^{
TeakOperationNotificationResult* result = (TeakOperationNotificationResult*)op.result;
if (result.error) {
NSLog(@"Notification errors: %@", [result toDictionary]);
} else {
NSLog(@"Notification scheduled: %@", [result toDictionary]);
}
}];
[whenDone addDependency:op];
[[[NSOperationQueue alloc] init] addOperation:whenDone];
let whenDone = BlockOperation {
if let result = op?.result as? TeakOperationNotificationResult {
if result.error {
print("Notification errors: \(result.toDictionary())")
} else {
print("Notification scheduled: \(result.toDictionary())")
}
}
}
if let op = op {
whenDone.addDependency(op)
}
OperationQueue().addOperation(whenDone)
Canceling a Scheduled Notification
To cancel a notification that you’ve scheduled from the client use cancelScheduledNotification:.
[TeakNotification cancelScheduledNotification:@"scheduleId"];
TeakNotification.cancelScheduledNotification("scheduleId")
Cancel All Client-Scheduled Notifications
Using cancelAll will cancel all of the notifications which were scheduled from client-side code.
[TeakNotification cancelAll];
TeakNotification.cancelAll()
Application Badge Count
A dashboard notification can only set your app icon’s badge to 0 or 1. To show an arbitrary count — for example, an in-game unread count — set it yourself with setApplicationBadgeNumber:.
Teak.sharedInstance()?.setApplicationBadgeNumber(5)
Notification Channels and Opt-Out Preferences
Teak can reach players over several channels: mobile push and email. Each channel, and each category within a channel, has an opt-in state. You can read a player’s current preferences and update them from your game, for example to build an in-game notification-settings screen. These are the player’s per-channel delivery preferences — distinct from the data-collection opt-outs on TeakUserConfiguration (see Disabling Automatic Data Collection).
Reading Opt-Out Preferences
A player’s channel preferences arrive in the TeakUserData notification, which Teak posts after your game calls login:withConfiguration:. Observe it and read the per-channel status from the notification’s userInfo. Each of pushStatus and emailStatus is a dictionary whose state is one of opt_out, available, opt_in, absent, or unknown.
NotificationCenter.default.addObserver(forName: Notification.Name(TeakUserData), object: nil, queue: nil, using:{notification in
if let pushStatus = notification.userInfo?["pushStatus"] as? [String: Any] {
print("Push opt-in state: \(pushStatus["state"] ?? "unknown")")
}
})
Updating Opt-Out Preferences
Update an entire channel with setState:forChannel:, or a single category within a channel with setState:forChannel:andCategory:. The channel is one of TeakChannelTypeMobilePush or TeakChannelTypeEmail.
When setting state from the SDK, you may only assign TeakChannelStateOptOut or TeakChannelStateAvailable.
|
// Opt the player out of marketing emails.
Teak.sharedInstance()?.setState(TeakChannelStateOptOut, forChannel: TeakChannelTypeEmail)
// Make a specific push category available to the player again.
Teak.sharedInstance()?.setState(TeakChannelStateAvailable, forChannel: TeakChannelTypeMobilePush, andCategory: "daily_reminders")
Player Properties
Player Properties are strings or numbers associated with each player of your game in Teak. Player Properties have several uses, including:
-
Targeting players for a send by using the player properties Audience rule
-
Personalizing push notification content using custom tags
-
Personalizing email content using custom tags
-
Personalizing deep links from Links, push notifications, and emails to take players to a meaningful location in your game
You do not need to register the property in the Teak Dashboard prior to sending them from your game, however you will need to register them in the Teak Dashboard before using them in targeting. Only Player Properties set to permit client updates can be updated through the SDK. Player Properties set to permit server updates may only be updated through the Server API.
Number Property
- To set a number property, use
Teak.setNumberProperty("bankroll", value: newCoinBalance)
Number Player Properties can store values between -999999999999999999999999999.999999999 and 999999999999999999999999999.999999999.
Custom Analytics Events
You can send custom analytics events to Teak to track player behavior. Teak models an event as an action taken on a type of object, optionally with a specific instance of that object.
Use trackEventWithActionId:forObjectTypeId:andObjectInstanceId: to record an event:
Teak.sharedInstance()?.trackEvent(withActionId: "level_complete", forObjectTypeId: "level", andObjectInstanceId: "10")
To keep a running count for an event, use incrementEventWithActionId:forObjectTypeId:andObjectInstanceId:count::
Teak.sharedInstance()?.incrementEvent(withActionId: "coins_spent", forObjectTypeId: "store", andObjectInstanceId: "gems", count: 50)
Deep Links
Deep Links are a way to link to specific screens in your game that will open when the game is launched from a notification or Universal Link.
These are useful for promoting new content or linking directly to sale content in the game.
| For the marketing team to use Deep Links, they will have to add the URL to their notifications in the dashboard. So, keep a master list of active deep links that can be shared with your team, so everyone knows what is available for use. |
Deep Linking with Teak is based on routes, which act like URLs. Route patterns may include named parameters, allowing you to pass in additional data.
- Add routes using
You need to register your deep link routes before you call Teak.login().
|
Teak.registerDeepLinkRoute("/store/:sku", name: "Store", description: "Open the store to the given SKU", block: {params in
print("Taking the player to \(params["sku"]!)")
})
How Routes Work
Routes work like URLs where parts of the path can be a variable. In the example
above, the route is /store/:sku. Variables in the path are designated with :.
So, in the route /store/:sku there is a variable named sku.
This means that if the deep link used to launch the app was /store/io.teak.test.dollar
was used to open the app, it would call the function and assign the value io.teak.test.dollar
to the key sku in the dictionary that is passed in.
This dictionary will also contain any URL query parameters. For example:
/store/io.teak.test.dollar?campaign=email
In this link, the value io.teak.test.dollar would be assigned to the key sku,
and the value email would be assigned to the key campaign.
When Are Deep Links Executed
Deep links are passed to an application as part of the launch. The Teak SDK holds
onto the deep link information and waits until your app has finished launching,
and initializing. Deep links will be processed when your game calls Teak.login().
Using Deep Links
A Deep Link route may be added to any notification or email in the Advanced section when setting up a Message or Link. We recommend documenting what routes are implemented and how to use them, with examples, for your marketing team to add to notifications, emails, and links.
Session Attribution
Each time your game launches Teak will post a notification with all of the attribution data it has for the launch, if available, to the default notification center with the name Notification.Name(TeakPostLaunchSummary)
This callback will be called after your game calls login:withConfiguration:, and is primarily intended to assist in reporting session attribution to other analytics systems.
NotificationCenter.default.addObserver(forName: Notification.Name(TeakPostLaunchSummary), object: nil, queue: nil, using:{notification in
let channelName = notification.userInfo!["teakChannelName"] as! Optional<String>
if(channelName == nil) {
print("Launch not attributed to a Teak source")
return
}
print("Launch attributed to \(channelName!)")
print("Launch came from a click on \(notification.userInfo!["teakCreativeName"] as! String)")
print("Launch was \(notification.userInfo!["teakRewardId"] as! NSObject == NSNull() ? "not" : "") rewarded")
})
Debugging with a Log Listener
Teak emits internal log events as it runs. You can observe them by assigning a logListener block, which is useful for debugging your integration or forwarding Teak’s diagnostics into your own logging system.
Teak.sharedInstance()?.logListener = { event, level, eventData in
print("Teak \(level): \(event) \(eventData ?? [:])")
}