This guide describes how to integrate with the APIs to support external offers
in eligible apps and regions. To learn more about the external offers program
including eligibility requirements and geographic scope see
[program requirements](https://support.google.com/googleplay/android-developer/answer/14372887).

## Play Billing Library setup

To use the external offers APIs,
[add version 6.2.1 or higher of the Play Billing Library dependency](https://developer.android.com/google/play/billing/getting-ready#dependency)
to your Android app. If you need to migrate from an earlier version, follow
the instructions in the [migration guide](https://developer.android.com/google/play/billing/migrate-gpblv5) before you attempt to implement
external offers.

## Connect to Google Play

The first steps in the integration process are the same as the ones described in
the [billing integration guide](https://developer.android.com/google/play/billing/integrate), with a few modifications when
[initializing your `BillingClient`](https://developer.android.com/google/play/billing/integrate#initialize):

- You need to call a new method to indicate that you want to use external offers: [`enableExternalOffer`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.Builder#enableExternalOffer()).

The following example demonstrates initializing a `BillingClient` with these
modifications:  

### Kotlin

    var billingClient = BillingClient.newBuilder(context)
      .enableExternalOffer()
      .build()

### Java

    private BillingClient billingClient = BillingClient.newBuilder(context)
        .enableExternalOffer()
        .build();

After you initialize the `BillingClient`, you need to [establish a connection to
Google Play](https://developer.android.com/google/play/billing/integrate#connect_to_google_play) as described in the integration guide.

## Check availability

Your app should confirm external offers are available by calling
[`isExternalOfferAvailableAsync`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient#isExternalOfferAvailableAsync(com.android.billingclient.api.ExternalOfferAvailabilityListener)).

This API returns `BillingResponseCode.OK` if external offers are available.
See [response handling](https://developer.android.com/google/play/billing/external/integration#response-handling) for details on how your app should
respond to other response codes.  

### Kotlin


    billingClient.isExternalOfferAvailableAsync(
      object : ExternalOfferAvailabilityListener {
        override fun onExternalOfferAvailabilityResponse(
          billingResult: BillingResult) {
            if (billingResult.responseCode !=  BillingResponseCode.OK) {
                // Handle failures such as retrying due to network errors,
                // handling external offers unavailable, etc.
                return
            }

            // External offers are available. Continue with steps in the
            // guide.
    })

### Java


    billingClient.isExternalOfferAvailableAsync(
      new ExternalOfferAvailabilityListener() {
        @Override
        public void onExternalOfferAvailabilityResponse(
          BillingResult billingResult) {
            if (billingResult.getResponseCode() != BillingResponseCode.OK) {
                // Handle failures such as retrying due to network errors,
                // handling external offers being unavailable, etc.
                return;
            }
            // External offers are available. Continue with steps in the
            // guide.
          }

    });

## Prepare an external transaction token

To report an external transaction to Google Play, you must have an external
transaction token generated from the Play Billing Library. A new external
transaction token must be generated each time the user visits an external
website through the external offers API. This can be done by calling the
[`createExternalOfferReportingDetailsAsync`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient#createExternalOfferReportingDetailsAsync(com.android.billingclient.api.ExternalOfferReportingDetailsListener)) API. This token should be
generated immediately before the user is directed outside the app. It should
never be cached and a new one should be generated each time the user is directed
outside the app.  

### Kotlin


    billingClient.createExternalOfferReportingDetailsAsync(
      object : ExternalOfferReportingDetailsListener {
        override fun onExternalOfferReportingDetailsResponse(
          billingResult: BillingResult,
          externalOfferReportingDetails: ExternalOfferReportingDetails?) {
            if (billingResult.responseCode !=  BillingResponseCode.OK) {
                // Handle failures such as retrying due to network errors.
                return
            }
            val externalTransactionToken =
                externalOfferReportingDetails?.externalTransactionToken
            // Persist the transaction token locally. Pass it to the external
            // website when showExternalOfferInformationDialog is called.
        }
    })

### Java


    billingClient.createExternalOfferReportingDetailsAsync(
      new ExternalOfferReportingDetailsListener() {
        @Override
        public void onExternalOfferReportingDetailsResponse(
          BillingResult billingResult,
          @Nullable ExternalOfferReportingDetails
            externalOfferReportingDetails) {
            if (billingResult.getResponseCode() != BillingResponseCode.OK) {
                // Handle failures such as retrying due to network errors.
                return;
            }

            String transactionToken =
              externalOfferReportingDetails.getExternalTransactionToken();

            // Persist the external transaction token locally. Pass it to the
            // external website when showExternalOfferInformationDialog is
            // called.
          }
    });

## Information dialog for users

To integrate with external offers, your eligible app must show an information
screen which helps users understand that they are about to be directed outside
the app to an external website. The information screen must be shown to users by
calling the [`showExternalOfferInformationDialog`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient#showExternalOfferInformationDialog(com.android.billingclient.api.ExternalOfferInformationDialogListener)) API before linking to an
external offer each time.  

### Kotlin


    // An activity reference from which the external offers information dialog
    // will be launched.
    val activity : Activity = ...;

    val listener : ExternalOfferInformationDialogListener =
      ExternalOfferInformationDialogListener {
          override fun onExternalOfferInformationDialogResponse(
            billingResult: BillingResult){
            // Check billingResult
        }
    }

    val billingResult = billingClient.showExternalOfferInformationDialog(
      activity, listener)

### Java


    // An activity reference from which the external offers information dialog
    // will be launched.
    Activity activity = ...;

    ExternalOfferInformationDialogListener listener =
      new ExternalOfferInformationDialogListener() {
        @Override
        public void onExternalOfferInformationDialogResponse(
          BillingResult billingResult) {
            if (billingResult.responseCode !=  BillingResponseCode.OK) {
              // Handle failures such as retrying due to network errors.
            }
            // Open the external website, passing along the external transaction
            // token as a URL parameter. If the user purchases an item, be sure
            // to report the transaction to Google Play.
          }
    }

    BillingResult billingResult =
      billingClient.showExternalOfferInformationDialog(activity, listener);

If this method returns `BillingResponseCode.OK`, then your app can proceed to
direct the user to the external website. If the method returns
`BillingResponseCode.USER_CANCELED`, your app must not continue opening the
website.

### Report transactions to Google Play

| **Note:** See [Enrolling in the external offers program](https://support.google.com/googleplay/android-developer/answer/14372887) for transaction reporting requirements.

All external transactions must be reported to Google Play
by calling the Google Play Developer API from your backend. External transactions
must be reported while providing an
`externalTransactionToken` obtained using the
[`createExternalOfferReportingDetailsAsync`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient#createExternalOfferReportingDetailsAsync(com.android.billingclient.api.ExternalOfferReportingDetailsListener)) API. If a user makes multiple
purchases, you may use the same
`externalTransactionToken` to report each purchase. To learn how to report a
transaction, see the [backend integration guide](https://developer.android.com/google/play/billing/outside-gpb-backend).

## Response handling

When an error occurs, the methods `isExternalOfferAvailableAsync`,
`createExternalOfferReportingDetailsAsync`, and
`showExternalOfferInformationDialog` might return responses other than
`BillingResponseCode.OK`. Consider handling these response codes as follows:

- `ERROR`: This is an internal error. Don't proceed with the transaction or opening the external website. Retry again by calling `showExternalOfferInformationDialog()` to display the information dialog to the user the next time you attempt to direct the user outside the app.
- `FEATURE_NOT_SUPPORTED`: The external offers APIs are not supported by the Play Store on the current device. Don't proceed with the transaction or opening the external website.
- `USER_CANCELED`: Don't proceed with opening the external website. Call `showExternalOfferInformationDialog()` again to display the information dialog to the user the next time you attempt to direct the user outside of the app.
- `BILLING_UNAVAILABLE`: The transaction is not eligible for external offers and therefore shouldn't proceed under this program. This is either because the user is not in an eligible country for this program or your account has not been successfully enrolled in the program. If it's the latter, check your enrollment status in the Play Developer Console.
- `DEVELOPER_ERROR`: There is an error with the request. Use the debug message to identify and correct the error before proceeding.
- `NETWORK_ERROR, SERVICE_DISCONNECTED, SERVICE_UNAVAILABLE`: These are transient errors that should be handled with an appropriate retry policy. In the case of `SERVICE_DISCONNECTED`, re-establish a connection with Google Play before retrying.

## Test external offers

License testers should be used to test your external offers integration. You
won't be invoiced for transactions that have been initiated by license tester
accounts. See [Test in-app billing with application licensing](https://support.google.com/googleplay/android-developer/answer/6062777) for more
information on configuring license testers.

## Next steps

Once you've finished in-app integration, you're ready to [integrate your
backend](https://developer.android.com/google/play/billing/outside-gpb-backend).