Documentation

Did you find this helpful?

Using Player Publisher Data

Player Data vs Player Publisher Data

Player Data is information about a player, specific to a game title. Thus it should be used for title-specific information, such as saving your player's position in a dungeon, or other game-specific data. The Player Publisher Data is associated with the player account, as opposed to the player account plus the title. So it is used to save information about a player relevant to all titles in your studio (which may also contain title-specific information, for purposes of cross-title rewards). All titles within a Studio in PlayFab share a Publisher ID by default, and that ID defines this relationship. Player accounts exist at the publisher layer, and are shared across all titles with the same Publisher ID (and then additionally have distinct Player Data per title). If you need to have titles in a Studio that have different Publisher IDs, or titles in different Studios that share the same Publisher ID, you can open a ticket in the PlayFab community forums and our Developer Success team will help you out.

By the way, please don't confuse Player Publisher Data with Publisher Data which is key/value pair data shared by all titles (it is not per-player).

Player Publisher Data usage is nearly identical to Player Data usage. They are both dictionaries mapping a string to a JSON blob (or other arbitrary string value). Our examples will demonstrate saving JSON blobs, and focus on targeted examples of why you might use Player Publisher Data.

Some basic examples would be:

Grant a Reward for Playing Multiple Titles

Rewards usually involve other systems outside of Player Data, so this example demonstrates awarding virtual currency for simplicity.

Requirements:

  • A player must sign into both titles using the same credentials. One approach is to use recoverable credentials, as described in our Login Best Practices guide. To add a recoverable login to an anonymous account, see our Linking & Unlinking guide.
  • These examples require a working knowledge of Cloud Script: Our examples demonstrate basic data security to avoid player cheating. One could likewise use the Server API on a custom game server, if the title makes use of them.
  • Rewards triggered through PlayFab require usage of the appropriate PlayFab features. PlayFab rewards can be in the form of virtual currency, inventory items, custom player data, statistics, etc. Distributing rewards outside of PlayFab systems is an advanced topic and will not be covered in this guide.
  • It's also recommended that developers use good error handling on all Server API calls made from Cloud Script. This is another advanced topic, which we will cover in a separate tutorial we'll be posting shortly.

Step 1: Each game reports login to Publisher Data

Each game needs to report that a login occurred. For simplicity, our example only provides one reward for each title, for each other publisher title played. Feel free to expand on the idea with counters, timestamps, or other mechanisms to provide progressive or sequential rewards.

The following Cloud Script would need to be present in every game in your studio:

// Cloud Script/Javascript

var PUBLISHER_USED_TITLES_KEY = "playedTitleIds";
handlers.TrackTitleUsage = function () {
    // Get the User Publisher Data for this player, and convert it into our expected format
    var getRequest = { Keys: [PUBLISHER_USED_TITLES_KEY], PlayFabId: currentPlayerId };
    var getResult = server.GetUserPublisherInternalData(getRequest);
    var playedTitlesList = JSON.parse(getResult.Data[PUBLISHER_USED_TITLES_KEY].Value); // format is arbitrary, but this example assumes Array<string>
    if (!playedTitlesList)
        playedTitlesList = [];
    // Check if we've played this title already
    var alreadyPlayed = false;
    for (var i = 0; i < playedTitlesList.length; i++)
        alreadyPlayed = alreadyPlayed || playedTitlesList[i] === script.titleId;
    if (alreadyPlayed)
        return; // Nothing to do
    // Update the list of played titles, and re-save
    playedTitlesList.push(script.titleId);
    var setRequest = { PlayFabId: currentPlayerId, Data: { PUBLISHER_USED_TITLES_KEY: JSON.stringify(playedTitlesList) } };
    server.UpdateUserPublisherInternalData(setRequest);
}

Note in particular that this example demonstrates using server.GetUserPublisherInternalData and server.UpdateUserPublisherInternalData

Step 2: Each game checks for redeemable rewards

Once you are tracking which titles are played, you need to track and grant the rewards. This Cloud Script function will check for, and grant available rewards based on having played other titles.

// Cloud Script/Javascript

var PUBLISHER_REDEEMED_TITLES_KEY = "redeemedTitleIds";
var MY_CROSS_TITLE_REWARDS = { "AU": 10 };
handlers.CheckCrossTitleRewards = function () {
    // Get the publisher data concerning cross-title rewards for this player
    var getRequest = { Keys: [PUBLISHER_USED_TITLES_KEY, PUBLISHER_REDEEMED_TITLES_KEY], PlayFabId: currentPlayerId };
    var getResult = server.GetUserPublisherInternalData(getRequest);
    var redeemedTitleRewards = JSON.parse(getResult.Data[PUBLISHER_REDEEMED_TITLES_KEY].Value); // format is arbitrary, but this example assumes { [key: string]: Array<string> }
    if (!redeemedTitleRewards)
        redeemedTitleRewards = {};
    var playedTitlesList = JSON.parse(getResult.Data[PUBLISHER_USED_TITLES_KEY].Value); // format is arbitrary, but this example assumes Array<string>
    if (!playedTitlesList)
        playedTitlesList = [];

    // Determine which titles are un-redeemed
    var unredeemedTitleIds = [];
    for (var i = 0; i < playedTitlesList.length; i++) {
        if (!redeemedTitleRewards.hasOwnProperty(playedTitlesList[i]) && playedTitlesList[i] !== script.titleId)
            unredeemedTitleIds.push(playedTitlesList[i]);
    }
    if (unredeemedTitleIds.length === 0)
        return null; // Nothing to redeem

    // Give the cross title rewards
    var multiplier = unredeemedTitleIds.length;
    var actualRewards = {}; // MY_CROSS_TITLE_REWARDS is a global constant, so don't modify it or you'll mess up future calls
    // Please note that the number of API calls that may be made from Cloud Script, as well as the total available processing time is limited,
    // and so the number of rewards should be as small as possible (only one VC, in this case)
    for (var eachKey in MY_CROSS_TITLE_REWARDS) {
        actualRewards[eachKey] = MY_CROSS_TITLE_REWARDS[eachKey] * multiplier;
        server.AddUserVirtualCurrency({ PlayFabId: currentPlayerId, VirtualCurrency: eachKey, Amount: MY_CROSS_TITLE_REWARDS[eachKey] }); // Can only add 1 VC at a time
    }

    // Save the Publisher data indicating rewards are claimed
    redeemedTitleRewards[script.titleId] = playedTitlesList;
    var setRequest = { PlayFabId: currentPlayerId, Data: { PUBLISHER_REDEEMED_TITLES_KEY: JSON.stringify(redeemedTitleRewards) } };
    server.UpdateUserPublisherInternalData(setRequest);

    // Tell the client the reward
    return actualRewards;
};

Note in particular, this example demonstrates the use of server.GetUserPublisherInternalData (requesting multiple keys), server.UpdateUserPublisherInternalData, and server.AddUserVirtualCurrency.

The code blocks represent these steps:

Conclusion

Player Publisher Data and Player Data are structurally identical. Player Data should be title-specific, and Player Publisher Data should only contain information relevant across all of your titles.



Did you find this helpful?