1page.title=In-app Promotions
2parent.title=In-app Billing
3parent.link=index.html
4page.metaDescription=Support promo codes in your app, which let you give content or features away to a limited number of users free of charge.
5page.image=/images/play_dev.jpg
6page.tags="promotions, billing, promo codes"
7meta.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. Once 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 Play Store app,
34  and gets the item at no cost. You can use promo codes in many ways to
35  creatively engage with users. For example:
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 code 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 out "friends and family" codes 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 a SKU off the Play Store, so 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 their 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 item
71  registered in the developer console.
72</p>
73
74<p>
75  When a user gets a promo code, they redeem it in one of 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. (We do not
89  currently support redeeming promo codes from the Google Play web store.)
90  </li>
91</ul>
92
93<p>
94  If the promo code is for a <a href=
95  "{@docRoot}google/play/billing/api.html#consumetypes">consumable product</a>,
96  the user can apply an additional code for the same product <em>after</em> the first
97  product is consumed. For example, a game might offer promo codes for a bundle
98  of extra lives. Betty has two different promo codes for that bundle. She
99  redeems a single promo code, then launches the game. When the game launches,
100  the her character receives the lives, consuming the item. She can now redeem
101  the second promo code for another bundle of lives. (She cannot redeem the
102  second promo code until after she consumes the item she purchased with the
103  first promo code.)
104</p>
105
106<h2 id="supporting">Supporting Promo Codes In Your App</h2>
107
108<p>
109  To support promotion codes, your app should call the <a href=
110  "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
111  ><code>getPurchases()</code></a>
112  method whenever the app starts or resumes. This method returns a bundle of all
113  current, unconsumed purchases, including purchases the user made by redeeming
114  a promo code. This simplest approach is to call <a href=
115  "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
116  ><code>getPurchases()</code></a>
117  in your activity's {@link android.app.Activity#onResume onResume()} method,
118  since that callback fires when the activity is created, as well as when the
119  activity is unpaused. Calling <a href=
120  "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
121  ><code>getPurchases()</code></a>
122  on startup and resume guarantees that your app will find out about all
123  purchases and redemptions the user may have made while the app wasn't
124  running. Furthermore, if a user makes a purchase while the app is running and
125  your app misses it for any reason, your app will still find out about the
126  purchase the next time the activity resumes and calls <a href=
127  "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
128  ><code>getPurchases()</code></a>.
129</p>
130
131<p>
132  In addition, your app should allow users to redeem promo codes inside the app
133  itself. If your app supports the in-app purchase workflow (described in
134  <a href=
135  "{@docRoot}google/play/billing/billing_integrate.html#billing-requests">Making
136  In-app Billing Requests</a>), your app automatically supports in-app
137  redemption of promo codes. When you launch the in-app purchase UI,
138  the user has the option to pay for the purchase with
139  a promo code. Your activity's {@link android.app.Activity#onActivityResult
140  onActivityResult()} method receives a response intent telling the app whether the
141  purchase was completed. However, your app should still call <a href=
142  "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
143  ><code>getPurchases()</code></a>
144  on startup and resume, just in case the purchase and consumption workflow
145  didn't complete. For example, if the user successfully redeems a promo code,
146  and then your app crashes before the item is consumed, your app still gets
147  information about the purchase when the app calls <a href=
148  "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
149  ><code>getPurchases()</code></a> on its next startup.
150</p>
151
152<p>
153  Your app should also support the scenario where a user redeems a promo code
154  in the Play Store app while the app is running. Your app can find out right
155  away when the user redeems a code by registering a listener for the
156  <code>PURCHASES_UPDATED</code> intent. The Play Store fires this intent
157  whenever a user redeems a promo code.
158</p>
159
160<p>
161  To listen for the <code>PURCHASES_UPDATED</code> intent, dynamically create a
162  {@link android.content.BroadcastReceiver} object and register it to listen
163  for <code>"com.android.vending.billing.PURCHASES_UPDATED"</code>. Register
164  the receiver by putting code like this in your activity's {@link
165  android.app.Activity#onResume onResume()} method:
166</p>
167
168<pre>IntentFilter promoFilter =
169    new IntentFilter("com.android.vending.billing.PURCHASES_UPDATED");
170registerReceiver(myPromoReceiver, promoFilter);</pre>
171
172<p>
173  When the user makes a purchase, the system invokes your broadcast receiver's
174  {@link android.content.BroadcastReceiver#onReceive onReceive()} method. That
175  method should call <a href=
176  "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
177  ><code>getPurchases()</code></a>
178  to see what purchases the user has made.
179</p>
180
181<p>
182  Your activity's {@link android.app.Activity#onPause onPause()} method should
183  unregister the broadcast receiver, to reduce system overhead when your app
184  isn't running:
185</p>
186
187<pre>unRegisterReceiver(myPromoReceiver);</pre>
188
189<p class="note">
190  <strong>Note:</strong> You should not register this broadcast receiver in the
191  app manifest. Declaring the receiver in the manifest can cause the system to
192  launch the app to handle the intent if the user makes a purchase while the app
193  isn't running. This behavior is not necessary, and may be annoying to the
194  user. Instead, your app should call <a href=
195  "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
196  ><code>getPurchases()</code></a>
197  when the user launches it, to find out about any purchases the user made
198  while the app wasn't running.
199</p>
200
201<h2 id="testing">Testing In-app Promotions</h2>
202
203<p>
204  If your app supports in-app promotions, you should test the following use
205  cases.
206</p>
207
208<h3 id="test-inapp">User redeems promo code in the app</h3>
209
210<p>
211  If the user redeems a promo code within the app's purchase flow, as described
212  in <a href=
213  "{@docRoot}google/play/billing/billing_integrate.html#billing-requests">Making
214  In-app Billing Requests</a>, the system invokes your activity's {@link
215  android.app.Activity#onActivityResult onActivityResult()} method to handle
216  the purchase. Verify that {@link android.app.Activity#onActivityResult
217  onActivityResult()} handles the purchase properly, whether the user uses cash
218  or a promo code.
219</p>
220
221<h3 id="test-playstore">User redeems promo code in the Play Store</h3>
222
223<p>
224  If the user redeems a promo code in the Play Store, there are several
225  possible workflows. You should verify each one of these.
226</p>
227
228<h4 id="test-app-uninstalled">App is not installed</h4>
229
230<p>
231  If the user redeems a promo code for an app that is not installed on the
232  device, the Play Store prompts the user to install the app. (If the app is
233  installed but not up-to-date, the Play Store prompts the user to update the
234  app.) You should test the following sequence on a device that does not
235  have your app installed.
236</p>
237
238<ol>
239  <li>User redeems a promo code for the app in the Play Store. The Play Store
240  prompts the user to install your app.
241  </li>
242
243  <li>User installs and launches your app. Verify that on startup, the app
244  calls <a href=
245  "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
246  ><code>getPurchases()</code></a>
247  and correctly detects the purchase the user made with the promo code.
248  </li>
249</ol>
250
251<h4 id="test-app-not-running">App is installed, but not running</h4>
252
253<p>
254  If the user redeems a promo code for an app that is installed on the device,
255  the Play Store prompts the user to switch to the app.  You should test the
256  following sequence on a device that has your app installed but not running:
257</p>
258
259<ol>
260  <li>User redeems a promo code for the app in the Play Store. The Play Store
261  prompts the user to switch to your app.
262  </li>
263
264  <li>User launches your app. Verify that on startup, the app calls <a href=
265  "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
266  ><code>getPurchases()</code></a>
267  and correctly detects the purchase the user made with the promo code.
268  </li>
269</ol>
270
271<h4 id="test-app-running">App is installed and running
272</h4>
273
274<p>
275  If the user redeems a promo code for an app that is currently running on the
276  device, the Play Store notifies the app via a <code>PURCHASES_UPDATED</code>
277  intent. You should test the following sequence:
278</p>
279
280<ol>
281  <li>User launches the app. Verify that the app has properly registered itself to
282  receive the <code>PURCHASES_UPDATED</code> intent.
283  </li>
284
285  <li>User launches the Play Store app and redeems a promo code for the app. The Play
286  Store fires a <code>PURCHASES_UPDATED</code> intent. Verify that your app's
287  {@link android.content.BroadcastReceiver#onReceive
288  BroadcastReceiver.onReceive()} callback fires to handle the intent.
289  </li>
290
291  <li>Your {@link android.content.BroadcastReceiver#onReceive onReceive()}
292  method should respond to the intent by calling <a href=
293  "{@docRoot}google/play/billing/billing_reference.html#getPurchases"
294  ><code>getPurchases()</code></a>. Verify that it calls this method, and that
295  it correctly detects the purchase the user made with the promo code.
296  </li>
297
298  <li>User switches back to your app. Verify that the user has the purchased
299  item.
300  </li>
301</ol>
302