Home | History | Annotate | Download | only in billing
      1 page.title=In-app Promotions
      2 parent.title=In-app Billing
      3 parent.link=index.html
      4 page.metaDescription=Support promo codes in your app, which lets you give content or features away to a limited number of users free of charge.
      5 page.image=/images/play_dev.jpg
      6 page.tags="promotions, billing, promo codes"
      7 meta.tags="monetization, inappbilling, promotions"
      8 @jd:body
      9 
     10 <div id="qv-wrapper">
     11 <div id="qv">
     12   <h2>Quickview</h2>
     13   <h2>In this document</h2>
     14   <ol>
     15     <li><a href="#workflow">Creating and Redeeming Promo Codes</a></li>
     16     <li><a href="#supporting">Supporting Promo Codes in Your App</a></li>
     17     <li><a href="#testing">Testing In-app Promotions</a></li>
     18   </ol>
     19   <h2>See also</h2>
     20   <ol>
     21     <li><a href="{@docRoot}google/play/billing/billing_integrate.html">Implementing
     22     In-app Billing</a></li>
     23     <!-- TODO: link to blog post when available -->
     24   </ol>
     25 </div>
     26 </div>
     27 
     28 <p>
     29   Promo codes let you give content or features away to a limited number of
     30   users free of charge. After you create a promo code, you can distribute it
     31   subject to the
     32   <!--TODO: Link to TOS when/if they're available as a web page --> terms of
     33   service. The user enters the promo code in your app or in the Google Play Store app
     34   and receives the item at no cost. You can use promo codes in many ways to
     35   creatively engage with users, such as the following:
     36 </p>
     37 
     38 <ul>
     39   <li>A game could have a special item, such as a character or decoration,
     40   that's only available to players who attend an event. The developer could
     41   distribute cards with promo codes at the event, and users would enter their
     42   promo codes to unlock the item.
     43   </li>
     44 
     45   <li>An app developer might distribute promo codes at local businesses to
     46   encourage potential users to try the app.
     47   </li>
     48 
     49   <li>An app developer might give <em>friends and family codes</em> to its employees to
     50   share with their friends.
     51   </li>
     52 </ul>
     53 
     54 <p>
     55   Every promo code is associated with a particular <em>product ID</em> (also
     56   known as a <em>SKU</em>). You can create promo codes for your existing in-app
     57   products. You can also keep an SKU off the Play Store, so that the only way to get
     58   that item is by entering that SKU's promo code. When a user enters the promo
     59   code in the Play Store or in an app, the user gets the item, just as if
     60   they paid full price for it. If your app already uses <a href=
     61   "{@docRoot}google/play/billing/api.html">In-app Billing Version 3</a> to
     62   support in-app purchases, it's easy to add support for promo codes.
     63 </p>
     64 
     65 <h2 id="workflow">Creating and Redeeming Promo Codes</h2>
     66 
     67 <p>
     68   You create promo codes through the <a href=
     69   "https://play.google.com/apps/publish/" class="external-link">Google Play
     70   Developer Console</a>. Each promo code is associated with a single product
     71   registered in the developer console.
     72 </p>
     73 
     74 <p>
     75   A user can redeem a promo code in one of these two ways:
     76 </p>
     77 
     78 <ul>
     79   <li>The user can enter the promo code as part of the app's ordinary purchase flow, as
     80   described in <a href="{@docRoot}google/play/billing/billing_integrate.html">
     81   Implementing In-app Billing</a>. As far as the app is concerned, this is
     82   just like an ordinary purchase, except that the user makes payment with a
     83   promo code instead of with money.
     84   </li>
     85 
     86   <li>The user can redeem the code in the Google Play Store app. Once the user
     87   enters the code, the Play Store prompts the user to open the app (if they have
     88   the latest version installed) or to download or update it. Google doesn't
     89   currently support redeeming promo codes from the Google Play web store.
     90   </li>
     91 </ul>
     92 
     93 <h2 id="supporting">Supporting Promo Codes in Your App</h2>
     94 
     95 <p>
     96   To support promotion codes, your app must call the <a href=
     97   "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
     98   ><code>getPurchases()</code></a>
     99   method whenever the app starts or resumes. This method returns a bundle of all
    100   current, unconsumed purchases, including purchases the user made by redeeming
    101   a promo code. The simplest approach is to call <a href=
    102   "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
    103   ><code>getPurchases()</code></a>
    104   in your activity's {@link android.app.Activity#onResume onResume()} method,
    105   since that callback fires when the activity is created, as well as when the
    106   activity is unpaused. Calling <a href=
    107   "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
    108   ><code>getPurchases()</code></a>
    109   on startup and resume guarantees that your app finds out about all
    110   purchases and redemptions the user may have made while the app wasn't
    111   running. Furthermore, if a user makes a purchase while the app is running and
    112   your app misses it for any reason, your app still finds out about the
    113   purchase the next time the activity resumes and calls <a href=
    114   "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
    115   ><code>getPurchases()</code></a>.
    116 </p>
    117 
    118 <p>
    119   Your app should allow users to redeem promo codes inside the app
    120   itself. If your app supports the in-app purchase workflow (described in
    121   <a href=
    122   "{@docRoot}google/play/billing/billing_integrate.html#billing-requests">Making
    123   In-app Billing requests</a>), your app automatically supports in-app
    124   redemption of promo codes. When you launch the in-app purchase UI,
    125   the user has the option to pay for the purchase with
    126   a promo code. Your activity's {@link android.app.Activity#onActivityResult
    127   onActivityResult()} method receives a response intent telling the app whether the
    128   purchase was completed. However, your app should still call <a href=
    129   "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
    130   ><code>getPurchases()</code></a>
    131   on startup and resume, in case the purchase and consumption workflow
    132   didn't complete. For example, if the user successfully redeems a promo code
    133   and then your app crashes before the item is consumed, your app still receives
    134   information about the purchase when the app calls <a href=
    135   "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
    136   ><code>getPurchases()</code></a> on its next startup.
    137 </p>
    138 
    139 <p>
    140   Your app should also support the scenario where a user redeems a promo code
    141   in the Play Store app while the app is running. Your app can find out right
    142   away when the user redeems a code by registering a listener for the
    143   <code>PURCHASES_UPDATED</code> intent. The Play Store fires this intent
    144   whenever a user redeems a promo code.
    145 </p>
    146 
    147 <p>
    148   To listen for the <code>PURCHASES_UPDATED</code> intent, dynamically create a
    149   {@link android.content.BroadcastReceiver} object and register it to listen
    150   for <code>com.android.vending.billing.PURCHASES_UPDATED</code>. Register
    151   the receiver by inserting code similar to the following in your activity's {@link
    152   android.app.Activity#onResume onResume()} method:
    153 </p>
    154 
    155 <pre>IntentFilter promoFilter =
    156     new IntentFilter("com.android.vending.billing.PURCHASES_UPDATED");
    157 registerReceiver(myPromoReceiver, promoFilter);</pre>
    158 
    159 <p>
    160   When the user makes a purchase, the system invokes your broadcast receiver's
    161   {@link android.content.BroadcastReceiver#onReceive onReceive()} method. That
    162   method must call <a href=
    163   "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
    164   ><code>getPurchases()</code></a>
    165   to see what purchases the user has made.
    166 </p>
    167 
    168 <p>To reduce system overhead when your app
    169   isn't running, your activity's {@link android.app.Activity#onPause onPause()} method must
    170   unregister the broadcast receiver:
    171 </p>
    172 
    173 <pre>unRegisterReceiver(myPromoReceiver);</pre>
    174 
    175 <p class="note">
    176   <strong>Note:</strong> Don't register this broadcast receiver in the
    177   app manifest. Declaring the receiver in the manifest can cause the system to
    178   launch the app to handle the intent if the user makes a purchase while the app
    179   isn't running. This behavior is not necessary and may be annoying to the
    180   user.
    181   To find out about any purchases the user made while the app wasn't running,
    182   call <a href="{@docRoot}google/play/billing/billing_reference.html#getPurchases"
    183   ><code>getPurchases()</code></a> when the user launches the app.
    184 </p>
    185 
    186 <h2 id="testing">Testing In-app Promotions</h2>
    187 
    188 <p>
    189   If your app supports in-app promotions, test the following use
    190   cases.
    191 </p>
    192 
    193 <h3 id="test-inapp">User redeems promo code in the app</h3>
    194 
    195 <p>
    196   If the user redeems a promo code within the app's purchase flow, as described
    197   in <a href=
    198   "{@docRoot}google/play/billing/billing_integrate.html#billing-requests">Making
    199   In-app Billing requests</a>, the system invokes your activity's {@link
    200   android.app.Activity#onActivityResult onActivityResult()} method to handle
    201   the purchase. Verify that {@link android.app.Activity#onActivityResult
    202   onActivityResult()} handles the purchase properly, whether the user pays with money
    203   or a promo code.
    204 </p>
    205 
    206 <h3 id="test-playstore">User redeems promo code in the Google Play Store</h3>
    207 
    208 <p>
    209   If the user redeems a promo code in the Play Store, there are several
    210   possible workflows. Verify each one of these workflows.
    211 </p>
    212 
    213 <h4 id="test-app-uninstalled">App is not installed</h4>
    214 
    215 <p>
    216   If the user redeems a promo code for an app that is not installed on the
    217   device, the Play Store prompts the user to install the app. (If the app is
    218   installed but not up-to-date, the Play Store prompts the user to update the
    219   app.) Test the following sequence on a device that doesn't
    220   have your app installed.
    221 </p>
    222 
    223 <ol>
    224   <li>The user redeems a promo code for the app in the Play Store. The Play Store
    225   prompts the user to install your app.
    226   </li>
    227 
    228   <li>The user installs and launches your app. Verify that on startup, the app
    229   calls <a href=
    230   "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
    231   ><code>getPurchases()</code></a>
    232   and correctly detects the purchase the user made with the promo code.
    233   </li>
    234 </ol>
    235 
    236 <h4 id="test-app-not-running">App is installed, but not running</h4>
    237 
    238 <p>
    239   If the user redeems a promo code for an app that is installed on the device,
    240   the Play Store prompts the user to switch to the app. Test the
    241   following sequence on a device that has your app installed but not running:
    242 </p>
    243 
    244 <ol>
    245   <li>The user redeems a promo code for the app in the Play Store. The Play Store
    246   prompts the user to switch to your app.
    247   </li>
    248 
    249   <li>The user launches your app. Verify that on startup the app calls <a href=
    250   "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
    251   ><code>getPurchases()</code></a>
    252   and correctly detects the purchase the user made with the promo code.
    253   </li>
    254 </ol>
    255 
    256 <h4 id="test-app-running">App is installed and running
    257 </h4>
    258 
    259 <p>
    260   If the user redeems a promo code for an app that is currently running on the
    261   device, the Play Store notifies the app via a <code>PURCHASES_UPDATED</code>
    262   intent. Test the following sequence:
    263 </p>
    264 
    265 <ol>
    266   <li>The user launches the app. Verify that the app has properly registered itself to
    267   receive the <code>PURCHASES_UPDATED</code> intent.
    268   </li>
    269 
    270   <li>The user launches the Play Store app and redeems a promo code for the app. The Play
    271   Store fires a <code>PURCHASES_UPDATED</code> intent. Verify that your app's
    272   {@link android.content.BroadcastReceiver#onReceive
    273   BroadcastReceiver.onReceive()} callback fires to handle the intent.
    274   </li>
    275 
    276   <li>Your {@link android.content.BroadcastReceiver#onReceive onReceive()}
    277   method should respond to the intent by calling <a href=
    278   "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
    279   ><code>getPurchases()</code></a>. Verify that your app calls this method and that
    280   it correctly detects the purchase the user made with the promo code.
    281   </li>
    282 
    283   <li>The user switches back to your app. Verify that the user has the purchased
    284   item.
    285   </li>
    286 </ol>
    287