Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Be instant and engaging on the mobile web - Goo...

Paul Kinlan
September 21, 2015

Be instant and engaging on the mobile web - Google Mobile for India

Paul Kinlan

September 21, 2015
Tweet

More Decks by Paul Kinlan

Other Decks in Programming

Transcript

  1. You don’t want to read our content right now WAIT

    3 MINUTES AND INSTALL OUR APP BAD!
  2. “I need my app to be installed. The Web can’t

    do that” - Every Tech Business in India*, August 2015
  3. “I need notifications for engagement. The Web can’t do that”

    - Every Tech Business in India*, August 2015
  4. “Network is terrible in India. I need to be fast.

    The Web can’t do that” - Every Tech Business in India*, August 2015
  5. “Deep access to hardware is why I need an app.

    The Web can’t do that” - Every Tech Business in India*, August 2015
  6. Mobile Native Mobile Web Load store Click install Accept Permission

    Download Go to homescreen Use Use Instant access
  7. In a consumer mobile app, every step you make a

    user perform before they get value out of your app will cost you 20% of users. http://blog.gaborcselle.com/2012/10/every-step-costs-you-20-of-users.html
  8. Mobile Native Mobile Web Load store Click install Accept Permission

    Download Go to homescreen Use Use 800 640 512 410 328 262 1000 Users Inferred from blog.gaborcselle.com Hypothetical numbers Inferred from blog.gaborcselle.com
  9. Mobile Native Mobile Web Load store Click install Accept Permission

    Download Go to homescreen Use Use 800 640 512 410 328 262 800 1000 Users Hypothetical numbers Inferred from blog.gaborcselle.com
  10. Use Use 262 800 Mobile Native Mobile Web Why app?

    Reach Performance Engagement Capabilities Installability
  11. Service workers are generic, event-driven, time-limited script contexts that run

    at an origin. What the spec says https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ Service Worker
  12. Service worker is a background script that sits between the

    browser and the networkOS What I say Service Worker
  13. Registering a Service Worker self.addEventListener('install', function(e) {}); self.addEventListener('activate', function(e) {});

    self.addEventListener('fetch', function(e) {}); navigator.serviceWorker.register('sw.js') .then(function(reg) { // Service Worker Registered }); Service Worker sw.js Web Page
  14. Users • Expect apps to be on the homescreen •

    Expect apps to be in the app switcher Installability
  15. How to get on the homescreen • Uses a service

    worker • Use HTTPS • Have a manifest declared Installability
  16. <link rel="manifest" href="manifest.json"> HTML { "short_name": "Airhorner", "name": "Airhorner", "start_url":

    "/", "display": "standalone", "background_color": "#2196F3", "theme_color": "#2196F3", "icons": [{ "src": "icons/icon-192.png", "sizes": "192x192", "type": "image/png" }], "orientation": "portrait" } JSON Manifest Installability
  17. You are offline. To continue searching please check your wifi

    and mobile data are turned on. Indicative Example SW Local If stored locally or get from internet Web Server Installability
  18. self.addEventListener('push', function(event) { var title = 'New message from Paul';

    var body = 'What\'s happening today?'; var icon = '/images/paul.png'; var tag = 'simple-push-demo-notification-tag'; var data = { url: 'https://paul.kinlan.me' }; event.waitUntil( self.registration.showNotification(title, { body: body, icon: icon, tag: tag, data: data }) ); }); Engagement
  19. self.addEventListener('push', function(event) { var title = 'Yay a message.'; var

    body = 'We have received a push message.'; var icon = '/images/icon-192x192.png'; var tag = 'simple-push-demo-notification-tag'; var data = { url: 'https://paul.kinlan.me' }; Cache.add( url ); event.waitUntil( self.registration.showNotification(title, { body: body, icon: icon, tag: tag, data: data }) ); }); Engagement
  20. What would first render look like • No Web Font’s

    • No Images inline • No plugins • Just the CSS for the page
  21. Reduce Requests DNS Lookup Initial Conn SSL Negotiation Socket set-up

    Time to first byte (HTTP Request) Data delivery . . .
  22. Remove Redirects no more www.site.com -> m.site.com DNS Lookup Initial

    Conn SSL Negotiation Socket set-up Time to first byte (HTTP Request) Data delivery . . .
  23. Stop using 3rd party plugins window.addEventListener("load", function() { var iframes

    = document.getElementsByTagName("iframe"); for(var i = 0; i < iframes.length; i++) { var ifr = iframes[i]; if(ifr.hasAttribute("data-src")) { var src = ifr.getAttribute("data-src"); ifr.setAttribute("src", src); } } });
  24. Camera exp.bartekdrozdz.com/app/webfilter/ navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia ||

    navigator.msGetUserMedia; var video = document.querySelector('video'); if (navigator.getUserMedia) { navigator.getUserMedia({ video: true }, function(stream) { video.src = window.URL.createObjectURL(stream); } , errorCallback); } Capabilities
  25. Microphone voice-memos.appspot.com/ navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia ||

    navigator.msGetUserMedia; var video = document.querySelector('video'); if (navigator.getUserMedia) { navigator.getUserMedia({ audio: true }, function(stream) { audio.src = window.URL.createObjectURL(stream); } , errorCallback); } Capabilities
  26. Battery Status var batterySuccess = function(battery) { updateState(battery); // Monitor

    further updates battery.addEventListener("levelchange", function() { /* battery.level changed */ }); battery.addEventListener("chargingchange", function() { /* battery.charging changed */ }); battery.addEventListener("dischargingtimechange", function() { }); battery.addEventListener("chargingtimechange", function() { }); }; navigator.getBattery().then(batterySuccess); Capabilities
  27. Bluetooth navigator.bluetooth.requestDevice( { filters: [{ services: ['battery_service'] }] }) .then(device

    => { // Human-readable name of the device. console.log(device.name); // Indicates whether or not the device is paired with the system console.log(device.paired); // Filtered UUIDs of GATT services the website origin has access console.log(device.uuids); // Attempts to connect to remote GATT Server. return device.connectGATT(); }) Capabilities
  28. Net Info function changeHandler(e) { // Handle change to connection

    here. connEl.innerText = navigator.connection.type; speed = navigator.connection.downlinkMax; } navigator.connection.addEventListener( 'typechange', changeHandler); Capabilities
  29. Periodic Background Sync self.addEventListener('periodicsync', function(e) { e.waitUntil(checkforNewsArticle()); }); navigator.serviceWorker.ready.then(function(reg) {

    reg.periodicSync.register({ minPeriod: 12 * 60 * 60 * 1000,// 12 hours powerState: 'avoid-draining', // default: 'auto' networkState: 'avoid-cellular' // default: 'online' }).then(function(periodicSyncReg) { }) }); Service Worker Web Page