Strattic Developer Docs

How to Set up an Algolia Instasearch App on your Strattic Site

Before you get started

This guide assumes you’re bringing your own Algolia index, and not using Strattic’s index of your site.

From there, you will need three things for the app to work:

  • Application ID (e.g. ABCDEF12345)
  • Search API key (e.g. asdf1234asdf1234asdf1234)
  • Index name (e.g. wp_posts_index)

These can all be found in your Algolia dashboard.

A note on the publish process on Strattic

On Strattic, you have the Live and Preview sites and if there’s anything unique you need to do, make sure to account for that.

For example, after you change the styling for your search, you’d need to republish to Preview or Live to see the changes on your static site. But if you’re just refreshing Algolia results or reindexing, you shouldn’t need to republish.

Set up a local working version of your app (optional, but helpful)

I’d recommend getting set up locally first, which will allow you to iterate quickly to get the functionality you’re looking for (we’ll talk about styles more below).

See Examples here: https://www.algolia.com/doc/guides/building-search-ui/resources/demos/js/

Review what Instantsearch is: https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/js/

Follow the Gettings Started guide to get up and running with an app: https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/js/

If you’re using the command line and npx create-instantsearch-app my-app, you’ll need to make sure you have NodeJS installed on your local computer (see https://nodejs.org/en/download/ for more info and download and installation instructions).

From here, you can go through the npx create-instantsearch-app my-app, entering:

  • The name of the application or widget: my-app (or whatever you want to name it)
  • InstantSearch template: InstantSearch.js (you can use React or something else if you like, but the JS version is what is demoed below)
  • InstantSearch.js version: 4.37.1 (or whatever the latest version is)
  • Application ID: latency (or whatever you app ID is)
  • Search API key: 6be0576ff61c053d5f9a3225e2a90f76 (or whatever you API key is)
  • Index name: instant_search (or whatever you index name is)
  • Attributes to display: You can select as many of these as you like.
  • Dynamic widget attributes: Start just selecting one and add more as you go along (the below code doesn’t use dynamic widgets, so you could also select none here)

Create the app, and follow the terminal instructions for starting the app.

See the following for more info and hints on building out the app (and to understand the below code):

You may need to transform the hits items coming back from Algolia. If that’s the case, you can use this method: https://www.algolia.com/doc/api-reference/widgets/hits/js/#widget-param-transformitems (see below code for more on this method).

Move it to WordPress

Now that the app is built out, let’s add it to our WordPress.

This is adapted from: https://www.algolia.com/doc/guides/building-search-ui/installation/js/#directly-in-your-page

Assuming you have a child theme set up, do the following:

  1. Add a page-instasearch.php file to your child theme (code below).
  2. Create a page in your WordPress dashboard called Instasearch and chose the Instasearch page themplate.
  3. In an instasearch directory in your child theme folder add two files: instastyles.css and instascripts.js (code below)
  4. In your child theme’s function.php file, add the function and action hook that enqueues the appropriate scripts (code below)

The result can be previewed here: https://algoliainstantsearch.preview.strattic.io/instasearch/

Note, you can add whatever JS or CSS code you added to app.js to your instascripts.js script (which adjustsments for the window, see the above directly-in-you-page link), and the CSS to instastyles.css.

Also, you can call these files whatever you like, feel free 😁.

With the below code, you should be able to see the Instasearch app show up on whatever page you’ve assigned it to on your WordPress site.

A not on styles: If you look at the Preview on Strattic, the styles are different and could “use some work”. That’s fine, and up to you to make sure things are styled to your needs, though the Instasearch styles we’ve enqueued give you a good starting point. You can read more about about styling Instasearch here: https://www.algolia.com/doc/guides/building-search-ui/widgets/customize-an-existing-widget/js/#style-your-widgets

The page-instasearch.php template

<?php

/**
 * Template Name: Instasearch
 *
 * @link https://developer.wordpress.org/themes/basics/template-hierarchy/
 *
 * @package WordPress
 * @subpackage Twenty_Twenty
 * @since Twenty Twenty 1.0
 */

get_header();
?>

<main id="site-content" role="main">

    <div class="ais-InstantSearch">
        <h1>InstantSearch Demo</h1>

        <div class="left-panel">
            <div id="clear-refinements"></div>

            <h2>Categories</h2>
            <div id="taxonomy-category"></div>
            <h2>Tags</h2>
            <div id="taxonomy-post_tag"></div>
        </div>

        <div class="right-panel">
            <div id="searchbox"></div>
            <div id="hits"></div>
            <div id="pagination"></div>
        </div>
    </div>

    <div class="container">
        <div class="search-panel">
            <div class="search-panel__filters">
                <div id="dynamic-widgets"></div>
            </div>

            <div class="search-panel__results">
                <div id="searchbox"></div>
                <div id="hits"></div>
            </div>
        </div>

        <div id="pagination"></div>
    </div>

</main><!-- #site-content -->

<?php get_template_part('template-parts/footer-menus-widgets'); ?>

<?php get_footer(); ?>

The instastyles.css file

.ais-ClearRefinements {
  margin: 1em 0;
}
.ais-SearchBox {
  margin: 1em 0;
}
.ais-Pagination {
  margin-top: 1em;
}
.left-panel {
  float: left;
  width: 250px;
}
.right-panel {
  margin-left: 260px;
}
.ais-InstantSearch {
  max-width: 960px;
  overflow: hidden;
  margin: 0 auto;
}
.ais-Hits-item {
  margin-bottom: 1em;
  width: calc(50% - 1rem);
}
.ais-Hits-item img {
  margin-right: 1em;
}
.hit-name {
  margin-bottom: 0.5em;
}
.hit-description {
  color: #888;
  font-size: 14px;
  margin-bottom: 0.5em;
}

The instascripts.js file

const { algoliasearch, instantsearch } = window;

const searchClient = algoliasearch('ABCDEF12345', 'asdf1234asdf1234asdf1234');

const search = instantsearch({
  indexName: 'wp_posts_index',
  searchClient,
});

search.addWidgets([
  instantsearch.widgets.searchBox({
    container: '#searchbox',
  }),
  instantsearch.widgets.clearRefinements({
    container: '#clear-refinements',
  }),
  instantsearch.widgets.refinementList({
    container: '#taxonomy-category',
    attribute: 'taxonomies.category',
  }),
  instantsearch.widgets.refinementList({
    container: '#taxonomy-post_tag',
    attribute: 'taxonomies.post_tag',
  }),
  instantsearch.widgets.configure({
    hitsPerPage: 12,
    attributesToRetrieve: [
      '*', // list of attributes to retrieve
    ]
  }),
  instantsearch.widgets.hits({
    container: '#hits',
    transformItems(items) {
      return items.map(item => ({
        ...item,
        post_title: item.post_title.toLowerCase(),
        categories: ( item.taxonomies.category ) ? item.taxonomies.category.join(', ') : '',
        post_tags: ( item.taxonomies.post_tag ) ? item.taxonomies.post_tag.join(', ') : '',
        featureImg: ( item.images.hasOwnProperty('thumbnail') ) ? item.images.thumbnail.url.replace('dev.site.strattic', 'dev.live.strattic') : ''
      }));
    },
    templates: {
      item: `
        <article>
          {{#featureImg}}<img src="{{ featureImg }}" align="left" alt="{{post_title}}" /> {{/featureImg}}
          <h3>{{#helpers.highlight}}{ "attribute": "post_title" }{{/helpers.highlight}}</h3>
          <p>Author: {{ post_author.display_name   }}</p>
          <p>Categories: {{ categories }} | Tags: {{ post_tags }}</p>
          <p>{{#helpers.highlight}}{ "attribute": "content" }{{/helpers.highlight}}</p>
        </article>
        `,
    },
  }),
  instantsearch.widgets.pagination({
    container: '#pagination',
  }),
]);

search.start();

Add this snippet to your function.php file

function strattic_instasearch_register_styles_scripts() {
    if( is_page( 'instasearch' ) ) {

        $theme_version = wp_get_theme()->get( 'Version' );

        // Add app styles.
        wp_enqueue_style( 'strattic_instasearch-rest-style', '//cdn.jsdelivr.net/npm/instantsearch.css@7.3.1/themes/reset-min.css', null, $theme_version );
        wp_enqueue_style( 'strattic_instasearch-base-style', '//cdn.jsdelivr.net/npm/instantsearch.css@7/themes/algolia-min.css', null, $theme_version );
        wp_enqueue_style( 'strattic_instasearch-print-style', get_stylesheet_directory_uri() . '/instasearch/instastyles.css', null, $theme_version );

        // Add app script.
        wp_enqueue_script( 'strattic_instasearch-algolia-lite-js', '//cdn.jsdelivr.net/npm/algoliasearch@4.5.1/dist/algoliasearch-lite.umd.js', array(), $theme_version, false );
        wp_script_add_data( 'strattic_instasearch-js', 'async', true );
        wp_enqueue_script( 'strattic_instasearch-prod-js', '//cdn.jsdelivr.net/npm/instantsearch.js@4.8.3/dist/instantsearch.production.min.js', array(), $theme_version, false );
        wp_script_add_data( 'strattic_instasearch-js', 'async', true );
        wp_enqueue_script( 'strattic_instasearch-js', get_stylesheet_directory_uri() . '/instasearch/instascripts.js', array(), $theme_version, false );
        wp_script_add_data( 'strattic_instasearch-js', 'async', true );
    }
}

add_action( 'wp_enqueue_scripts', 'strattic_instasearch_register_styles_scripts' );