{"id":8163,"date":"2015-10-13T18:05:48","date_gmt":"2015-10-13T17:05:48","guid":{"rendered":"http:\/\/intercom.com\/blog\/?p=8163"},"modified":"2020-07-30T13:02:18","modified_gmt":"2020-07-30T12:02:18","slug":"why-we-built-our-message-editor-twice","status":"publish","type":"post","link":"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/","title":{"rendered":"Why we built our message editor twice"},"content":{"rendered":"<p class=\"opening_paragraph\">Building a sound, intuitive message editor for use everywhere in Intercom proved to be a much more challenging, time-consuming, and expensive task than we ever imagined.<\/p>\n<p>I explained how we overcame those hurdles and the importance of this investment\u00a0at a recent Intercom event, <em>On Product<\/em>. What follows is an edited transcript of my talk, along with a handful of relevant presentation slides.<\/p>\n<hr \/>\n<p><img decoding=\"async\" src=\"https:\/\/intercom.com\/blog\/wp-content\/uploads\/2015\/10\/1_Old-Messaging1.png\" alt=\"\" \/><\/p>\n<p>Up until mid-2014, Intercom used a simple text area to create new messages. But this text area was just that, for text only \u2013 no formatting, no images, and no rich media. We supported a mixture of markdown and HTML to get around this, but there were problems: it was tricky to compose, you needed to be somewhat technical, and it was very easy to make mistakes. It was also difficult to render consistently on all devices. Mobile applications, for example, need a WebView to render HTML.<\/p>\n<h2 id=\"we-can-build-it-better\">We can build it better<\/h2>\n<p>Around this time, we kicked off what we thought would be a small project, to build a better editor. To start, we defined a few guiding principles:<\/p>\n<ol>\n<li>Everyone should be able to create beautiful messages.<\/li>\n<li>Messages should be composed of simple constructs; constraining options would help users craft effective and consistent messages.<\/li>\n<li>Messages should look great on all platforms, so no HTML.<\/li>\n<\/ol>\n<p>We then came up with a simple data format we call \u201cBlocks\u201d. These have a flat structure and support a limited set of types, including headers, paragraphs, images, buttons, and videos.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/intercom.com\/blog\/wp-content\/uploads\/2015\/10\/2_JSON.png\" alt=\"\" \/><\/p>\n<p>Above is a JSON representation of those Blocks. We would use this format for both database storage and client application APIs.<\/p>\n<p>Our initial prototype used ContentEditable as the input surface. This is very straightforward; you add the property tag to an HTML element and it gains super powers. You can paste into it, and it supports lists, along with bold and italic formatting. You also get undo\/redo support and keyboard shortcuts.<\/p>\n<p>It does, however, produce HTML. But, we\u2019d be fine as long as we could convert that HTML into Blocks format \u2013 or so we thought. We kicked off a six-week project to build this new editor but soon realized there are a great many quirks with ContentEditable. For example, when a user presses a return key in an empty ContentEditable element:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/intercom.com\/blog\/wp-content\/uploads\/2015\/10\/4_Content-Editable-HTML.png\" alt=\"\" \/><\/p>\n<p>With Firefox you get a &lt;br&gt;\u00a0tag. IE gives you two paragraph tags. With Chrome it\u2019s two &lt;div&gt; and two &lt;br&gt; tags. It turns out there are no real standards with ContentEditable. As we built our editor we discovered many more weird cases. We\u2019d find a quirk, create a workaround, and find another quirk. It was rinse and repeat.<\/p>\n<div>\n<p>This project turned out to be a lot more complex than we had first imagined. But after a while we felt what we&#8217;d built was sufficiently better than our previous text area.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/intercom.com\/blog\/wp-content\/uploads\/2015\/10\/5_BETA-Messaging.png\" alt=\"\" \/><\/p>\n<p>There was a beta program, and some more bugs came in; we fixed them, all quite normal. Nothing seemed too difficult, and after a while we released it to everyone.<\/p>\n<h2 id=\"live-complications\">Live complications<\/h2>\n<p>Suddenly the issues came flooding in. We had 60 new issues in the first week \u2013 many more problems than we had known about. We closed 30 of those issues during that first week and another 50 came in. A common one: ContentEditable would get into an unexpected state. We\u2019d end up with JavaScript exceptions or do a bad job of converting the HTML to a valid block structure.<\/p>\n<p>We had run lots of trials, but our editor&#8217;s architecture made it difficult to test what we now discovered were its most brittle parts. This was a very bad situation, but we couldn\u2019t go back. Our customers had used this editor to create content and messages that we couldn&#8217;t convert back to the old format.<\/p>\n<p>We didn\u2019t think we could fix these bugs and build upon our current editor. A new approach was necessary, one that avoided the complexity of ContentEditable. If we wanted to take full control of the editing experience, we needed to build a Blocks editor and not a HTML editor.<\/p>\n<h2 id=\"building-the-bom\">Building the BOM<\/h2>\n<p>We sketched out a new architecture we called the Block Object Model (BOM).<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/intercom.com\/blog\/wp-content\/uploads\/2015\/10\/6_Block-Object-Model.png\" alt=\"\" \/><\/p>\n<p>We would intercept all key user actions such as backspace, return, and paste, and run these against our BOM. The BOM would become the canonical representation of the message being edited, and we would be in complete control of all rules for content manipulation. This was going to be a massive project and would take many months to build.<\/p>\n<h2 id=\"the-cupcake-principle\">The cupcake principle<\/h2>\n<p>At Intercom we ship fast and iterate based on feedback. For new projects, we usually apply <a href=\"https:\/\/www.intercom.com\/blog\/start-with-a-cupcake\/\" target=\"_blank\" rel=\"noopener noreferrer\">the cupcake principle<\/a>: the first time you bake a cake it should be a cupcake not a wedding cake. If you make mistakes, they&#8217;re not so costly; you learn from them and make better cakes.<\/p>\n<p>But we knew exactly what we needed to build. We couldn\u2019t ship half an editor, so we accepted the mammoth project. After six months of hard work by a lot of engineers, we shipped it, and it\u2019s now used everywhere in Intercom.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/intercom.com\/blog\/wp-content\/uploads\/2015\/10\/7_New-Messaging.png\" alt=\"\" \/><\/p>\n<p>This simple editor enables lists, and formatting such as bold, italic, and links. The auto message editor enables headings, data attributes, and videos. Our custom undo\/redo stack is unremarkable \u2013 meaning we did a good job diligently recreating the native behavior.<\/p>\n<p>We can paste images and insert other block types such as buttons, which have nice live updating editors. Messages can take a number of forms. We can also send as email and use predefined or custom templates.<\/p>\n<p>The shared inbox enables our customers to manage a large number of conversations with customers. The composer supports images, emoji, and stickers. Private notes can contain mentions through a simple shortcut and typeahead. There are also shortcuts for inserting saved replies.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/intercom.com\/blog\/wp-content\/uploads\/2015\/10\/8_Shared-Inbox.png\" alt=\"\" \/><\/p>\n<p>To guarantee the ongoing quality of the composer we built up a suite of more than\u00a01,000 test cases using a simple DSL.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/intercom.com\/blog\/wp-content\/uploads\/2015\/10\/9_Simple-DSL.png\" alt=\"\" \/><\/p>\n<h2 id=\"applying-hindsight-to-the-future\">Applying hindsight to the future<\/h2>\n<p>Looking back at these two projects, a couple of things become clear.\u00a0First, we completely underestimated the difficulty in building a solid message editor, so much so that had we known how challenging it was we may not have even attempted it. But as we built the second version, we realized how important this component is to our product.<\/p>\n<p>Whatever Intercom becomes in 10 years time, messaging will still be at its heart. Although the initial project was a failure, we learned a huge amount about how a solid editor should be built. That first failure allowed us to nail it the second time, and we now have a great foundation to build upon.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Building a sound, intuitive message editor for use everywhere in Intercom proved to be a much more challenging, time-consuming, and expensive task than we ever imagined. I explained how we overcame those hurdles and the importance&hellip;<\/p>\n","protected":false},"author":86,"featured_media":8188,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"category":[4],"tags":[124,200,161],"coauthors":[393],"class_list":["post-8163","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news","tag-email","tag-messaging","tag-product-development"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Why we built our message editor twice - The Intercom Blog<\/title>\n<meta name=\"description\" content=\"Building a message editor for use across all Intercom products proved to be more challenging and time-consuming than we ever imagined. So why did we do it?\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Why we built our message editor twice\" \/>\n<meta property=\"og:description\" content=\"Building a message editor for use across all Intercom products proved to be more challenging and time-consuming than we ever imagined. So why did we do it?\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/\" \/>\n<meta property=\"og:site_name\" content=\"The Intercom Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/intercominc\" \/>\n<meta property=\"article:published_time\" content=\"2015-10-13T17:05:48+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-07-30T12:02:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2015\/10\/Gavin-Joyce-Hero_Related.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1248\" \/>\n\t<meta property=\"og:image:height\" content=\"591\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Gavin Joyce\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@gavinjoyce\" \/>\n<meta name=\"twitter:site\" content=\"@intercom\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Gavin Joyce\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/why-we-built-our-message-editor-twice\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/why-we-built-our-message-editor-twice\\\/\"},\"author\":{\"name\":\"Gavin Joyce\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#\\\/schema\\\/person\\\/79e83ec7372bf3c375bb7d365669be88\"},\"headline\":\"Why we built our message editor twice\",\"datePublished\":\"2015-10-13T17:05:48+00:00\",\"dateModified\":\"2020-07-30T12:02:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/why-we-built-our-message-editor-twice\\\/\"},\"wordCount\":1126,\"publisher\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/why-we-built-our-message-editor-twice\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/10\\\/Gavin-Joyce-Hero_Related.png\",\"keywords\":[\"email\",\"messaging\",\"product development\"],\"articleSection\":[\"News &amp; Updates\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/why-we-built-our-message-editor-twice\\\/\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/why-we-built-our-message-editor-twice\\\/\",\"name\":\"Why we built our message editor twice - The Intercom Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/why-we-built-our-message-editor-twice\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/why-we-built-our-message-editor-twice\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/10\\\/Gavin-Joyce-Hero_Related.png\",\"datePublished\":\"2015-10-13T17:05:48+00:00\",\"dateModified\":\"2020-07-30T12:02:18+00:00\",\"description\":\"Building a message editor for use across all Intercom products proved to be more challenging and time-consuming than we ever imagined. So why did we do it?\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.intercom.com\\\/blog\\\/why-we-built-our-message-editor-twice\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/why-we-built-our-message-editor-twice\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/10\\\/Gavin-Joyce-Hero_Related.png\",\"contentUrl\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/10\\\/Gavin-Joyce-Hero_Related.png\",\"width\":1248,\"height\":591},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/\",\"name\":\"The Intercom Blog\",\"description\":\"Articles and Podcasts on Customer Service, AI and Automation, Product, and more\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#organization\",\"name\":\"The Intercom Blog\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/08\\\/Intercom-logo-sq-black-trans.png\",\"contentUrl\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/08\\\/Intercom-logo-sq-black-trans.png\",\"width\":1000,\"height\":1000,\"caption\":\"The Intercom Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/intercominc\",\"https:\\\/\\\/x.com\\\/intercom\",\"https:\\\/\\\/www.instagram.com\\\/intercom\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/2491343\",\"https:\\\/\\\/www.pinterest.ie\\\/intercom\\\/\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCJG0MvLP03kyzzAkD-w98aQ\",\"https:\\\/\\\/en.wikipedia.org\\\/wiki\\\/Intercom_(company)\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#\\\/schema\\\/person\\\/79e83ec7372bf3c375bb7d365669be88\",\"name\":\"Gavin Joyce\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f7233f3a50606e1d6bd901950963db023819a6c68763714c453992ac0505b5d4?s=96&d=mm&r=pgee57bc9b05233d68817bc62e7887cf74\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f7233f3a50606e1d6bd901950963db023819a6c68763714c453992ac0505b5d4?s=96&d=mm&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f7233f3a50606e1d6bd901950963db023819a6c68763714c453992ac0505b5d4?s=96&d=mm&r=pg\",\"caption\":\"Gavin Joyce\"},\"description\":\"Ruby &amp; Ember.js | @intercom | @restpack\",\"sameAs\":[\"http:\\\/\\\/www.gavinjoyce.com\\\/\",\"https:\\\/\\\/x.com\\\/gavinjoyce\"],\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/author\\\/gavinjoyce\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Why we built our message editor twice - The Intercom Blog","description":"Building a message editor for use across all Intercom products proved to be more challenging and time-consuming than we ever imagined. So why did we do it?","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/","og_locale":"en_US","og_type":"article","og_title":"Why we built our message editor twice","og_description":"Building a message editor for use across all Intercom products proved to be more challenging and time-consuming than we ever imagined. So why did we do it?","og_url":"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/","og_site_name":"The Intercom Blog","article_publisher":"https:\/\/www.facebook.com\/intercominc","article_published_time":"2015-10-13T17:05:48+00:00","article_modified_time":"2020-07-30T12:02:18+00:00","og_image":[{"width":1248,"height":591,"url":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2015\/10\/Gavin-Joyce-Hero_Related.png","type":"image\/png"}],"author":"Gavin Joyce","twitter_card":"summary_large_image","twitter_creator":"@gavinjoyce","twitter_site":"@intercom","twitter_misc":{"Written by":"Gavin Joyce","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/#article","isPartOf":{"@id":"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/"},"author":{"name":"Gavin Joyce","@id":"https:\/\/www.intercom.com\/blog\/#\/schema\/person\/79e83ec7372bf3c375bb7d365669be88"},"headline":"Why we built our message editor twice","datePublished":"2015-10-13T17:05:48+00:00","dateModified":"2020-07-30T12:02:18+00:00","mainEntityOfPage":{"@id":"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/"},"wordCount":1126,"publisher":{"@id":"https:\/\/www.intercom.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/#primaryimage"},"thumbnailUrl":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2015\/10\/Gavin-Joyce-Hero_Related.png","keywords":["email","messaging","product development"],"articleSection":["News &amp; Updates"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/","url":"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/","name":"Why we built our message editor twice - The Intercom Blog","isPartOf":{"@id":"https:\/\/www.intercom.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/#primaryimage"},"image":{"@id":"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/#primaryimage"},"thumbnailUrl":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2015\/10\/Gavin-Joyce-Hero_Related.png","datePublished":"2015-10-13T17:05:48+00:00","dateModified":"2020-07-30T12:02:18+00:00","description":"Building a message editor for use across all Intercom products proved to be more challenging and time-consuming than we ever imagined. So why did we do it?","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.intercom.com\/blog\/why-we-built-our-message-editor-twice\/#primaryimage","url":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2015\/10\/Gavin-Joyce-Hero_Related.png","contentUrl":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2015\/10\/Gavin-Joyce-Hero_Related.png","width":1248,"height":591},{"@type":"WebSite","@id":"https:\/\/www.intercom.com\/blog\/#website","url":"https:\/\/www.intercom.com\/blog\/","name":"The Intercom Blog","description":"Articles and Podcasts on Customer Service, AI and Automation, Product, and more","publisher":{"@id":"https:\/\/www.intercom.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.intercom.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.intercom.com\/blog\/#organization","name":"The Intercom Blog","url":"https:\/\/www.intercom.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.intercom.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2019\/08\/Intercom-logo-sq-black-trans.png","contentUrl":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2019\/08\/Intercom-logo-sq-black-trans.png","width":1000,"height":1000,"caption":"The Intercom Blog"},"image":{"@id":"https:\/\/www.intercom.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/intercominc","https:\/\/x.com\/intercom","https:\/\/www.instagram.com\/intercom\/","https:\/\/www.linkedin.com\/company\/2491343","https:\/\/www.pinterest.ie\/intercom\/","https:\/\/www.youtube.com\/channel\/UCJG0MvLP03kyzzAkD-w98aQ","https:\/\/en.wikipedia.org\/wiki\/Intercom_(company)"]},{"@type":"Person","@id":"https:\/\/www.intercom.com\/blog\/#\/schema\/person\/79e83ec7372bf3c375bb7d365669be88","name":"Gavin Joyce","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f7233f3a50606e1d6bd901950963db023819a6c68763714c453992ac0505b5d4?s=96&d=mm&r=pgee57bc9b05233d68817bc62e7887cf74","url":"https:\/\/secure.gravatar.com\/avatar\/f7233f3a50606e1d6bd901950963db023819a6c68763714c453992ac0505b5d4?s=96&d=mm&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f7233f3a50606e1d6bd901950963db023819a6c68763714c453992ac0505b5d4?s=96&d=mm&r=pg","caption":"Gavin Joyce"},"description":"Ruby &amp; Ember.js | @intercom | @restpack","sameAs":["http:\/\/www.gavinjoyce.com\/","https:\/\/x.com\/gavinjoyce"],"url":"https:\/\/www.intercom.com\/blog\/author\/gavinjoyce\/"}]}},"jetpack_featured_media_url":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2015\/10\/Gavin-Joyce-Hero_Related.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/posts\/8163","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/users\/86"}],"replies":[{"embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/comments?post=8163"}],"version-history":[{"count":0,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/posts\/8163\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/media\/8188"}],"wp:attachment":[{"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/media?parent=8163"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/category?post=8163"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/tags?post=8163"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/coauthors?post=8163"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}