Integrating the Google Play Grouping API

The Google Play Grouping API lets app developers share data about their users (aka user tags) with Google Play and then use those tags to customize content across the Play Store.

For now, the existence of a specific tag can be used specifically as a targeting condition of Promotional Content (aka LiveOps). In the future, more types of content will be targetable and use cases beyond targeting will be added.

The API provides strong privacy guarantees for end users, including user-visible notification when the API is first used, and opt-out options managed by Google.

Note: The Grouping API is not generally available yet. If you're interested, please reach out through your Google Play partner manager to get allowlisted.

High level flow

The Grouping API operates with two main entities:

  • User tokens are opaque privacy-preserving user identifiers.
  • User tags are atomic pieces of information provided by the developer about a specific user.

In a typical case, the app or game regularly generates a fresh user token (for example, daily when the user opens the app) and stores it on the app back-end server for later use. Within its lifetime, the token can be repeatedly used to write tags for the user identified by that token.

The technical details of the Grouping API integration differ based on whether you’re classified as an app or game on the Play Store - the SDKs and API end-points used to obtain the user token differ, tagging is the same for both.

Flow for apps

Step 1: The app requests generation of the user token by invoking a method in the new Play Grouping SDK. The call is asynchronous, requires a persona and a window token parameters, and produces a token or an error.

Persona is a stable user identifier, based on your own user identity system - the account ID, and optionally the active in-app profile ID (if the app supports them). Persona must be an opaque encrypted or hashed string, free from sensitive or personally-identifiable data. Personas will be transparently mapped 1:1 with Google user accounts in the Play Store.

The window token is used to show a snackbar with user notice, informing about the data exchange. This happens only on the first token generation for the given user and app.

Step 2: The app transfers the token to the app back-end server.

Step 3: The app back-end server calls VerifyToken Cloud API end-point, asserting the expected app package name and persona associated with the token. If the call succeeds, the token may now be stored in the back-end database under the appropriate account ID, and later used to manipulate user tags. A token needs to be verified only once during its lifetime.

Token verification serves as a security mechanism and is mandatory.

Step 4: The app-back end server calls CreateOrUpdateTags Cloud API end-point to write tags for the user represented by the given token.

Flow for games

Step 1: The game signs the user in with Play Games Services.

Depending on the type of the sign-in, the game receives either a server auth code for an OAuth 2.0, or a Recall session ID.

Step 2: The game transfers the user sign in information to the game back-end server.

Step 3: The game back-end server generates a Grouping API user token using either the generatePlayGroupingApiToken or generateRecallPlayGroupingApiToken Cloud API end-point. Both APIs require the asserted app package name, and the persona associated with the token.

Persona is a stable user identifier, based on your own user identity system - the account ID, and optionally the active in-app profile ID (if the app supports them). Persona must be an opaque encrypted or hashed string, free from sensitive or personally-identifiable data. Personas will be transparently mapped 1:1 with Google user accounts in the Play Store.

If the call succeeds, the token may now be stored in the back-end database under the appropriate account ID, and later used to manipulate user tags.

Step 4: The game back-end server calls  CreateOrUpdateTags Cloud API end-point to write tags for the user represented by the given token.

Notes and tips

The Grouping API tokens and tags are subject to expiration. TTL for tokens is 30 days, and for tags 90 days.

Tokens are independent of each other. Namely, generation or verification of one token has no effect on other existing tokens. It is recommended to store the latest successfully verified token of a user.

For simplicity, we recommend handling token generation and verification on a best-effort basis. Since the token TTL is considerably long and new token can be generated frequently, an occasional failure doesn’t require special handling - if token generation or verification fails, discard that token/error and keep using any previously verified token you have for that user.

Unverified tokens (apps only) will be considered invalid in tag-modifying API calls. Typically, the persona-generating algorithm will make use of cryptographic secrets (encryption key or hashing salt) in which case the algorithm will live only on the app back-end server, and the resulting persona will be passed down from the server to the app. While it is ok to compute the persona inside the app itself, the server must never trust and use a persona that was generated by the app.

The Cloud API can be used in various modes, for example from a batch job that tags all users of a specific type, or continuously based on a stream of real-time user events.

The API imposes reasonable limits on the amount of requests, and on data size. Tentative size limits (subject to change) are: 128B for persona, 32B for tag keys and values, max 100 unique tag keys per app throughout the app lifetime. Tag keys cannot start with google_ or play_ (case-insensitive).

Generating user tokens for apps

If you’re a game, follow these steps instead.

Configure a Google Cloud project for your app

Before you can start making server calls to the Grouping API, you need to set up access to the Google Play Grouping API.

In the Google Cloud Console:

Create new or use an existing Google Cloud project. Note the Project name and Project ID for later.

  1. Under APIs & Services > Enabled APIs & services, enable the "Google Play Grouping API".
  2. Under APIs & Services > Credentials, create a new API key.
    Later, this guide will explain how to attach this API key to the Play Grouping API requests from your back-end server as a form of authentication.
    See also API Keys Overview for best security practices.

In the Google Play Console, navigate to the Store presence > Custom audiences section and finish the "Link a Google Cloud project" step (you can search by Project ID).

All steps require you to be an owner of the Google Cloud project in Google Cloud Console.

Please reach out to [email protected] if you encounter issues.

Generating unverified tokens in your Android app

1. Import the Play Grouping SDK

The Play Grouping SDK is hosted in the Google Maven repository and can be added to a Gradle-based Android app project by editing the appropriate build.gradle files.

Java

// Top-level build.gradle:

allprojects {

    repositories {

        // Make sure that the Google Maven Repository is present.

        google()

    }

}

 

// Application module build.gradle:

dependencies {

    // Add the Play Grouping SDK.

    implementation 'com.google.android.play:grouping:1.0.0'

}

2. Request the user token from the app

Generate the Grouping API user token by calling the client SDK. When successfully generated, send the token to your app back-end server for verification, storage and to manage tags of the user.

It is recommended to request token generation regularly when the user interacts with the app. For example, at a daily frequency when the app is opened.

Your app must be in the foreground when calling the SDK.

Java 

import android.os.IBinder;

import com.google.android.play.core.grouping.service.GroupingApiErrorCode;

import com.google.android.play.core.grouping.service.GroupingApiException;

import com.google.android.play.core.grouping.service.GroupingApiManager;

import com.google.android.play.core.grouping.service.GroupingApiManagerFactory;

 

// Persona is typically computed on the app back-end server,

// to protect cryptographic secrets.

String persona = ...;

// On the first token generation, the SDK will show the user a snackbar informing

// about the data exchange.

IBinder windowToken = getWindow().getDecorView().getWindowToken();

 

GroupingApiManager client =

    GroupingApiManagerFactory.create(getApplicationContext());

 

client

    .requestGroupingApiToken(persona, windowToken)

    .addOnCompleteListener(

        task -> {

          if (task.isSuccessful()) {

            String token = task.getResult().getString("token");

            // Send this API token to the app back-end server.

            // ...

          } else {

            Exception exception = task.getException();

            if (exception instanceof GroupingApiException) {

              @GroupingApiErrorCode

              int errorCode = ((GroupingApiException) exception).getErrorCode();

              // Handle ...

            }

          }

        });

3. Make a new app release

After you’ve integrated the SDK into your app, you need to upload and roll out the updated version to your users.

SDK errors FAQ

API_NOT_AVAILABLE (error #12)

  1. The app package name hasn’t been added to Google-managed allowlist. Please contact your Google BD partner for resolution.
  2. The Google Play services or the Play Store app on the device is outdated.
  3. The Google user account on the device is a special account type (for example, an enterprise Google account that is owned/managed by your organization). Retry on a device with a vanilla @gmail.com user account.

Verifying tokens

The server-server Play Grouping API is a RESTful API with API key authentication. As such, you can access it using any REST library and programming language. For generality, this guide will illustrate the API calls using plain curl (see Appendix for drop-in code snippets using the auto-generated Google API clients).

Before storing a user token in the back-end server’s database and using it for tagging users, the app back-end server must successfully verify the token by calling the VerifyToken API end-point. A token needs to be verified only once during its lifetime.

Token verification serves as a security mechanism to detect malicious client-side activities and is a mandatory prerequisite for using the token in tag-modifying API calls.

Shell

API_KEY="..."

PACKAGE_NAME="..."

TOKEN="..."

PERSONA="..."

BASE_URL="https://playgrouping.googleapis.com/v1alpha1"

 

curl -X POST \

  -H 'Content-Type: application/json; charset=utf-8' \

  -d "{ 'persona': 'personas/${PERSONA}' }" \

  "${BASE_URL}/apps/${PACKAGE_NAME}/tokens/${TOKEN}:verify?key=${API_KEY}"

Generating user tokens for games

If you’re an app, follow these steps instead.

Configure a Google Cloud project for your game

Before you can start making server calls to the Grouping API, you need to set up access to the Google Play Grouping API.

In the Google Cloud Console:

  1. Create new or use an existing Google Cloud project. Note the Project name and Project ID for later.
  2. Under APIs & Services > Enabled APIs & services, enable the "Google Play Grouping API."
  3. Under APIs & Services > Credentials, create a new API key.
    Later, this guide will explain how to attach this API key to the Play Grouping API requests from your back-end server as a form of authentication.
    See also API Keys Overview for best security practices.

In the Google Play Console, navigate to the Store presence > Custom audiences section and finish the "Link a Google Cloud project" step (you can search by Project ID).

All steps require you to be an owner of the Google Cloud project in Google Cloud Console.

Please reach out to [email protected] if you encounter issues.

Enable Play Grouping API for your Play Games Services project

If you have not integrated your game with Play Games Services yet, follow this guide.

To enable the Play Grouping API for your Play Games Services project, in the Google Play Console go to Grow users > Play Games Services > Configuration. Select "Edit properties" on the page, turn on "Play Grouping API" setting and hit "Save":

After you enabled the Play Grouping API for your Play Games Services project, your testers will start seeing this popup when they open the game:

This popup will only be shown for the first time a player has signed in into the game. It will be shown only to your testers while the change in Play Console is not published. After you publish the change in the Play Console, all your players will see it.

Generating the user token

The Grouping API user token is generated through a server-server API end-point.

If you integrate with Play Games Services through regular sign-in and server auth code following this guide, you will need to use the generatePlayGroupingApiToken end-point to generate the Grouping API user token.

If you integrate with Play Games Services through Recall sign-in following this guide, you will need to use the generateRecallPlayGroupingApiToken end-point to generate the Grouping API user token.

Note: In both cases, the user token is considered to be already verified, while apps need to explicitly verify each token through an extra API call.

Verification

We need to check if the game with the package name you want to generate the Grouping API user token for is owned by you. To make the check pass:

  • In the Google Cloud Console, create an OAuth client and link it in Play Games Services configuration following https://developer.android.com/games/pgs/console/setup#create_a_credential.
  • Upload the game AAB/APK in Play Store
    • You may have to get your release approved one time in any of the release tracks (for example, open/closed/internal testing).
  • You may have to wait for up to 24 hours after completing steps above for the check to start passing.

After the player has seen the popup and verification check passes, you will be able to generate Play Grouping API tokens through Play Games Services API.

Publishing

After you have verified that the Play Grouping API token is successfully generated for your testers, you can publish the change in the Play Console so it will be available for all players. To learn more, read Publish game changes.

API errors FAQ

  • "No valid Android OAuth client for the provided package name."
    • Package ownership verification check described in the Verification section has failed. Please make sure all of the steps are completed. 
  • "Play Grouping API is not enabled for this game project."
    • "Play Grouping API" setting is not enabled in the Play Console for your Play Games Services project. 
  • "Player has not seen the personalization popup yet."
    • Player has an old version of Google Play services on their device which does not have that popup yet.
    • Generate API was called with server auth code/Recall session ID which were obtained before the player has seen the popup. You can retry again with fresh credentials. 
  • "Package name <your_package_name> is not allowed to access the Play Grouping API."
    • The app package name hasn’t been added to Google-managed allowlist. Please contact your Google BD partner for resolution.

Tagging users

Once you’ve completed all the steps for generating user tokens, you can use the tokens in the Play Grouping API to modify tags of users represented by the tokens. This is the same for apps and games.

The server-server Play Grouping API is a RESTful API with API key authentication. As such, you can access it using any REST library and programming language. For generality, this guide will illustrate the API calls using plain curl (see Appendix for drop-in code snippets using the auto-generated Google API clients).

A tag consists of a key (string) and a value (string, int64, boolean, or timestamp). Each tag component is subject to size constraints (currently 32B). The key must conform to the regular expression "[a-zA-Z0-9_-]+".

Tags must be free of any sensitive or personally-identifiable information (including data like name, passport number, health data, ethnicity) about users.

Call the CreateOrUpdateTags API end-point to write a collection of tags. If a tag with a given key doesn’t exist yet, it is created; otherwise its value and timestamp is updated. One request can freely combine new and existing tags.

 

Shell

API_KEY="..."

PACKAGE_NAME="..."

TOKEN="..."

TAG_KEY="sample_tag"

TAG_INT_VALUE="42"

BASE_URL="https://playgrouping.googleapis.com/v1alpha1"

 

curl -X POST \

  -H 'Content-Type: application/json; charset=utf-8' \

  -d "{ 'tags': [

          { 'key': 'sample_numeric_tag', 'int64_value': 42 },

          { 'key': 'sample_boolean_tag', 'boolean_value': true },

          { 'key': 'sample_string_tag',  'string_value': 'hello world' },

          { 'key': 'sample_time_tag', 'time_value': { 'seconds': 1693399877 } } ] }" \

  "${BASE_URL}/apps/${PACKAGE_NAME}/tokens/${TOKEN}/tags:createOrUpdate?key=${API_KEY}"

Appendix: Code snippets for the Google APIs client library for Java

Code examples below assume usage of the Google API Java client that can be downloaded from the shared Drive folder. Please let us know if you need the client library for a different language.

Note (2023-08-31): The publicly available version of Google APIs doesn’t include the Play Grouping API client yet.

Initialize the Grouping API client

Java

import com.google.play.grouping.v1alpha1.GroupingServiceClient;

import com.google.play.grouping.v1alpha1.GroupingServiceSettings;

import com.google.api.gax.core.NoCredentialsProvider;

import com.google.api.gax.rpc.FixedHeaderProvider;

 

private static final String API_KEY = ...;

 

private static final GroupingServiceSettings CLIENT_SETTINGS =

    GroupingServiceSettings.newHttpJsonBuilder()

        // Authenticate using API key.

        .setCredentialsProvider(NoCredentialsProvider.create())

        .setHeaderProvider(FixedHeaderProvider.create("X-goog-api-key", API_KEY))

        .build();

 

// Create and use the API client.

try (GroupingServiceClient client = GroupingServiceClient.create(CLIENT_SETTINGS)) {

    ...

}

Verifying tokens (apps only)

Prerequisite: Initialize the Grouping API client section.

See the Verifying tokens (via REST) for details.

Java

import com.google.play.grouping.v1alpha1.GroupingServiceClient;

import com.google.play.grouping.v1alpha1.VerifyTokenRequest;

 

// You app package name.

// Format: "apps/{package_name}". For example, "apps/com.google.sample_package".

String packageName = ...;

 

// The to-be-verified user token.

// Format: "tokens/{token}".

String token = ...;

 

// Persona the token is expected to belong to.

// Format: "personas/{persona}".

String persona = computePersona(userId, optionalProfileId);        

 

GroupingServiceClient client = ...; // Created up previously.

 

try {

    VerifyTokenRequest verifyTokenRequest =

        VerifyTokenRequest.newBuilder()

            .setToken(token)

            .setAppPackage(packageName)

            .setPersona(persona)

            .build();

 

    client.verifyToken(verifyTokenRequest);

 

    // Success.

    // Store the token in the database for the given persona

    // (i.e. under the userId and profileId corresponding to the persona).

} catch (Exception e) {

    // Failure.

    // Discard the token, do NOT store it in your database as it is not verified.

}

Tagging users

Prerequisite: Initialize the Grouping API client section.

See the Tagging users (via REST) section for details.

Java

import com.google.play.grouping.v1alpha1.CreateOrUpdateTagsRequest;

import com.google.play.grouping.v1alpha1.CreateOrUpdateTagsResponse;

import com.google.play.grouping.v1alpha1.GroupingServiceClient;

import com.google.play.grouping.v1alpha1.Tag;

 

// You app package name.

// Format: "apps/{package_name}". For example, "apps/com.google.sample_package".

String packageName = ...;

 

// The previously verified token.

// Format: "tokens/{token}".

String token = ...;

 

GroupingServiceClient client = ...; // Created up previously.

 

try {

    Tag sampleTag =

        Tag.newBuilder()

            .setKey("sample_string")

            .setStringValue("hello_world")

            .build();

    CreateOrUpdateTagsRequest modifyTagsRequest =

        CreateOrUpdateTagsRequest.newBuilder()

            .setToken(token)

            .setAppPackage(packageName)

            .addTags(sampleTag)

            .build();

 

    CreateOrUpdateTagsResponse modifyTagsResponse =

          client.createOrUpdateTags(modifyTagsRequest);

 

    // Success.

    // ...

} catch (Exception e) {

    // Failure.

    // ...

}

 

Was this helpful?

How can we improve it?
false
Search
Clear search
Close search
Google apps
Main menu
13392634535670286426
true
Search Help Center
true
true
true
true
true
92637
false
false