Teak Features in Unity
Identify User
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 Teak.Instance.IdentifyUser()
.
// ...
Teak.UserConfiguration userConfiguration = new Teak.UserConfiguration {};
Teak.Instance.IdentifyUser(YOUR_USER_ID, userConfiguration);
Make sure that your user 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 makes customer support easier, and makes life easier for your analytics team. |
If you need to change players during a session, call Teak.Instance.IdentifyUser()
with the other player’s id. Teak will automatically end the current player’s session and start a new session for the new player id.
User 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 UserConfiguration
object passed to Teak.Instance.IdentifyUser()
.
If you need to update any of this additional data during a game session, call Teak.Instance.IdentifyUser()
with an appropriately configured UserConfiguration
object. Teak.Instance.IdentifyUser()
will never clear or remove information about a player, and fields that are not set on the UserConfiguration
object will be ignored.
Request Notification Permissions
On iOS and Android 13 and greater you are required to ask the user if you can send them notifications. Do that with the Teak.Instance.RegisterForNotifications()
call.
// ...
StartCoroutine(Teak.Instance.RegisterForNotifications(granted => {
Debug.Log("Player " + (granted ? "granted" : "denied") + " notification permissions.");
});
You can still make this call even if the player cannot be prompted for permissions again. In that case, the callback will be called passing in true if notification permissions are enabled, otherwise false if they are disabled.
Teak.Instance.PushNotificationState will not update until the callback is called.
|
Prompt a Player to Reenable Notifications
If notifications are disabled, you can prompt the player to re-enable them on the settings page for the app, and use Teak to go directly the settings for your app.
To get the state of push notifications, use Teak.Instance.PushNotificationState
Value |
Description |
UnableToDetermine |
Unable to determine the notification state. |
Enabled |
Notifications are enabled, your app can send push notifications. |
Disabled |
Notifications are disabled, your app cannot send push notifications. |
Provisional |
Provisional notifications are enabled, your app can send notifications but they will only display in the Notification Center (iOS 12+ only). |
NotRequested |
The user has not been asked to authorize push notifications (iOS only). |
if (Teak.Instance.PushNotificationState == Teak.NotificationState.Disabled) {
if (Teak.Instance.CanOpenNotificationSettings()) {
// Show the player a screenshot or guide on how to enable push notifications from notification settings, then...
Teak.Instance.OpenNotificationSettings();
} else if (Teak.Instance.CanOpenSettingsAppToThisAppsSettings()) {
// Show the player a screenshot or guide on how to enable push notifications from settings.
// On iOS this will require that the player tap 'Notifications' after the settings app launches.
// Then...
Teak.Instance.OpenSettingsAppToThisAppsSettings();
}
}
Local Notifications
Local Notifications let you schedule push notifications directly from your game code for the current player or other players. This differs from Standard push notifications, which your marketing team schedules for delivery in the Teak Dashboard.
Common use cases include informing players that their hourly bonus is ready or that a tournament is over.
Use Local Notifications when you need deeply personalized content or scheduling that the game code is better equipped to determine. For example, an hourly bonus should be a local notification scheduled by the game, since the game will know when the hourly bonus was last claimed, and when the next bonus will be ready. A daily bonus should be setup using a standard notification scheduled in the dashboard, since the timing is not specific to the game logic. |
You should not use Local Notifications for a new player flow/new user experience or lapsing player flow. Instead, your marketing team should create Triggered Schedules for these use cases.
Although you can schedule Local Notifications in your game code, you will still coordinate with your marketing team on content created on the Teak Dashboard. Discuss and document when your game triggers Local Notifications thoroughly so your marketing team can craft the most relevant messaging.
Setup a Local Notification
Before sending, you must configure the corresponding Local Schedule on the Teak Dashboard. Doing so gives you the full benefit of Teak’s analytics, A/B testing, and Content Management System when using local notifications.
The Name
you give the Schedule is the first parameter for any local notification scheduling calls. Your marketing team may already have set up some Local Schedules; be sure to ask them if they have and what names they’ve given the Local Schedules.
Schedule a Local Notification
All notification related methods are coroutines. Unless you want the
method to block execution, you must use |
To schedule a notification from your game, use:
IEnumerator Schedule(string scheduleName,
long delayInSeconds,
Dictionary<string, object> personalizationData,
System.Action<Reply> callback);
scheduleName
should be the name of a Local Schedule on the Teak Dashboard.
The personalizationData
parameter allows you to provide custom data that can be templated into each send using Local Notification Tags. Be sure to inform your marketing team what data you send under which keys so that the tags can be properly configured.
// Requires a Local Schedule on the Teak Dashboard with the Name "hourly_bonus"!
StartCoroutine(
Teak.Notification.Schedule(
"hourly_bonus", 3600, new Dictionary<string, object> { {"coins", 100000} },
(Teak.Notification.Reply reply) => {
if(!reply.Error) {
Debug.Log("Scheduled local notification to send in one hour, id is " + reply.ScheduleIds[0]);
}
}
)
);
Scheduling a Long-Distance Notification
A notification which is scheduled from code, but delivered to a different player beside the current player is called a "long distance notification".
Common use cases include notifing players of friend activity and achievements.
To schedule a long-distance notification from your game, use:
IEnumerator ScheduleNotification(string scheduleName,
long delayInSeconds,
string[] userIds,
System.Action<Reply> callback);
The maximum delay for a Long-Distance Notification is 30 days. |
Canceling a Local Notification
To cancel a previously scheduled notification, use:
IEnumerator CancelScheduledNotification(string scheduleId,
System.Action<Reply> callback);
Canceling all Local Notifications
To cancel all previously scheduled local notifications, use:
IEnumerator CancelAllScheduledNotifications(System.Action<Reply> callback);
This call is processed asynchronously. If you immediately call
TeakNotification.ScheduleNotification() after calling
TeakNotification.CancelAllScheduledNotifications() it is possible for your
newly scheduled notification to also be canceled. We recommend waiting until the
callback has fired before scheduling any new notifications.
|
Rewards
Whenever your game should grant a reward to a player Teak will let you know by sending
out an event to all listeners added to Teak.Instance.OnReward
.
Teak does not provide any in-game UI to inform a player if they received a reward or not. You should
add a listener to Teak.Instance.OnReward
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.
void MyRewardListener(TeakReward reward)
{
switch (reward.Status) {
case TeakReward.RewardStatus.GrantReward: {
// The user has been issued this reward by Teak
foreach(KeyValuePair<string, object> entry in reward.Reward)
{
Debug.Log("[Teak Unity Cleanroom] OnReward -- Give the user " +
entry.Value + " instances of " + entry.Key);
}
}
break;
case TeakReward.RewardStatus.SelfClick: {
// The user has attempted to claim a reward
// from their own social post
}
break;
case TeakReward.RewardStatus.AlreadyClicked: {
// The user has already been issued this reward
}
break;
case TeakReward.RewardStatus.TooManyClicks: {
// The reward has already been claimed its
// maximum number of times globally
}
break;
case TeakReward.RewardStatus.ExceedMaxClicksForDay: {
// The user has already claimed their maximum number of rewards
// of this type for the day
}
break;
case TeakReward.RewardStatus.Expired: {
// This reward has expired and is no longer valid
}
break;
case TeakReward.RewardStatus.InvalidPost: {
// Teak does not recognize this reward id
}
break;
}
}
And then adding it to the Teak.Instance.OnReward
event during Awake()
in any MonoBehaviour
:
void Awake()
{
Teak.Instance.OnReward += MyRewardListener;
}
See TeakReward for more details.
Universal Links
Teak’s Links are an implementation of iOS Universal Links and Android App Links. These are links that open your game from a URL. Links can be incentivized with Rewards.
If the game is not installed on the device, the user will be directed to your game in the app store. On a desktop web browser, the user will be taken to the Desktop URL from your game settings.
Most of the setup for Links is covered in the getting started guide.
-
Associated Domains checkbox is checked on the Apple Developer Site.
-
ShortLink Domain is setup in the ShortLinks section of
-
ShortLink Domain is copied to the Teak settings in Unity.
-
Build Post-Processing is on.
The remaining items to-do are:
-
Set a Desktop Game URL
Go to
and add the URL that should be opened when game links are clicked on desktop computers. -
Set a iTunes Product ID
Used to link to the game in the App Store on devices where the game is not installed. Set this in
-
Set a Android Package Name
Used to link to the game in the Play Store page on devices where the game is not installed. Set this in
in the Android App Links section. -
Add Android Certificate Fingerprints
Required for the optimal user experience on Android devices. Go to
and click the Add Android Certificate Fingerprints and follow the directions in the modal.
Once those are added, your game is setup to use Links. To confirm, create a new link on the dashboard and click on it on your devices. Your game should launch.
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:
void RegisterRoute(string route,
string name,
string description,
Action<Dictionary<string, object>> action);
You need to register your deep link routes before you call IdentifyUser .
|
void Awake()
{
Teak.Instance.RegisterRoute("/store/:sku", "Store", "Open the store to an SKU", (Dictionary<string, object> parameters) => {
// Any URL query parameters, or path parameters will be contained in the dictionary
Debug.Log("Open the store to this sku - " + parameters["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.Instance.IdentifyUser()
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 pass all of the attribution data it has for the launch, if available, to all listeners added to Teak.Instance.OnPostLaunchSummary
.
This callback will be called after your game calls Teak.Instance.IdentifyUser()
, and is primarily intended to assist in reporting session attribution to other analytics systems.
void MyPostLaunchSummaryListener(TeakPostLaunchSummary launchSummary)
{
if (launchSummary.ChannelName == null) {
Debug.Log("Launch not attributed by Teak");
return;
}
Debug.Log("Launch attributed to " + launchSummary.ChannelName);
Debug.Log("Launch came from click on " + launchSummary.CreativeName);
Debug.Log("Launch was " + (launchSummary.RewardId == null ? "not" : "") + " rewarded");
if (launchSummary.DeepLink != null) {
Debug.Log("Launch requested to link to " + launchSummary.DeepLink);
}
}
And then adding it to Teak.Instance.OnPostLaunchSummary
event during Awake()
in any MonoBehaviour
:
void Awake()
{
Teak.Instance.OnPostLaunchSummary += MyPostLaunchSummaryListener;
}
See TeakPostLaunchSummary for more details.
Player Opt-Out Preferences
We recommend providing players with an in-game UI to manage their opt-out preferences. By keeping the UI in-game you can reduce the number of players who opt-out of all notifications from their device settings and provide a simpler experience for players to reenable notifications.
Teak also provides Opt-Out Categories which can be configured on the Dashboard. Each notification or email must be assigned to an Opt-Out Category. This allows players to opt-out of specific types of messaging while continuing to receive other notifications or emails.
Reading Player Opt-Out Preferences
Teak will inform your game of all configured Opt-Out Categories through the Teak.Instance.OnConfigurationData
event.
void MyConfigurationDataListener(Teak.ConfigurationData configurationData) {
foreach(Teak.Channel.Category category in configurationData.ChannelCategories) {
Debug.Log("Opt-Out Category - Id: "+ category.Id + ", Player Facing Name: " + category.Name + ", Player Facing Description: " + category.Description);
}
}
void Awake()
{
Teak.Instance.OnConfigurationData += MyConfigurationDataListener;
}
After the OnConfigurationData
callback is called Opt-Out Categories will also be accessible through
Teak.Channel.Categories
. Before the OnConfigurationData
callback is called Teak.Channel.Categories
will be null
.
Teak will inform your game of the player’s current opt-out status through the Teak.Instance.OnUserData
event.
void MyUserDataListener(Teak.UserData userData) {
Debug.Log("Player's push channel state is: " + userData.PushStatus.StateName);
Debug.Log("Player's email channel state is: " + userData.EmailStatus.StateName);
foreach(Teak.Channel.Category category in Teak.Channel.Categories) {
Debug.Log("Player is " + (userData.PushStatus[category.Id] == Teak.Channel.State.OptIn ? "opted-in to" : " opted-out of") + category.Name + " for push.");
// Note: If the player has no email address then the state will always be Teak.Channel.State.Unknown!
Debug.Log("Player is " + (userData.EmailStatus[category.Id] == Teak.Channel.State.OptIn ? "opted-in to" : "opted-out of") + category.Name + " for email.");
}
}
void Awake()
{
Teak.Instance.OnUserData += MyUserDataListener;
}
Teak guarantees that OnConfigurationData will be called before OnUserData , and Teak.Channel.Categories will be available when OnUserData is called.
|
Updating Player Opt-Out Preferences
To change a player’s opt-out status for an entire channel, use
IEnumerator SetChannelState(Channel.Type channel,
Channel.State state,
System.Action<Channel.Reply> callback);
// Opt out of all push notifications
StartCoroutine(Teak.Instance.SetChannelState(Teak.Channel.PlatformPush, Teak.Channel.State.OptOut, (Teak.Channel.Reply reply) => {
if(reply.Error == false && reply.State == Teak.Channel.State.OptOut) {
Debug.Log("Opted player out of push");
}
}));
Changing a player’s opt-out status may fail if the player is not reachable by the given channel. In this case reply.Error will be true, and reply.Errors will be a dictionary containing more information.
|
To change a player’s opt-out status for a single Opt-Out Category, use
IEnumerator SetCategoryState(Channel.Type channel,
string category,
Channel.State state,
System.Action<Channel.Reply> callback);
// Opt a player out of the emails from the 'sales' Opt-Out Category
// Note: Will only work if there is an Opt-Out Category with the Id 'sales'!
StartCoroutine(Teak.Instance.SetCategoryState(Teak.Channel.Email, "sales", Teak.Channel.State.OptOut, (TeakChannel.Reply reply) => {
if(reply.Error == false && reply.State == Teak.Channel.State.OptOut) {
Debug.Log("Opted player out of emails for " + reply.Category);
}
}));
Player Properties
Teak can store up to 16 numeric, and 16 string properties per player. These properties can then be used for targeting.
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.
Numeric Property
- To set a numeric property, use
void SetNumericAttribute(string key,
double value);
Teak.Instance.SetNumericAttribute("coins", new_coin_balance);
Custom Analytics Events
Teak tracks a number of analytics event by default, including install, session start, in-app purchases facilitated by the platform app store, notification clicks, link clicks, and session timing, and nothing extra is needed to track them.
Teak can also track custom analytics events which can then be used for targeting. These events are automatically batched by the Teak SDK, you do not need to perform your own batching.
Event Format
Teak events are a tuple of values, 'action', 'object type' and 'object instance'. For example: ['LevelUp', 'Fishing', '13'].
Object instance, and object type are optional, but if you provide an object instance, you must also provide an object type, for example ['FishCaught', null, '13'] is not allowed, but ['FishCaught', 'Salmon'] is allowed.
Tracking an Event
To track that an event occurred, use:
void TrackEvent(string actionId,
string objectTypeId,
string objectInstanceId);
Teak.Instance.TrackEvent("LevelUp", "Fishing", "13");
Incrementing Events
Incremented events are used for analytics which grow over time. You cannot provide negative values.
To increment an event, use:
void IncrementEvent(string actionId,
string objectTypeId,
string objectInstanceId,
long count);
Teak.Instance.IncrementEvent("coin_sink", "slot", "Happy Land Slots", 25000);
Teak.Instance.IncrementEvent("spin", "slot", "Happy Land Slots", 1);
// <after the spin happens>
Teak.Instance.IncrementEvent("coin_source", "slot", "Happy Land Slots", 1000000);
Payment Reporting
Teak will automatically collect information for in-app purchases made using the platform app store on iOS, Android, and Amazon Fire devices.
On Facebook Canvas, if you are using Facebook Login for Gaming, you will need to report purchases manually with:
void ReportCanvasPurchase(string rawResult);
FB.Canvas.PayWithProductId(
this.testPurchaseSku,
"purchaseiap",
null,
null,
(IPayResult result) => {
if(!string.IsNullOrEmpty(result.Error)) {
Debug.LogError(result.Error);
} else {
Teak.Instance.ReportCanvasPurchase(result.RawResult);
}
}
);
Teak will automatically deduplicate reported purchases, including manually reported and automatically collected purchases. It is always safe to manually report Facebook Canvas purchases. |
Logout
You can log out the current player using Logout
. If the player is logged out, Teak
will not process deep links or rewards until a player is logged in, via Teak.Instance.IdentifyUser()
.
The current device will remain associated with the last player id passed to IdentifyUser , and Teak will continue to send
notifications to the device even if you call Logout . In general we do not recommend using Logout unless you have very specific
needs and can handle some players potentially being denied notification or email rewards.
|
Log Events
Teak communicates via semi-structured log events. You can view these in the device logs, but we also expose an event that you can use to listen for these logs inside Unity, as well as a wrapper class to help work with the log messages.
Getting Log Events from Teak
Create a handler for log events:
void HandleLogEvent(Dictionary<string, object> logData) {
Debug.Log(new TeakLogEvent(logData));
}
And assign it to Teak.Instance.OnLogEvent
:
Teak.Instance.OnLogEvent += HandleLogEvent;
See TeakLogEvent for more details.