{"id":5269,"date":"2018-08-11T19:17:23","date_gmt":"2018-08-11T17:17:23","guid":{"rendered":"https:\/\/pi3g.com\/?p=5269"},"modified":"2018-08-11T20:44:57","modified_gmt":"2018-08-11T18:44:57","slug":"algolia-and-using-instantsearch-js-from-your-script-for-shopify","status":"publish","type":"post","link":"https:\/\/pi3g.com\/de\/algolia-and-using-instantsearch-js-from-your-script-for-shopify\/","title":{"rendered":"Algolia und Verwendung von instantsearch.js aus Ihrem Skript f\u00fcr Shopify"},"content":{"rendered":"<p><em>\u201cGood artists copy, great artists steal.\u201d \u2013 Steve Jobs<\/em><\/p>\n<p>Inspired by <a href=\"https:\/\/www.pimoroni.com\">pimoroni.com<\/a> I wanted to implement a similar search on our webshop, <a href=\"https:\/\/buyzero.de\/\">buyzero.de<\/a> as well. buyzero.de is currently powered by Shopify.<\/p>\n<p>The search shows results as you type \u2013 in the main page, dynamically replacing the previosly displayed content. Very cool, very useful \u2013 and very, very fast (thanks to <a href=\"https:\/\/www.algolia.com\">Algolia<\/a>!)<\/p>\n<p>Since I\u2019ve struggled with the available documentation about Algolia, and their onboarding service was not very helpful, I\u2019ve had to figure things out on my own, and by extensive Googling.<\/p>\n<p>This is a summary of my experience implementing Algolia. I did it in a single day, in a single session of about 12 \u2013 14 hours of coding. <\/p>\n<h2>Suggested Preparation: injection of development code into your page<\/h2>\n<p>I suggest to use the Google Chrome extension <a href=\"https:\/\/tampermonkey.net\/documentation.php\">Tampermonkey<\/a> for injecting CSS and Javascript from your local harddrive while you develop. <\/p>\n<p>To do this, you have to enable file access for Tampermonkey. Open:<\/p>\n<p><a title=\"chrome:\/\/extensions\" href=\"chrome:\/\/extensions\">chrome:\/\/extensions<\/a><\/p>\n<p>Click on Details and switch \u201cAllow access to file URLs\u201d on<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2018\/08\/image-4.png\"><img loading=\"lazy\" decoding=\"async\" width=\"381\" height=\"163\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2018\/08\/image_thumb-4.png\" border=\"0\"><\/a><\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2018\/08\/image-5.png\"><img loading=\"lazy\" decoding=\"async\" width=\"638\" height=\"57\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2018\/08\/image_thumb-5.png\" border=\"0\"><\/a><\/p>\n<p><\/p>\n<p>Create the following new userscript in Tampermonkey:<\/p>\n<p><\/p>\n<p><pre>\/\/ ==UserScript==\n\/\/ @name         Algolia-Inject\n\/\/ @namespace    https:\/\/pi3g.com\/\n\/\/ @version      0.5\n\/\/ @description  inject local file to test Algolia!\n\/\/ @author       Maximilian Batz\n\/\/ @grant       GM_getResourceText\n\/\/ @grant       GM_addStyle\n\/\/ @noframes\n\/\/ @include      https:\/\/buyzero.de\/*\n\/\/ @resource     YOUR_CSS file:\/\/D:\\algolia_jr.css\n\/\/ @require      file:\/\/D:\\algolia_jr.js\n\n\/\/ ==\/UserScript==\n\nvar my_css = GM_getResourceText (\"YOUR_CSS\");\nGM_addStyle(my_css);\n<\/pre>\n<p><\/p>\n<p><strong>Explanation:<\/strong><\/p>\n<ul>\n<li>you have to grant getResourceText and addStyle to be able to access and inject the CSS file<\/li>\n<li>noframes for not executing a second time in the frames which Shopify apparently loads, and which also would match the domain<\/li>\n<li>include \u2013&gt; will match on buyzero.de. You might want to change that line <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" alt=\"Smile\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2018\/08\/wlEmoticon-smile.png\"><\/li>\n<li>resource used for importing CSS file. Provide the path \u2026 in Linux it might be <a href=\"file:\/\/\/home\/whatever\/whatever\">file:\/\/\/home\/whatever\/whatever<\/a> \u2013 notice the triple forward slash<\/li>\n<li>require \u2013 include your javascript file<\/li>\n<li>userscript: this is the userscript to add the CSS file<\/li>\n<\/ul>\n<p><\/p>\n<h2>Adding the Algolia Code<\/h2>\n<p>With the \u201chow to develop\u201d bit out of the way, <a href=\"http:\/\/pi3g.com\/misc\/algolia-sample.zip\">here\u2019s my code as sample code in a nice little ZIP file<\/a>. <\/p>\n<p>Please don\u2019t copy paste from this blog, as I\u2019m not sure, whether WordPress will destroy the code\u2019s formatting \u2026 use the .js in the ZIP file to copy from.<\/p>\n<p><\/p>\n<p>Please note that the Algolia dependencies \/ JavaScript files were already installed in our Shopify theme \u2013 by installing the Algolia Shopify plugin. Also our datastore was set up, etc. Algolia was (and still is) already serving search results in a drop down while you typed into the search box. <\/p>\n<p><\/p>\n<p>I\u2019ll walk you through the important parts of the code:<\/p>\n<p>we start aj_setup() once the document is ready, to inject our new search functionality.<\/p>\n<p>Please note that I use aj to prepend my functions &amp; id\u2019s for this script. You may use anything you like, it is not required by Algolia.<\/p>\n<p><\/p>\n<h3>The container<\/h3>\n<p>in aj_setup() I set up a new container for the search results to be put into (it would probably be better practice to include this directly in your theme file \u2013 for developing this was easier). <\/p>\n<p>this is the HTML part of the search <\/p>\n<p><\/p>\n<p>\n<pre>$(\".main-content\").before('&lt;div id=\"aj-search-container\" class=\"aj-main-content full-width\"&gt;&lt;div class=\"background\"&gt;&lt;div class=\"pattern\"&gt;&lt;div class=\"container\"&gt;&lt;div class=\"row\"&gt;&lt;div class=\"col-md-12\"&gt;&lt;div class=\"row\"&gt;&lt;div class=\"col-md-12 center-column content-without-background\"&gt;'+<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;DIV style='display:block;'&gt;\"+<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;H1&gt;Suchresultate f\u00fcr: &lt;span id='sc-query'&gt;&lt;\/span&gt;&lt;\/H1&gt;\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;DIV id='aj-right-container'&gt;\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;DIV id='aj-clear-all'&gt;&lt;\/DIV&gt;\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;DIV id='aj-facet-brand'&gt;&lt;\/DIV&gt;\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;DIV id='aj-facet-category'&gt;&lt;\/DIV&gt;\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;DIV id='aj-facet-price'&gt;&lt;\/DIV&gt;\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;\/DIV&gt;\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;DIV id='aj-left-container'&gt;\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;DIV id='aj-stats'&gt;&lt;\/DIV&gt;\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;DIV id='aj-search-results'&gt;&lt;\/DIV&gt;\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;DIV id='aj-search-pagination'&gt;&lt;\/DIV&gt;\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;\/DIV\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \"&lt;\/DIV&gt;\" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '&lt;\/div&gt;&lt;\/div&gt;&lt;\/div&gt;&lt;\/div&gt;&lt;\/div&gt;&lt;\/div&gt;&lt;\/div&gt;&lt;\/div&gt;'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );<br>\n<\/pre>\n<ul>\n<li>I give it the ID <strong>aj-search-container, <\/strong>to be able to show \/ hide the entire search container results<\/li>\n<li> most of the div\u2019s, including <strong>container<\/strong> are necessary for compatible styling with our current theme \u2013 use as necessary<\/li>\n<li><strong>sc-query <\/strong>is used to mirror the search the user has currently entered, to show that the system updates the results dynamically on his behalf (there\u2019s code to do this \u2013 read on)<\/li>\n<li><strong>aj-right-container<\/strong> contains filters to get at \u201cfacets\u201d of the search. The user can pick one or several brands to show, product categories, and we include a price filter<\/li>\n<li><strong>aj-clear-all<\/strong> will contain a link to clear facetting \u2013 to return all results which match the user\u2019s query<\/li>\n<li><strong>aj-left-container<\/strong> contains the search results. aj-stats will contain statistics about the search (search results + time taken to search), aj-search-results will contain the results, and aj-search-pagination will contain the pagination<\/li>\n<\/ul>\n<p><\/p>\n<h2>The hit template<\/h2>\n<p>again, this would probably go directly into your page instead of being injected via Javascript. <\/p>\n<p>\n<pre>&nbsp;&nbsp;&nbsp; $(\".main-content\").before(''+<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '&lt;script type=\"text\/html\" id=\"aj-hit-template\"&gt;'+<br>\n'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div class=\"aj-hit\"&gt;'+<br>\n'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div class=\"aj-hit-image\"&gt;'+<br>\n'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;A HREF=\"{{product_link}}\"&gt;&lt;img src=\"{{image}}\" alt=\"{{title}}\"&gt;&lt;\/A&gt;'+<br>\n'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/div&gt;'+<br>\n'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div class=\"aj-hit-content\"&gt;'+<br>\n'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div class=\"aj-hit-title\"&gt;&lt;A HREF=\"{{product_link}}\"&gt;{{{_highlightResult.title.value}}}{{variant_title}}&lt;\/A&gt;&lt;\/div&gt;'+<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '&lt;p class=\"aj-hit-description\"&gt;{{{_highlightResult.body_html_safe.value}}} &amp;nbsp; &lt;A HREF=\"{{product_link}}\"&gt;&amp;raquo;&amp;nbsp;mehr&lt;\/A&gt;&lt;\/p&gt;'+<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '&lt;p class=\"aj-hit-sku\"&gt;&lt;A HREF=\"{{product_link}}\"&gt;{{sku}}&lt;\/A&gt;&lt;\/p&gt;'+<br>\n'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div class=\"aj-hit-bottominfos\"&gt;' +<br>\n'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div class=\"aj-hit-price\"&gt;{{price}} \u20ac&lt;\/div&gt;' +<br>\n'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div class=\"aj-hit-stock\"&gt;{{inventory_quantity}} auf Lager &lt;\/div&gt;'+<br>\n\n'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div&nbsp; class=\"aj-hit-link\"&gt;&lt;A HREF=\"{{product_link}}\"&gt;zur Produktseite&lt;\/A&gt;&lt;\/div&gt;'+<br>\n'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/div&gt;'+<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '&lt;\/div&gt;'+<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '&lt;HR class=\"aj-divider\"&gt;' +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '&lt;\/div&gt;'+<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '&lt;\/script&gt;'+<br>&nbsp;&nbsp;&nbsp;&nbsp; '');<\/pre>\n<p>This template is inserted as \u201cscript\u201d. This is the recommended way by the Algolia docs.<\/p>\n<p>It is used to render a search result, or hit. <\/p>\n<p>Here, inside <strong>aj-hit <\/strong>we have:<\/p>\n<ul>\n<li><strong>aj-hit-image<\/strong>, using {{product_link}} and {{image}} as placeholders to insert the correct values later<\/li>\n<li><strong>aj-hit-title<\/strong>, using {{{_highlightResult.title.value}}} \u2013 I also link in the {{variant_title}} to provide a full title for variations<\/li>\n<li><strong>aj-hit-description<\/strong>, to render the product description &#8211; {{{_highlightResult.body_html_safe.value}}}<\/li>\n<li><strong>aj-hit-price <\/strong>for the {{price}} \u2013 don\u2019t forget to add your currency (or add it by modifying the variable passed to the template)<\/li>\n<li><strong>aj-hit-stock<\/strong>, to show how much {{inventory_quantity}} we have<\/li>\n<li><strong>aj-hit-link<\/strong> \u2013 finally, a link to the product page. {{product_link}}<\/li>\n<\/ul>\n<p>All of this is nicely (IMHO) styled with my CSS file. Styling is outside the scope of this blogpost, refer to <a href=\"https:\/\/buyzero.de\/\">buyzero.de<\/a> for some inspiration and then code your own.<\/p>\n<h3>More on {{{_highlightResult.title.value}}}<\/h3>\n<p>Variables displayed using three curly brackets will not be escaped by Algolia for HTML. This is used here, to allow the highlighting. <\/p>\n<p>Algolia will automatically put &lt;em&gt; Tags for you around the parts of the title, etc.&nbsp; which were matched in the <strong>_highlightResult <\/strong>variable. You can use the in the output, to show the user why the search result is thought to be relevant to their search.<\/p>\n<p>I\u2019ll later show you how to modify the values which are passed to the template, as you will not want to render the entire of your product description body, for instance.<\/p>\n<p><\/p>\n<h2>aj_setup_search<\/h2>\n<p>var pb = aj_setup_search();<\/p>\n<p>To handle the search later on, we return a variable from the setup function (called var point_both inside the setup_search function. pb is it\u2019s abbreviation).<\/p>\n<p><pre>\t\nvar search = instantsearch({\n\t  appId: 'YOUR_APP_ID',\n\t  apiKey: 'YOUR_API_KEY', \/\/ search only API key, no ADMIN key\n\t  indexName: 'shopify_buyzero_de_products',\n\t  urlSync: true,\n\t  searchParameters: {\n\t\thitsPerPage: 10\n\t  },\n\t  searchFunction(my_helper){\n\t\t  point_both.ihelper = my_helper;\n\t\t  \/\/search.helper.setQuery('Pi 3'); \/\/sic!\n\t\t  \/\/my_helper.search(); \/\/sic!\n\t\t  \n\t\t  if(my_helper.state.query === '') {\t\n\t\t\t\treturn;\n\t\t\t}\n\t\t  my_helper.search();\n\t  } \/\/end searchFunction\n\t});\/\/end instantsearch setup\n<\/pre>\n<p>Here we setup the search (as mentioned before, instantsearch is already included and available on the page through another .js file). <\/p>\n<p>You need to pass:<\/p>\n<ul>\n<li>your appId<\/li>\n<li>apiKey<\/li>\n<li>indexName<\/li>\n<\/ul>\n<p>you will get these from your Algolia backend. There you can also browse your data structures, and see what parameters you can use for faceting, for instance.<\/p>\n<p><strong>The really important bit is the searchFunction (my_helper) function.<\/strong><\/p>\n<p>The helper allows you to drive the search via your own script, instead of triggering it from a search box widget which is setup with Algolia\u2019s instantsearch. <\/p>\n<p>It is important to create a reference to this helper, in this particular function. <\/p>\n<p><strong>point_both.ihelper = my_helper;<\/strong><\/p>\n<p>Accessing the helper from the search variable later on will <strong>not <\/strong>work. <\/p>\n<p>In fact you need both. See this example code, I commented out?<\/p>\n<p>\/\/search.helper.setQuery(&#8216;Pi 3&#8217;); \/\/sic!\n<\/p>\n<p>\/\/my_helper.search(); \/\/sic!\n<\/p>\n<p>sic is the latin word for \u201clike this\u201d. Meaning, it indeed has to be accessed in two different ways to set the query and then execute the search.<\/p>\n<p>Also, you <strong>need <\/strong>to add my_helper.search() in here. This will \u2013 as I remember it \u2013 allow your widgets to update the search correctly \u2026 if you find that your results are not updated, check whether you have it in there!<\/p>\n<p><\/p>\n<p>After adding the widgets \u2013 which we will discuss below \u2013 we wrap up the search setup with the following code:<\/p>\n<p>search.start();<br \/>\npoint_both.search = search;<br \/>\nreturn point_both;<\/p>\n<p>Here we also add a reference to the search object itself, and return it to the aj_setup function. <\/p>\n<p>Note that point_both now has access to the \u201csearch\u201d object, and the special helper object \u201cihelper\u201d we obtained from within the searchFunction function.<\/p>\n<p><\/p>\n<h2>Adding the first widget<\/h2>\n<p>we will add the result as the first widget:<\/p>\n<p><\/p>\n<p>search.addWidget(<br \/>&nbsp;&nbsp; instantsearch.widgets.hits({<br \/>&nbsp;&nbsp;&nbsp;&nbsp; container: &#8216;#aj-search-results&#8217;,<br \/>&nbsp;&nbsp;&nbsp;&nbsp; templates: {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; item: document.getElementById(&#8216;aj-hit-template&#8217;).innerHTML,<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; empty: &#8220;Es konnten leider keine Resultate f\u00fcr die Suchanfrage &lt;em&gt;\\&#8221;{{query}}\\&#8221;&lt;\/em&gt; gefunden werden.&#8221;<br \/>&nbsp;&nbsp;&nbsp;&nbsp; },<br \/>&nbsp;&nbsp;&nbsp;&nbsp; transformData: {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; item: function (my_result) {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/console.log(my_result);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/console.log(my_result._highlightResult.body_html_safe.value);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (my_result[&#8220;variant_title&#8221;] == &#8216;Default Title&#8217;){<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; my_result[&#8220;variant_title&#8221;] = &#8221;;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; my_result[&#8220;variant_title&#8221;] = &#8216; :: &#8216; + my_result[&#8220;variant_title&#8221;];<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/my_result[&#8220;body_html_safe&#8221;] = my_result[&#8220;body_html_safe&#8221;].substring(0,175) + &#8216;\u2026&#8217;;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/we do NOT want multiline, we want to match the REAL ending of the string. \/m would match at the line ending ..<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var pattern_a = \/(.*?)(&lt;[^&gt;]*)?$\/i;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var pattern_b = \/&lt;em&gt;[^&lt;]+$\/i;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/take the first matched group &#8211; which excludes the second match.<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var body_string = my_result._highlightResult.body_html_safe.value.substring(0,175).replace(pattern_a,&#8221;$1&#8243;);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pattern_b.test(body_string)){<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; body_string = body_string + &#8220;&lt;\/em&gt;&#8221;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/search for pi 3 b+<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/product id <a href=\"https:\/\/buyzero.de\/products\/budget-kit-raspberry-pi-3-model-b?variant=698066665499\">https:\/\/buyzero.de\/products\/budget-kit-raspberry-pi-3-model-b?variant=698066665499<\/a><br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; my_result._highlightResult.body_html_safe.value = body_string + &#8216;\u2026&#8217;;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; my_result[&#8220;product_link&#8221;] = &#8220;<a href=\"https:\/\/buyzero.de\/products\/&quot;\">https:\/\/buyzero.de\/products\/&#8221;<\/a> + my_result[&#8220;handle&#8221;] + &#8220;?variant=&#8221; + my_result[&#8220;id&#8221;];<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return my_result;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp; })<br \/>\n);<\/p>\n<p><\/p>\n<p>The container to put the output in is selected as&nbsp; &#8216;#aj-search-results&#8217;, the template to render the results is selected here: item: document.getElementById(&#8216;aj-hit-template&#8217;).innerHTML.<\/p>\n<p>I assume that they put this in a &lt;script&gt; tag, because the contents are not rendered as HTML by the browser. <\/p>\n<p>For empty we just pass a string back as template. <\/p>\n<p>Really straightforward so far, right?<\/p>\n<p><\/p>\n<p>Next we use <strong>transformData <\/strong>to prepare a shortened version of your product\u2019s text body and other variables passed to the hit template discussed previously. <\/p>\n<p>Because we introduced &lt;em&gt;\u2019s into the search output \u2013 using the automatic highlighting of Algolia \u2013 we need to shorten the text in a safe manner. I\u2019ve prepared my own regular expressions for this, in my example code.<\/p>\n<p>If there is an incomplete statement beginning with &lt; after the shortening&nbsp; (no matching &gt;), it is cut from the output. <\/p>\n<p>If there is an &lt;em&gt; tag without corresponding &lt;\/em&gt; tag to close it, we add it. <\/p>\n<p>The product link is built obtaining the handle, and setting the id as the variant. <\/p>\n<p><\/p>\n<h2>Adding pagination<\/h2>\n<p>adding additional widgets is easy:<\/p>\n<p>\/\/ Add this after the other search.addWidget() calls<br \/>\nsearch.addWidget(<br \/>&nbsp;&nbsp; instantsearch.widgets.pagination({<br \/>&nbsp;&nbsp;&nbsp;&nbsp; container: &#8216;#aj-search-pagination&#8217;,<br \/>&nbsp;&nbsp;&nbsp;&nbsp; render: function(my_obj){<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; console.log(&#8220;render&#8221;);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; console.log(my_obj);<br \/>&nbsp;&nbsp;&nbsp;&nbsp; },<br \/>&nbsp;&nbsp;&nbsp;&nbsp; getConfiguration: function(my_obj){<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; console.log(&#8220;getConfiguration&#8221;);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; console.log(my_obj);<br \/>&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp; })<br \/>\n);<\/p>\n<p>\n<\/p>\n<p>you don\u2019t want the console log output \u2026 I was using this to debug, and apparently forgot to took it out. Sorry. I\u2019m human.<\/p>\n<p>Again, the widget\u2019s output container is set. #aj-search-pagination&#8217;<\/p>\n<p>You don\u2019t really need anything else for pagination to work \u2013 set up the widget, and style it \u2013 you\u2019ll be good.<\/p>\n<p><\/p>\n<h2>Faceting<\/h2>\n<p>With faceting your user can refine their search:<\/p>\n<p>\/\/ Faceting<br \/>\nsearch.addWidget(<br \/>&nbsp;&nbsp; instantsearch.widgets.refinementList({<br \/>&nbsp;&nbsp;&nbsp;&nbsp; container: &#8216;#aj-facet-brand&#8217;,<br \/>&nbsp;&nbsp;&nbsp;&nbsp; attributeName: &#8216;vendor&#8217;,<br \/>&nbsp;&nbsp;&nbsp;&nbsp; operator: &#8216;or&#8217;,<br \/>&nbsp;&nbsp;&nbsp;&nbsp; limit: 5,<br \/>&nbsp;&nbsp;&nbsp;&nbsp; showMore: true,<br \/>&nbsp;&nbsp;&nbsp;&nbsp; cssClasses: {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; header: &#8216;aj-refine-header&#8217;,<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count: &#8216;aj-refine-count&#8217;<br \/>&nbsp;&nbsp;&nbsp;&nbsp; },<br \/>&nbsp;&nbsp;&nbsp;&nbsp; templates: {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; header: &#8216;Marke \/ Brand&#8217;<br \/>&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp; })<br \/>\n);<\/p>\n<p><\/p>\n<ul>\n<li>you need to look at possible attributeNames in your Algolia backend \u2013 it will show you the available facets for your data (see screenshot below).<\/li>\n<li>The limit of 5 does not refer to your search results, but to the limit of entries which are shown by Algolia for your refinementList<\/li>\n<li>The available refinements will be automatically updated if the other search parameters are changed (e.g. if there is no match for a specific brand, this brand will not be shown)<\/li>\n<li>showMore: will show a show more link at the bottom of the widget<\/li>\n<li>count: \u2018aj-refine-count\u2019 \u2013 you can style your search results a bit. Probably more than I ued here \u2013 <a href=\"https:\/\/community.algolia.com\/instantsearch.js\/v2\/widgets\/refinementList.html\">refer to the official documentation<\/a><\/li>\n<\/ul>\n<p><\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2018\/08\/image-6.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1100\" height=\"401\" title=\"image\" style=\"margin: 0px; display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2018\/08\/image_thumb-6.png\" border=\"0\"><\/a><\/p>\n<h2>Clear Facets widget<\/h2>\n<p>search.addWidget(<br \/>&nbsp;&nbsp; instantsearch.widgets.clearAll({<br \/>&nbsp;&nbsp;&nbsp;&nbsp; container: &#8216;#aj-clear-all&#8217;,<br \/>&nbsp;&nbsp;&nbsp;&nbsp; templates: {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; link: &#8216;Filter zur\u00fccksetzen \/ Reset&#8217;<br \/>&nbsp;&nbsp;&nbsp;&nbsp; },<br \/>&nbsp;&nbsp;&nbsp;&nbsp; autoHideContainer: false,<br \/>&nbsp;&nbsp;&nbsp;&nbsp; clearsQuery: true,<br \/>&nbsp;&nbsp; })<br \/>\n);\n<\/p>\n<p>use this to allow the customer to clear the facetting (i.e. they will be shown all results that match for their query again).<\/p>\n<p>No need of configuring besides this.<\/p>\n<p><\/p>\n<p>I will not speak about the other widgets \u2013 take a look at my code if you are interested.<\/p>\n<p><\/p>\n<h2>Binding to the search box<\/h2>\n<p>We are not using Algolia\u2019s search widget, but bind to a keyup event on our search form input, like this:<\/p>\n<p>&nbsp;&nbsp;&nbsp; var pb = aj_setup_search();<br \/>&nbsp;&nbsp;&nbsp;&nbsp; \/\/#search_query is the input we want<br \/>&nbsp;&nbsp;&nbsp;&nbsp; $(&#8220;#search_query&#8221;).keyup(function(search) {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; updateSearch(pb);<br \/>&nbsp;&nbsp;&nbsp;&nbsp; });&nbsp;&nbsp;&nbsp; <br \/>\n}<\/p>\n<p>(we discussed aj_setup_search just now, it\u2019s added here to show you where pb comes from). <\/p>\n<p>We do this so we can do additional processing when the keyup event is triggered \u2013 hiding the content we were displaying previously on the page, and adding the search results, etc.<\/p>\n<p><\/p>\n<p>function updateSearch(pb){<br \/>&nbsp;&nbsp;&nbsp;&nbsp; var my_query = $(&#8220;#search_query&#8221;).val();<br \/>&nbsp;&nbsp;&nbsp;&nbsp; \/\/$(&#8220;.main-content&#8221;).html(my_query);<br \/>&nbsp;&nbsp;&nbsp;&nbsp; if (my_query) {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(&#8220;.main-content&#8221;).hide();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(&#8220;#megamenu-header-menu2&#8221;).hide();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(&#8220;#ajr_na&#8221;).show();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(&#8220;#sc-query&#8221;).html(my_query);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(&#8220;#aj-search-container&#8221;).show();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pb.search.helper.setQuery(my_query);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/console.log(search_handle.helper.state);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pb.ihelper.search();<br \/>&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp;&nbsp;&nbsp; else {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(&#8220;#aj-search-container&#8221;).hide();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(&#8220;.main-content&#8221;).show();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(&#8220;#ajr_na&#8221;).hide();<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(&#8220;#megamenu-header-menu2&#8221;).show();<br \/>&nbsp;&nbsp;&nbsp;&nbsp; }<\/p>\n<p>}<\/p>\n<p>We use jQuery to obtain the value of the search field. If it is not empty, we hide the main content we were displaying before, and show the search container. <\/p>\n<p>We set sc-query to show to the user that we are responding to his entry: $(&#8220;#sc-query&#8221;).html(my_query);<\/p>\n<p>Finally, the important bits are these here:<\/p>\n<p><strong>pb.search.helper.setQuery(my_query);<br \/>\npb.ihelper.search();<br \/>\n<\/strong><\/p>\n<p>as you see, <strong>we need to use two different helpers to set the query and execute the actual search<\/strong>. Yes, that is how it needs to be done \u2013 luckily I found someone complaining about this behaviour. <\/p>\n<p>Finally, if the search string is empty (the user pressed Escape, or deleted it, or we deleted it, or whatever \u2026) we hide the search, and show the main content.<\/p>\n<h2>Thank you for reading<\/h2>\n<p><strong>Thank you for your attention, I hope this helps someone who wants to implement instantsearch.js without using Algolia\u2019s search widget. <\/strong><\/p>\n<p><\/p>\n<h1>References<\/h1>\n<p><strong>Tampermonkey<\/strong><\/p>\n<ul>\n<li><a href=\"https:\/\/tampermonkey.net\/documentation.php\">https:\/\/tampermonkey.net\/documentation.php<\/a><\/li>\n<\/ul>\n<p><strong>Algolia<\/strong><\/p>\n<ul>\n<li><a href=\"https:\/\/community.algolia.com\/instantsearch.js\/v2\/widgets.html\">Algolia instantsearch widgets documentation<\/a><\/li>\n<li><a href=\"https:\/\/community.algolia.com\/shopify\/instant_search.html\">https:\/\/community.algolia.com\/shopify\/instant_search.html<\/a><\/li>\n<li><a href=\"https:\/\/www.algolia.com\/doc\/tutorials\/search-ui\/instant-search\/build-an-instant-search-results-page\/instantsearchjs\/\">https:\/\/www.algolia.com\/doc\/tutorials\/search-ui\/instant-search\/build-an-instant-search-results-page\/instantsearchjs\/<\/a><\/li>\n<li><a href=\"https:\/\/www.algolia.com\/doc\/guides\/searching\/highlighting-snippeting\">https:\/\/www.algolia.com\/doc\/guides\/searching\/highlighting-snippeting<\/a><\/li>\n<li><a href=\"https:\/\/www.algolia.com\/doc\/guides\/search-ui\/building-a-search-ui\/\">https:\/\/www.algolia.com\/doc\/guides\/search-ui\/building-a-search-ui\/<\/a><\/li>\n<li><a href=\"https:\/\/community.algolia.com\/instantsearch.js\/v2\/widgets\/hits.html#struct-HitsTransforms\">https:\/\/community.algolia.com\/instantsearch.js\/v2\/widgets\/hits.html#struct-HitsTransforms<\/a><\/li>\n<li><a href=\"https:\/\/stackoverflow.com\/questions\/42672838\/algolia-instantsearch-add-a-callback-after-results-are-displayed\">https:\/\/stackoverflow.com\/questions\/42672838\/algolia-instantsearch-add-a-callback-after-results-are-displayed<\/a><\/li>\n<li><a href=\"https:\/\/community.algolia.com\/algoliasearch-helper-js\/gettingstarted.html\">https:\/\/community.algolia.com\/algoliasearch-helper-js\/gettingstarted.html<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/algolia\/instantsearch.js\/issues\/1924\">https:\/\/github.com\/algolia\/instantsearch.js\/issues\/1924<\/a><\/li>\n<li><a href=\"https:\/\/jsfiddle.net\/bobylito\/bsjdch4m\/1\/\">https:\/\/jsfiddle.net\/bobylito\/bsjdch4m\/1\/<\/a><\/li>\n<li><a href=\"https:\/\/stackoverflow.com\/questions\/49638646\/algolia-instantsearch-with-multiple-indices-and-multiple-pagination-widgets\/49796164?noredirect=1#comment86826994_49796164\">https:\/\/stackoverflow.com\/questions\/49638646\/algolia-instantsearch-with-multiple-indices-and-multiple-pagination-widgets\/49796164?noredirect=1#comment86826994_49796164<\/a> <\/li>\n<li><a href=\"https:\/\/github.com\/algolia\/instantsearch.js\/issues\/2887\">https:\/\/github.com\/algolia\/instantsearch.js\/issues\/2887<\/a><\/li>\n<\/ul>\n<p><strong>Bonus<\/strong><\/p>\n<ul>\n<li><a href=\"https:\/\/discourse.algolia.com\/t\/how-to-create-facet-widget-from-shopify-metafield\/1710\">https:\/\/discourse.algolia.com\/t\/how-to-create-facet-widget-from-shopify-metafield\/1710<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/algolia\/awesome-algolia\">https:\/\/github.com\/algolia\/awesome-algolia<\/a><\/li>\n<\/ul>\n<p><\/p>\n<ul>\n<p><\/p>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>\"Gute K\u00fcnstler kopieren, gro\u00dfe K\u00fcnstler klauen.\" - Steve Jobs Inspiriert von pimoroni.com wollte ich eine \u00e4hnliche Suche auch auf unserem Webshop, buyzero.de, implementieren. buyzero.de wird derzeit von Shopify betrieben. Die Suche zeigt die Ergebnisse w\u00e4hrend der Eingabe an - auf der Hauptseite, und ersetzt dynamisch den vorher angezeigten Inhalt. Sehr cool, sehr n\u00fctzlich - und...<\/p>","protected":false},"author":830,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[402],"tags":[],"class_list":["post-5269","post","type-post","status-publish","format-standard","hentry","category-development"],"_links":{"self":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/5269","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/users\/830"}],"replies":[{"embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/comments?post=5269"}],"version-history":[{"count":2,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/5269\/revisions"}],"predecessor-version":[{"id":5278,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/5269\/revisions\/5278"}],"wp:attachment":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/media?parent=5269"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/categories?post=5269"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/tags?post=5269"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}