Working with Contexts

Welcome to the Facebook Instant Games SDK Tutorials. This series of tutorials covers many aspects of using the Facebook Instant Games SDK.

In this tutorial we will take a look contexts using the Facebook Instant Games SDK.

What is a Context?

Facebook Instant Games revolve very heavily around the concept of the context. What is a context? A context is basically a collection of players in some area of Facebook. A few examples:

  • POST – This is a Facebook post
  • THREAD – A messenger thread
  • GROUP – A Facebook group
  • SOLO – The default with just the player

Each context has its own unique ID that allows you to identify it and switch into it to perform operations in the context.
What sort of operations? Once you are in a context your game can perform various operations such as get all of the players in the context, post messages to the context about the current state of the game. You can also store and retrieve leaderboard scores that are specific to that context only. Context ID’s are unique and persistent so you can store a context’s ID and come back to it at any time.

You generally post an update to a context when something important happens in your game. For example, you have just beaten a friends score and you want them to know. This helps with retention because all players in the thread or chat or whatever context you are in will see the rich message (a message usually consists of an image from the game, a title, a sub title and a call to action button). The rich message can also contain hidden meta data about the game, this will be passed to the game via entry point data when anyone clicks the posted call to action to launch the game. This enables information to be passed around from player to player in a none real-time / sort of turn based environment. I say sort of because you cannot post a new message to the context until another player in the context has posted a message back to the context. This is an anti spamming mechanism to prevent a user spamming a single context.

Querying the Context

You can find out information about the context you are currently in by querying the FBInstant.context object for information such as ID, type, size etc.., for example:

var context_id = FBInstant.context.getID();
var context_type = FBInstant.context.getType();

Its useful to know information about the context as you may want to adjust game play and user interface to match how many players are playing the game together.

Choosing a Context

By far the easiest way to create a context between your player and their friends is using chooseAsync:

FBInstant.context.chooseAsync(options)
.then(function() {
    // We are now in a context with other players
}).catch(function(error) {
    // User probably cancelled or some other error occurred
});

Calling chooseAsync() pops open a dialog to the player which allows them to select a player or group of players to play with (including players that have not yet played the game). When chooseAsync() returns successfully you are placed in a context with the chosen players. Note at this point, if any players within the context have not yet played your game then you will not be able to query them, their data is protected until they open the game and click the Play Game button.

Note that you can pass optional options into chooseAsync() to limit the type and number of players that can be selected by the player.

Creating a Context

An alternative to choosing a context is creating one yourself. You can create a context between the player and another player as shown below:

FBInstant.context.createAsync(player_id)
.then(function() {
    // We are now in a context with the other player
}).catch(function(error) {
    // Some error occurred
});

The player_id parameter is the ID of another player that already plays the game and is connected to you. We will look at connected players in the next tutorial.

Switching into a Context

It is also possible to switch from one context to another. Each context has its own unique ID when created, you can store these ID’s in the players game data and retrieve them at a later date. To switch into a different context we call switchAsync():

FBInstant.context.switchAsync(context_id)
.then(function() {
    // We have switched into a previously created context
}).catch(function(error) {
    // Some error occurred
});

This feature is very useful because it allows games sessions to continue over a long period of time. For example, in my game Lets Bounce, I remember all contexts that the player has played in and present them to the user to allow them to continue playing against any other player that they have challenged or been challenged by in the past.

Context Players

You can retrieve a list of all active players (played withub the last 90 days) in the current context that have played the game:

FBInstant.context.getPlayersAsync()
.then(function(players) {
    // players contains a list of player objects, one for each active player in the context
}).catch(function(error) {
    // Error collecting players
});

Like with the main player you can get details of each player in the players array, by calling functions such as getID(), getName(), getPhoto().
You can use this information to determine who else is playing with the player which is especially useful in multiplayer games.

NOTE: When you first invite a player to play the game via a call to something like ChooseAsync(), when you retrieve the list of context players, the invited player will be missing, they will only appear in the list once they have played the game for the first time.

Posting Context Updates

One of the most powerful features of Facebook Instant Games is the ability to post update messages to all players within the context. When a custom update message is sent, all players in the context are notified of the update. To post a custom update message to the context you can call updateAsync(). Lets take a look at a quick example:

var state_data = {
    id: FBInstant.player.getID(),
    level: 10,
    score: 1234
};

FBInstant.updateAsync({
    action: "CUSTOM",
    cta: "Play Me",
    image: image64,
    text: {
        default: "I challenge thee to a duel",
    },
    template: "",
    data: { myReplayData: state_data },
    strategy: "IMMEDIATE",
    notification: "NO_PUSH",
})
.then(function(){
    // Message was sent
}).catch(function(error) {
    // Error sending message
});

The above piece of code will post a fancy rich message to the context which all players in the context will receive and see. The parameters passed to updateAsync need a little more explanation:

  • action – Has to be CUSTOM
  • cta – Call to action text that is displayed on the message button
  • image – A base 64 encoded string of an image that will be sent with the custom update message
  • text: The main text body of the message that is sent to the context
  • template – ID of a custom update template
  • data – Meta data that will be passed to the game via entry point data when the game is launched from this message. Max 1000 characters when stringified.
  • strategy – Defines when and which update to send, can be IMMEDIATE, IMMEDIATE_CLEAR AND LAST. LAST sends the last custom update sent to the context when the game exits. IMMEDIATE sends immediately and IMMEDIATE_CLEAR sends immediately and clears any existing pending updates
  • notification: Can be used to send via push notifications

Note that the strategy section is quite important. You can only send one custom update to a specific context in a game session, if the recipient does not respond to it then any more updates you send will be ignored. If you use a version of IMMEDIATE then the message will be sent immediately and you cannot send another to that context until the player re-runs the game or someone else responds to the message by sending a custom update back to the context. The LAST strategy is a little more flexible as you can send many context update messages but only the very last will be sent as the user exits the game. This situation is useful if for example the player is playing a game consisting of rounds and you want to always post the players best score to the context.

The based64 image that accompanies the message can be either a pre-defined base64 string or you can generate one from a canvas by calling canvas.toDataURL(“image/png”) or canvas.toDataURL(“image/jpg”). I generally create a small canvas (around 600×200 pixels) and render an image, the players avatar and name to personalise the message image. You can also post screen shots of the game, by calling toDataURL on the main canvas.

Leave a Reply