{"action":"created","comment":{"url":"https://api.github.com/repos/google/WebFundamentals/pulls/comments/68780939","id":68780939,"diff_hunk":"@@ -0,0 +1,448 @@\n+---  \n+layout: shared/narrow\n+title: \"Handling messages\"\n+description: \"\"\n+published_on: 2016-07-01\n+updated_on: 2016-07-01\n+order: 40\n+translation_priority: 0\n+authors:\n+  - josephmedley\n+---\n+\n+<p class=\"intro\"> Way back at the [beginning of this section](index#anatomy), we\n+showed a notification that looks like this and the code that goes with it.<br/><br/>\n+\n+<img src=\"images/joe-asked.png\" width=\"300\" height=\"109\" /><br/><br/>\n+\n+While we showed you a little bit about how this is coded, we really didn't give\n+you enough information for it to be useful. That's what this section is about.\n+</p>\n+\n+{% include shared/toc.liquid %}\n+\n+## More notification anatomy {#more-anatomy}\n+\n+When a notification is received from the server, it's intercepted by a service\n+worker using the push event. It's basic structure is this.\n+\n+{% highlight javascript %}\n+self.addEventListener('push', event => {\n+  event.waitUntil(\n+    // Process the event and display a notification.\n+  );\n+});\n+{% endhighlight %}\n+\n+Somewhere inside `waitUntil()`, we're going to call `showNotification()` on a\n+service worker registration object.\n+\n+{% highlight javascript %}\n+self.registration.showNotification(title, {\n+    body: 'Are you free tonight?',\n+    icon: 'images/joe.png',\n+    vibrate: [200, 100, 200, 100, 200, 100, 400],\n+    tag: 'request',\n+    actions: [\n+      { action: 'yes', title: 'Yes!', icon: 'images/thumb-up.png' },\n+      { action: 'no', title: 'No', icon: 'images/thumb-down.png' }\n+    ]\n+  })\n+{% endhighlight %}\n+\n+Technically, the only required parameter for `showNotification()` is the title.\n+Practically speaking, you should include a body and an icon.\n+\n+Finally, we'll process the user's response using the notificationclick and\n+notificationclose methods.\n+\n+{% highlight javascript %}\n+self.addEventListener('notificationclick', event => {  \n+  // Do something with the event  \n+  event.notification.close();  \n+});\n+\n+self.addEventListener('notificationclose', event => {  \n+  // Do something with the event  \n+});\n+{% endhighlight %}\n+\n+Everything else is just an elaboration of these basic ideas.\n+\n+## Preparing message content {#preparing-messages}\n+\n+As we said earlier, your server sends two kinds of messages. \n+\n+* Messages with a data payload.\n+* Messages without a data payload, often called a tickle.\n+\n+Your push handler needs to account for both. For messages without a payload you \n+want to provide a good user experience by getting the data before you tell the \n+user it's available.\n+\n+Let's start with our basic push event handler with a call to\n+`event.waitUntil()`.  This method can only take a Promise or something that\n+resolves to a promise.\n+\n+{% highlight javascript %}\n+self.addEventListener('push', event => {\n+  event.waitUntil(() => {\n+    // Do something with the event.\n+  });\n+});\n+{% endhighlight %}\n+\n+Next, if you find data in the event object, get it.\n+\n+{% highlight javascript %}\n+self.addEventListener('push', event => {\n+  event.waitUntil(() => {\n+    if (event.data) {\n+      return Promise.resolve(event.data);\n+    }\n+    // No data, so do something else.  \n+  });  \n+});\n+{% endhighlight %}\n+\n+If there's no data in the object, call `fetch()` to get it from the server. \n+Otherwise, just return the data.\n+\n+{% highlight javascript %}\n+self.addEventListener('push', event => {\n+  event.waitUntil(() => {\n+    if (event.data) {\n+      return Promise.resolve(event.data);\n+    }\n+    return fetch('some/data/endpoint.json')\n+      .then(response => response.json());\n+  });\n+});\n+{% endhighlight %}\n+\n+In both cases we end up with a JSON object. Now it's time to show a\n+notification to the user.\n+\n+{% highlight javascript %}\n+self.addEventListener('push', event => {\n+  event.waitUntil(() => {\n+    if (event.data) {\n+      return Promise.resolve(event.data);\n+    }\n+    return fetch('some/data/endpoint.json')\n+        .then(response => response.json());\n+    })\n+    .then(data => {\n+      return self.registration.showNotification(data.title, {\n+        body: data.body,\n+        icon: (data.icon ? data.icon : '/images/icon-192x192.png'),\n+        vibrate: [200, 100, 200, 100, 200, 100, 400],\n+        tag: data.tag\n+       })\n+    }))\n+});\n+{% endhighlight %}\n+\n+## Combine similar notifications {#combine-similar-notes}\n+\n+Sometimes it's useful to combine multiple notifications into a single one. For\n+example, a social networking app might want to avoid messaging users for every\n+post from a particular person, and instead combine them.\n+\n+<img src=\"images/combined-notes-mobile.png\" width=\"296\" height=\"526\">\n+\n+Combining similar notifications comes down to three things.\n+\n+* A call to `getNotifications()`.\n+* reusing an existing `tag` value.\n+* Setting the `retnotify` flag in the call to `showNotification()`.\n+\n+Let's look at an example that shows all three.\n+\n+The following examples, we're going to assume that you've already received or\n+retrieved message data  as described in the last section. Now let's look at what\n+to do with it. Start with a basic push event handler.\n+\n+{% highlight javascript %}\n+self.addEventListener('push', function(event) {\n+  event.waitUntil(\n+    // Get the message data somehow and return a Promise.\n+  )\n+  .then(data => {\n+    // Do something with the data.\n+  })\n+});\n+{% endhighlight %}\n+\n+Check for notifications that match `data.tag` with a call to `getNotifications()`.\n+\n+{% highlight javascript %}\n+self.addEventListener('push', function(event) {\n+  event.waitUntil(\n+    // Get the message data somehow and return a Promise.\n+  )\n+  .then(data => {\n+    return self.registration.getNotifications({tag: data.tag});\n+  })\n+  .then(notifications => {\n+    //Do something with the notifications.\n+  })\n+});\n+{% endhighlight %}\n+\n+In other examples, we've instantiated our notification options right in the call \n+to `showNotification()`. For this scenario, the options object needs to change \n+based on the results of `getNotifications()`.  So instantiate a notification \n+options object. \n+\n+Notice that we've also attached the notification data to the notification\n+options. We're doing this to ensure that it's available to `notificationclick`,\n+which we'll look at in a later section. To tell the browser we're combining\n+notifications, we need to not just reuse the tag (line 6), we also need to set renotify","path":"src/content/en/fundamentals/engage-and-retain/push-notifications/handling-messages.markdown","position":201,"original_position":201,"commit_id":"4108afa3eb0f2ec1045ff22a717a4879d1fbb0a0","original_commit_id":"4108afa3eb0f2ec1045ff22a717a4879d1fbb0a0","user":{"login":"petele","id":718038,"avatar_url":"https://avatars.githubusercontent.com/u/718038?v=3","gravatar_id":"","url":"https://api.github.com/users/petele","html_url":"https://github.com/petele","followers_url":"https://api.github.com/users/petele/followers","following_url":"https://api.github.com/users/petele/following{/other_user}","gists_url":"https://api.github.com/users/petele/gists{/gist_id}","starred_url":"https://api.github.com/users/petele/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/petele/subscriptions","organizations_url":"https://api.github.com/users/petele/orgs","repos_url":"https://api.github.com/users/petele/repos","events_url":"https://api.github.com/users/petele/events{/privacy}","received_events_url":"https://api.github.com/users/petele/received_events","type":"User","site_admin":false},"body":"tag should be back ticked.","created_at":"2016-06-28T15:31:40Z","updated_at":"2016-06-28T15:31:40Z","html_url":"https://github.com/google/WebFundamentals/pull/3031#discussion_r68780939","pull_request_url":"https://api.github.com/repos/google/WebFundamentals/pulls/3031","_links":{"self":{"href":"https://api.github.com/repos/google/WebFundamentals/pulls/comments/68780939"},"html":{"href":"https://github.com/google/WebFundamentals/pull/3031#discussion_r68780939"},"pull_request":{"href":"https://api.github.com/repos/google/WebFundamentals/pulls/3031"}}},"pull_request":{"url":"https://api.github.com/repos/google/WebFundamentals/pulls/3031","id":75390693,"html_url":"https://github.com/google/WebFundamentals/pull/3031","diff_url":"https://github.com/google/WebFundamentals/pull/3031.diff","patch_url":"https://github.com/google/WebFundamentals/pull/3031.patch","issue_url":"https://api.github.com/repos/google/WebFundamentals/issues/3031","number":3031,"state":"open","locked":false,"title":"New Push Notifications Section for Engage and Retain","user":{"login":"jpmedley","id":8204171,"avatar_url":"https://avatars.githubusercontent.com/u/8204171?v=3","gravatar_id":"","url":"https://api.github.com/users/jpmedley","html_url":"https://github.com/jpmedley","followers_url":"https://api.github.com/users/jpmedley/followers","following_url":"https://api.github.com/users/jpmedley/following{/other_user}","gists_url":"https://api.github.com/users/jpmedley/gists{/gist_id}","starred_url":"https://api.github.com/users/jpmedley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpmedley/subscriptions","organizations_url":"https://api.github.com/users/jpmedley/orgs","repos_url":"https://api.github.com/users/jpmedley/repos","events_url":"https://api.github.com/users/jpmedley/events{/privacy}","received_events_url":"https://api.github.com/users/jpmedley/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-06-27T22:28:57Z","updated_at":"2016-06-28T15:31:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0646ab7ae36647a2541e87819c0196bf7b340151","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/google/WebFundamentals/pulls/3031/commits","review_comments_url":"https://api.github.com/repos/google/WebFundamentals/pulls/3031/comments","review_comment_url":"https://api.github.com/repos/google/WebFundamentals/pulls/comments{/number}","comments_url":"https://api.github.com/repos/google/WebFundamentals/issues/3031/comments","statuses_url":"https://api.github.com/repos/google/WebFundamentals/statuses/4108afa3eb0f2ec1045ff22a717a4879d1fbb0a0","head":{"label":"jpmedley:enr","ref":"enr","sha":"4108afa3eb0f2ec1045ff22a717a4879d1fbb0a0","user":{"login":"jpmedley","id":8204171,"avatar_url":"https://avatars.githubusercontent.com/u/8204171?v=3","gravatar_id":"","url":"https://api.github.com/users/jpmedley","html_url":"https://github.com/jpmedley","followers_url":"https://api.github.com/users/jpmedley/followers","following_url":"https://api.github.com/users/jpmedley/following{/other_user}","gists_url":"https://api.github.com/users/jpmedley/gists{/gist_id}","starred_url":"https://api.github.com/users/jpmedley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpmedley/subscriptions","organizations_url":"https://api.github.com/users/jpmedley/orgs","repos_url":"https://api.github.com/users/jpmedley/repos","events_url":"https://api.github.com/users/jpmedley/events{/privacy}","received_events_url":"https://api.github.com/users/jpmedley/received_events","type":"User","site_admin":false},"repo":{"id":56626575,"name":"WebFundamentals","full_name":"jpmedley/WebFundamentals","owner":{"login":"jpmedley","id":8204171,"avatar_url":"https://avatars.githubusercontent.com/u/8204171?v=3","gravatar_id":"","url":"https://api.github.com/users/jpmedley","html_url":"https://github.com/jpmedley","followers_url":"https://api.github.com/users/jpmedley/followers","following_url":"https://api.github.com/users/jpmedley/following{/other_user}","gists_url":"https://api.github.com/users/jpmedley/gists{/gist_id}","starred_url":"https://api.github.com/users/jpmedley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpmedley/subscriptions","organizations_url":"https://api.github.com/users/jpmedley/orgs","repos_url":"https://api.github.com/users/jpmedley/repos","events_url":"https://api.github.com/users/jpmedley/events{/privacy}","received_events_url":"https://api.github.com/users/jpmedley/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jpmedley/WebFundamentals","description":"Best practices for modern web development","fork":true,"url":"https://api.github.com/repos/jpmedley/WebFundamentals","forks_url":"https://api.github.com/repos/jpmedley/WebFundamentals/forks","keys_url":"https://api.github.com/repos/jpmedley/WebFundamentals/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jpmedley/WebFundamentals/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jpmedley/WebFundamentals/teams","hooks_url":"https://api.github.com/repos/jpmedley/WebFundamentals/hooks","issue_events_url":"https://api.github.com/repos/jpmedley/WebFundamentals/issues/events{/number}","events_url":"https://api.github.com/repos/jpmedley/WebFundamentals/events","assignees_url":"https://api.github.com/repos/jpmedley/WebFundamentals/assignees{/user}","branches_url":"https://api.github.com/repos/jpmedley/WebFundamentals/branches{/branch}","tags_url":"https://api.github.com/repos/jpmedley/WebFundamentals/tags","blobs_url":"https://api.github.com/repos/jpmedley/WebFundamentals/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jpmedley/WebFundamentals/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jpmedley/WebFundamentals/git/refs{/sha}","trees_url":"https://api.github.com/repos/jpmedley/WebFundamentals/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jpmedley/WebFundamentals/statuses/{sha}","languages_url":"https://api.github.com/repos/jpmedley/WebFundamentals/languages","stargazers_url":"https://api.github.com/repos/jpmedley/WebFundamentals/stargazers","contributors_url":"https://api.github.com/repos/jpmedley/WebFundamentals/contributors","subscribers_url":"https://api.github.com/repos/jpmedley/WebFundamentals/subscribers","subscription_url":"https://api.github.com/repos/jpmedley/WebFundamentals/subscription","commits_url":"https://api.github.com/repos/jpmedley/WebFundamentals/commits{/sha}","git_commits_url":"https://api.github.com/repos/jpmedley/WebFundamentals/git/commits{/sha}","comments_url":"https://api.github.com/repos/jpmedley/WebFundamentals/comments{/number}","issue_comment_url":"https://api.github.com/repos/jpmedley/WebFundamentals/issues/comments{/number}","contents_url":"https://api.github.com/repos/jpmedley/WebFundamentals/contents/{+path}","compare_url":"https://api.github.com/repos/jpmedley/WebFundamentals/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jpmedley/WebFundamentals/merges","archive_url":"https://api.github.com/repos/jpmedley/WebFundamentals/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jpmedley/WebFundamentals/downloads","issues_url":"https://api.github.com/repos/jpmedley/WebFundamentals/issues{/number}","pulls_url":"https://api.github.com/repos/jpmedley/WebFundamentals/pulls{/number}","milestones_url":"https://api.github.com/repos/jpmedley/WebFundamentals/milestones{/number}","notifications_url":"https://api.github.com/repos/jpmedley/WebFundamentals/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jpmedley/WebFundamentals/labels{/name}","releases_url":"https://api.github.com/repos/jpmedley/WebFundamentals/releases{/id}","deployments_url":"https://api.github.com/repos/jpmedley/WebFundamentals/deployments","created_at":"2016-04-19T19:41:45Z","updated_at":"2016-04-19T19:41:55Z","pushed_at":"2016-06-27T22:28:16Z","git_url":"git://github.com/jpmedley/WebFundamentals.git","ssh_url":"git@github.com:jpmedley/WebFundamentals.git","clone_url":"https://github.com/jpmedley/WebFundamentals.git","svn_url":"https://github.com/jpmedley/WebFundamentals","homepage":"https://developers.google.com/web/fundamentals","size":1046592,"stargazers_count":0,"watchers_count":0,"language":"HTML","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"google:master","ref":"master","sha":"968a4a104577f8f02088920960a7de26289c646e","user":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"repo":{"id":19249835,"name":"WebFundamentals","full_name":"google/WebFundamentals","owner":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/google/WebFundamentals","description":"Best practices for modern web development","fork":false,"url":"https://api.github.com/repos/google/WebFundamentals","forks_url":"https://api.github.com/repos/google/WebFundamentals/forks","keys_url":"https://api.github.com/repos/google/WebFundamentals/keys{/key_id}","collaborators_url":"https://api.github.com/repos/google/WebFundamentals/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/google/WebFundamentals/teams","hooks_url":"https://api.github.com/repos/google/WebFundamentals/hooks","issue_events_url":"https://api.github.com/repos/google/WebFundamentals/issues/events{/number}","events_url":"https://api.github.com/repos/google/WebFundamentals/events","assignees_url":"https://api.github.com/repos/google/WebFundamentals/assignees{/user}","branches_url":"https://api.github.com/repos/google/WebFundamentals/branches{/branch}","tags_url":"https://api.github.com/repos/google/WebFundamentals/tags","blobs_url":"https://api.github.com/repos/google/WebFundamentals/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/google/WebFundamentals/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/google/WebFundamentals/git/refs{/sha}","trees_url":"https://api.github.com/repos/google/WebFundamentals/git/trees{/sha}","statuses_url":"https://api.github.com/repos/google/WebFundamentals/statuses/{sha}","languages_url":"https://api.github.com/repos/google/WebFundamentals/languages","stargazers_url":"https://api.github.com/repos/google/WebFundamentals/stargazers","contributors_url":"https://api.github.com/repos/google/WebFundamentals/contributors","subscribers_url":"https://api.github.com/repos/google/WebFundamentals/subscribers","subscription_url":"https://api.github.com/repos/google/WebFundamentals/subscription","commits_url":"https://api.github.com/repos/google/WebFundamentals/commits{/sha}","git_commits_url":"https://api.github.com/repos/google/WebFundamentals/git/commits{/sha}","comments_url":"https://api.github.com/repos/google/WebFundamentals/comments{/number}","issue_comment_url":"https://api.github.com/repos/google/WebFundamentals/issues/comments{/number}","contents_url":"https://api.github.com/repos/google/WebFundamentals/contents/{+path}","compare_url":"https://api.github.com/repos/google/WebFundamentals/compare/{base}...{head}","merges_url":"https://api.github.com/repos/google/WebFundamentals/merges","archive_url":"https://api.github.com/repos/google/WebFundamentals/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/google/WebFundamentals/downloads","issues_url":"https://api.github.com/repos/google/WebFundamentals/issues{/number}","pulls_url":"https://api.github.com/repos/google/WebFundamentals/pulls{/number}","milestones_url":"https://api.github.com/repos/google/WebFundamentals/milestones{/number}","notifications_url":"https://api.github.com/repos/google/WebFundamentals/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/google/WebFundamentals/labels{/name}","releases_url":"https://api.github.com/repos/google/WebFundamentals/releases{/id}","deployments_url":"https://api.github.com/repos/google/WebFundamentals/deployments","created_at":"2014-04-28T18:45:45Z","updated_at":"2016-06-28T13:42:15Z","pushed_at":"2016-06-28T15:13:28Z","git_url":"git://github.com/google/WebFundamentals.git","ssh_url":"git@github.com:google/WebFundamentals.git","clone_url":"https://github.com/google/WebFundamentals.git","svn_url":"https://github.com/google/WebFundamentals","homepage":"https://developers.google.com/web/fundamentals","size":1080064,"stargazers_count":5988,"watchers_count":5988,"language":"HTML","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1097,"mirror_url":null,"open_issues_count":324,"forks":1097,"open_issues":324,"watchers":5988,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/google/WebFundamentals/pulls/3031"},"html":{"href":"https://github.com/google/WebFundamentals/pull/3031"},"issue":{"href":"https://api.github.com/repos/google/WebFundamentals/issues/3031"},"comments":{"href":"https://api.github.com/repos/google/WebFundamentals/issues/3031/comments"},"review_comments":{"href":"https://api.github.com/repos/google/WebFundamentals/pulls/3031/comments"},"review_comment":{"href":"https://api.github.com/repos/google/WebFundamentals/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/google/WebFundamentals/pulls/3031/commits"},"statuses":{"href":"https://api.github.com/repos/google/WebFundamentals/statuses/4108afa3eb0f2ec1045ff22a717a4879d1fbb0a0"}}}}
{"actor":{"display_login":"petele"}}