Share
Playing with Fire(base) (DevFest Florida)
Firebase is a feature-rich platform that provides Android apps with a powerful foundation for acquiring users and keeping them engaged. For a recent news app I developed, I employed Cloud Messaging, Remote Config, Dynamic Links, and App Indexing. In this talk, I'll describe practical examples of how I used these features, as well as a few places where I nearly got burned. I'll explain how I:
● Implemented custom push notifications using Cloud Messaging
● Defined simple A/B tests with Remote Config
● Acquired users with Dynamic Links in app banners
● Used App Indexing to get our app into search results
● Recorded events and user properties to measure performance in Analytics
Download the PDF for a copy with clickable links.
Video available at https://www.youtube.com/watch?v=EBVSbHiuyig
Eric Fung
Transcript
81 slides
-
Feature Tour Click website banner to install app @gnufmuffin •
DevFest Florida, 2016-11-05 -
Feature Tour Click website banner to install app @gnufmuffin •
DevFest Florida, 2016-11-05 -
Feature Tour Browse article summaries, tap to read @gnufmuffin •
DevFest Florida, 2016-11-05 -
Feature Tour Browse article summaries, tap to read @gnufmuffin •
DevFest Florida, 2016-11-05 -
Feature Tour Receive notification for new articles @gnufmuffin • DevFest
Florida, 2016-11-05 -
Feature Tour Search results highlight app content, and link to
app @gnufmuffin • DevFest Florida, 2016-11-05 -
Feature Tour Previously viewed articles are suggested in search results
@gnufmuffin • DevFest Florida, 2016-11-05 -
What is it? Gets app into Google search results, and
associates it with your website @gnufmuffin • DevFest Florida, 2016-11-05 -
What does it give you? — Install cards for users
who don't have app @gnufmuffin • DevFest Florida, 2016-11-05 -
What does it give you? — Install cards for users
who don't have app — Deep links launch app from search results @gnufmuffin • DevFest Florida, 2016-11-05 -
What does it give you? — Install cards for users
who don't have app — Deep links launch app from search results — Viewed content appears in search autocompletion @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 1. Identify website URL structure
http://www.shopify.com/blog/really-informative-article http://www.shopify.ca/blog/topics/ http://www.shopify.in/blog/topics/informative @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 1. Identify website URL structure
http://www.shopify.com/blog/<title-slug-of-article> http://www.shopify.ca/blog/topics/ http://www.shopify.in/blog/topics/<subject> ! Watch out for shared prefix in paths! @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 2. Associate website with app
On Android 6.0+, create a Digital Asset Link — Upload to /.well-known/assetlinks.json @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 2. Associate website with app
Example assetlinks.json [ { "relation": [ "delegate_permission/common.handle_all_urls" ], "target": { "namespace": "android_app", "package_name": "com.shopify.blog", "sha256_cert_fingerprints": [ "00:01:02:03…" ] } } ] @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 2. Associate website with app
On Android < 6.0, associate in Search Console — Add Android app as a new property — Link webpages to app by adding markup on page — Get Google to crawl your site @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 2. Associate website with app
Example markup for /blog/really-informative-article <link rel="alternate" href="android-app://com.shopify.blog/https/↩ www.shopify.com/blog/really-informative-article" /> @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 2. Associate website with app
! Without linkage, user sees chooser @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 3. Add intent filters to
Android manifest <intent-filter> … <data android:scheme="https" ↩ android:host="www.example.com" ↩ android:path="/recipes"> … — For each Activity, define one or more handled inbound URLs @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 3. Add intent filters to
Android manifest <intent-filter> … <data android:scheme="http" /> <data android:scheme="https" /> <data android:pathPrefix="/blog" /> <data android:host="www.shopify.com" /> <data android:host="www.shopify.ca" /> <data android:host="www.shopify.in" /> … ! All data elements contribute to filter @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 3. Add intent filters to
Android manifest http://www.shopify.com/blog/<title-slug-of-article> http://www.shopify.com/blog/topics/<subject> — What if I want different activities to handle URLs with same prefix? @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 3. Add intent filters to
Android manifest @Override protected void onCreate(Bundle savedInstanceState) { Uri uri = getIntent.getData(); String uriPath = uri.getPath(); if (uriPath.startsWith("/blog/topics")) { // launch Activity for handling topics } else { // launch Activity for handling articles } ! Use a router Activity @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 4. Index user action To
get user action indexed (for search autocomplete): — Include App Indexing library dependency — Create Thing for Action — Call AppIndex.AppIndexApi.start() and stop() @gnufmuffin • DevFest Florida, 2016-11-05 -
App Indexing: How To Implement 4. Index user action Action
also appears in https://history.google.com/ @gnufmuffin • DevFest Florida, 2016-11-05 -
What is it? Cross-platform deep linking that survives app installs,
and drives app installation from mobile web users @gnufmuffin • DevFest Florida, 2016-11-05 -
What does it give you? — Deep link into app,
triggers upgrade or install if necessary @gnufmuffin • DevFest Florida, 2016-11-05 -
What does it give you? — Deep link into app,
triggers upgrade or install if necessary — Short links @gnufmuffin • DevFest Florida, 2016-11-05 -
What does it give you? — Deep link into app,
triggers upgrade or install if necessary — Short links — Analytics @gnufmuffin • DevFest Florida, 2016-11-05 -
Dynamic Links: How To Implement 1. Create the links —
Enter basic details in console — Creates a short link @gnufmuffin • DevFest Florida, 2016-11-05 -
Dynamic Links: How To Implement 1. Create the links —
Can also construct long links programmatically — ! No analytics — Can create short links programmatically via REST API — From existing long links or from parameters @gnufmuffin • DevFest Florida, 2016-11-05 -
Dynamic Links: How To Implement 1. Create the links —
Pass d=1 when creating long link programmatically @gnufmuffin • DevFest Florida, 2016-11-05 -
Dynamic Links: How To Implement 1. Create the links !
Cannot delete Dynamic Links at the moment @gnufmuffin • DevFest Florida, 2016-11-05 -
Dynamic Links: How To Implement 2. Receive links in app
— Include Dynamic Link library dependency — ! Called firebase-invites — In every activity that could be launched, call AppInvite.AppInviteApi.getInvitation() — MAIN launch activity (if app was just installed) — Any activities with intent filter matching link @gnufmuffin • DevFest Florida, 2016-11-05 -
Dynamic Links: How To Implement 2. Receive links in app
— Analytics events automatically generated @gnufmuffin • DevFest Florida, 2016-11-05 -
Dynamic Links: How To Implement 2. Receive links in app
You must consume the invitation — ! If you don't, no analytic events will be generated @gnufmuffin • DevFest Florida, 2016-11-05 -
What is it? Cross-platform messaging service for reliable delivery of
messages @gnufmuffin • DevFest Florida, 2016-11-05 -
What does it give you? — Fast, free, and reliable
message delivery @gnufmuffin • DevFest Florida, 2016-11-05 -
What does it give you? — Fast, free, and reliable
message delivery — Display notifications @gnufmuffin • DevFest Florida, 2016-11-05 -
Comparison with Notifications — Graphical console for re- engagement —
No coding required — Built-in analytics @gnufmuffin • DevFest Florida, 2016-11-05 -
Which one? — Notifications — Basic messages meant to be
displayed — Open rate analytics @gnufmuffin • DevFest Florida, 2016-11-05 -
Which one? — Notifications — Basic messages meant to be
displayed — Open rate analytics — Cloud Messaging — Everything else @gnufmuffin • DevFest Florida, 2016-11-05 -
Cloud Messaging: How To Implement 1. Add messaging service to
app — Include Cloud Messaging library dependency — Declare messaging service @gnufmuffin • DevFest Florida, 2016-11-05 -
Cloud Messaging: How To Implement 1. Add messaging service to
app <service android:name=".notifications.MyFirebaseMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> @gnufmuffin • DevFest Florida, 2016-11-05 -
Cloud Messaging: How To Implement 1. Add messaging service to
app MyFirebaseMessagingService.java @Override public void onMessageReceived(RemoteMessage remoteMessage) { Map<String, String> data = remoteMessage.getData(); // React to message, e.g. create a Notification, or // schedule sync with server } @gnufmuffin • DevFest Florida, 2016-11-05 -
Cloud Messaging: How To Implement 2. Subscribe to topics —
Some uses cases don't require dealing with registration IDs — ! Publish/subscribe model firebase.subscribeToTopic("all_new_articles"); @gnufmuffin • DevFest Florida, 2016-11-05 -
Cloud Messaging: How To Implement 3. Send message — Send
message to FCM connection server — From your application server — Manually (e.g. cURL) @gnufmuffin • DevFest Florida, 2016-11-05 -
Cloud Messaging: How To Implement 3. Send message Example payload:
{ "data": { "article_id": "123400", "notif_type": "new_article" }, "to" : "/topics/all_new_articles", "restricted_package_name": "com.example" } @gnufmuffin • DevFest Florida, 2016-11-05 -
Cloud Messaging: How To Implement 3. Send message Example cURL
invocation: curl \ --header "Authorization: key=${FCM_SERVER_KEY}" \ --header "Content-Type: application/json" \ https://fcm.googleapis.com/fcm/send \ --data-ascii "${BODY}" @gnufmuffin • DevFest Florida, 2016-11-05 -
Cloud Messaging: How To Implement 3. Send message — !
Understand data vs notification messages — Default behaviour may not be what you want @gnufmuffin • DevFest Florida, 2016-11-05 -
What is it? Change behaviour and appearance of app without
needing a client update @gnufmuffin • DevFest Florida, 2016-11-05 -
What does it give you? — Tune parameters in app
— Appearance — Timing @gnufmuffin • DevFest Florida, 2016-11-05 -
What does it give you? — Tune parameters in app
— Appearance — Timing — Run experiments, A/B tests @gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config Overview — Single access point for storing config
data @gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config Overview — Single access point for storing config
data — Client handles fetching, caching, and activating remote config @gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config Overview — Single access point for storing config
data — Client handles fetching, caching, and activating remote config — Use console to define parameters, with optional conditions @gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config: How To Implement 1. Set up default values
in app — Include Remote Config library dependency — Define parameter names and values in defaults.xml @gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config: How To Implement 1. Set up default values
in app <defaultsMap> <entry> <key>sync_min_seconds</key> <value>300</value> </entry> <entry> <key>sync_max_seconds</key> <value>1500</value> </entry> <entry> <key>Experiment_notif_title</key> <value>notif_title_default</value> </entry> </defaultsMap> @gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config: How To Implement 1. Set up default values
in app — Apply defaults to Remote Config remoteConfig.setDefaults(R.xml.defaults); @gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config: How To Implement 1. Set up default values
in app — Read from config in your app long seconds = remoteConfig.getLong("sync_min_seconds"); String variant = remoteConfig.getString("Experiment_notif_title"); @gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config: How To Implement 2. Set up server values
@gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config: How To Implement 2. Set up server values
@gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config: How To Implement 3. Set up experiments Conditions
are used to target groups of users — User property, device property, audience, random percentile @gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config: How To Implement 3. Set up experiments e.g.
A/B test with equal buckets @gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config: How To Implement 3. Set up experiments Define
parameter values for each condition @gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config: How To Implement 4. Fetch remote config in
app remoteConfig.fetch(cacheExpiration) .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { remoteConfig.activateFetched(); // or, activate whenever appropriate } } }); @gnufmuffin • DevFest Florida, 2016-11-05 -
Remote Config: How To Implement 4. Fetch remote config in
app — Record variant as user property — Use to define Analytics audience analytics.setUserProperty("Experiment_notif_title_variant", remoteConfig.getString("Experiment_notif_title")); @gnufmuffin • DevFest Florida, 2016-11-05 -
Review — App Indexing: Gets app into Google search results
— Dynamic Links: Deep linking that survives app installs and drives re-engagement — Cloud Messaging: Service for reliable delivery of messages — Remote Config: Change behaviour and appearance of app after deploy @gnufmuffin • DevFest Florida, 2016-11-05 -
Further Reading App Indexing — https://firebase.google.com/docs/app-indexing/ — https://developer.android.com/training/app-links/ index.html —
https://realm.io/news/juan-gomez-android-app- indexing/ — https://moz.com/blog/how-to-get-your-app-content- indexed-by-google @gnufmuffin • DevFest Florida, 2016-11-05 -
Further Reading Dynamic Links — https://firebase.google.com/docs/dynamic-links/ Cloud Messaging — https://firebase.google.com/docs/cloud-messaging/
@gnufmuffin • DevFest Florida, 2016-11-05 -
Further Reading Remote Config — https://firebase.google.com/docs/remote-config/ — https://medium.com/@hitherejoe/exploring- firebase-on-android-ios-remote- config-3e1407b088f6#.46fwwrb3s
— https://riggaroo.co.za/ab-test-app-firebase-remote- config/ @gnufmuffin • DevFest Florida, 2016-11-05 -
Additional Resources (1/2) — Dev Summit: Nov 7 in Berlin:
https:// events.withgoogle.com/firebase-dev-summit/ — Status Dashboard: https:// status.firebase.google.com/ — Google Group: https://groups.google.com/forum/#! forum/firebase-talk — Slack: https://firebase-community.appspot.com/ @gnufmuffin • DevFest Florida, 2016-11-05 -
Additional Resources (2/2) — Blog: https://firebase.googleblog.com/ — YouTube channel: https://www.youtube.com/
channel/UCP4bf6IHJJQehibu6ai__cg — SDK Changelog: https://firebase.google.com/ support/releases — Quickstart samples: https://github.com/firebase/ quickstart-android @gnufmuffin • DevFest Florida, 2016-11-05 -
Let's have some questions! Email [email protected] Work www.shopify.com Twitter @gnufmuffin
Slides speakerdeck.com/efung/ Blog code.gnufmuffin.com @gnufmuffin • DevFest Florida, 2016-11-05