Algolia e usando instantsearch.js dal tuo script per Shopify

"I buoni artisti copiano, i grandi artisti rubano". - Steve Jobs

Ispirato da pimoroni.com Volevo implementare una ricerca simile sul nostro webshop, buyzero.de buyzero.de è attualmente alimentato da Shopify.

La ricerca mostra i risultati mentre si digita - nella pagina principale, sostituendo dinamicamente il contenuto precedentemente visualizzato. Molto bello, molto utile - e molto, molto veloce (grazie a Algolia!)

Dal momento che ho lottato con la documentazione disponibile su Algolia, e il loro servizio di onboarding non è stato molto utile, ho dovuto capire le cose da solo, e con una vasta ricerca su Google.

Questo è un riassunto della mia esperienza nell'implementazione di Algolia. L'ho fatto in un solo giorno, in una sola sessione di circa 12 - 14 ore di codifica.

Preparazione suggerita: iniezione di codice di sviluppo nella tua pagina

Suggerisco di usare l'estensione di Google Chrome Tampermonkey per iniettare CSS e Javascript dal tuo hard disk locale mentre sviluppi.

Per fare questo, devi abilitare l'accesso ai file per Tampermonkey. Aprire:

chrome://extensions

Clicca su Dettagli e attiva "Consenti l'accesso agli URL dei file" su

immagine

immagine

Crea il seguente nuovo userscript in Tampermonkey:

// ==UserScript==
// @nome Algolia-Inject
// @namespace https://pi3g.com/
// @versione 0.5
// @description inietta un file locale per testare Algolia!
// @autore Maximilian Batz
// @concessione GM_getResourceText
// @grant GM_addStyle
// @noframes
// @include https://buyzero.de/*
// @resource YOUR_CSS file://D:\algolia_jr.css
// @require file://D:\algolia_jr.js

// ==/UserScript==

var my_css = GM_getResourceText ("YOUR_CSS");
GM_addStyle(my_css);

Spiegazione:

  • dovete concedere getResourceText e addStyle per poter accedere e iniettare il file CSS
  • noframes per non eseguire una seconda volta nei frame che Shopify apparentemente carica, e che corrisponderebbe anche al dominio
  • include -> corrisponderà a buyzero.de. Potresti voler cambiare quella linea Sorriso
  • risorsa usata per importare il file CSS. Fornisci il percorso ... in Linux potrebbe essere file:///home/whatever/whatever - notare la tripla barra in avanti
  • require - includi il tuo file javascript
  • userscript: questo è l'userscript per aggiungere il file CSS

Aggiungere il codice Algolia

Con il "come sviluppare" fuori dai piedi, ecco il mio codice come codice d'esempio in un piccolo file ZIP.

Per favore non copiate da questo blog, perché non sono sicuro che WordPress distruggerà la formattazione del codice ... usate il .js nel file ZIP per copiarlo.

Si prega di notare che le dipendenze Algolia / file JavaScript erano già installati nel nostro tema Shopify - installando il plugin Algolia Shopify. Anche il nostro datastore era impostato, ecc. Algolia serviva (e serve ancora) già i risultati della ricerca in un menu a tendina mentre si digitava nella casella di ricerca.

Vi guiderò attraverso le parti importanti del codice:

avviamo aj_setup() una volta che il documento è pronto, per iniettare la nostra nuova funzionalità di ricerca.

Si prega di notare che io uso aj per aggiungere le mie funzioni e gli id per questo script. Potete usare quello che volete, non è richiesto da Algolia.

Il contenitore

in aj_setup() ho impostato un nuovo contenitore in cui mettere i risultati della ricerca (sarebbe probabilmente una pratica migliore includere questo direttamente nel file del tema - per lo sviluppo è stato più facile).

questa è la parte HTML della ricerca

$(".main-content").before('<div id="aj-search-container" class="aj-main-content full-width"><div class="background"><div class="pattern"><div class="container"><div class="row"><div class="col-md-12"><div class="row"><div class="col-md-12 center-column content-without-background">'+
                         "
"+
                           "<h1>Tali risultati sono stati ottenuti per: <span id='sc-query'></span></h1>" +
                           "
" +
                             "
" +
                             "
" +
                             "
" +
                             "
" +
                           "
" +
                           "
" +
                               "
" +
                               "
" +
                               "
" +
                           "</DIV" +
                       "
" +
                       '</div></div></div></div></div></div></div></div>'
                       );
  • Gli do l'ID aj-search-container, essere in grado di mostrare/nascondere l'intero contenitore dei risultati della ricerca
  • la maggior parte dei div, tra cui contenitore sono necessari per uno stile compatibile con il nostro tema attuale - utilizzare come necessario
  • sc-query è usato per rispecchiare la ricerca che l'utente ha attualmente inserito, per mostrare che il sistema aggiorna dinamicamente i risultati per suo conto (c'è del codice per farlo - continua a leggere)
  • aj-right-container contiene dei filtri per ottenere delle "sfaccettature" della ricerca. L'utente può scegliere una o più marche da mostrare, categorie di prodotti, e noi includiamo un filtro di prezzo
  • aj-clear-all conterrà un link per cancellare la sfaccettatura - per restituire tutti i risultati che corrispondono alla query dell'utente
  • aj-left-container contiene i risultati della ricerca. aj-stats conterrà le statistiche sulla ricerca (risultati della ricerca + tempo impiegato per la ricerca), aj-search-results conterrà i risultati, e aj-search-pagination conterrà la paginazione

Il modello di colpo

Di nuovo, questo andrebbe probabilmente direttamente nella tua pagina invece di essere iniettato tramite Javascript.

    $(".main-content").before(''+
       ''+
'          <div class="aj-hit">'+
'            <div class="aj-hit-image">'+
'              <a href="/it/{{product_link}}/"><img src="{{image}}" alt="{{titolo}}"></a>'+
'            </div>'+
'            <div class="aj-hit-content">'+
'              <div class="aj-hit-title"><a href="/it/{{product_link}}/">{{{highlightResult.title.value}}}{{variant_title}}</a></div>'+
               '<p class="aj-hit-description">{{{_highlightResult.body_html_safe.value}}} &nbsp; <a href="/it/{{product_link}}/">" altro</a></p>'+
               '<p class="aj-hit-sku"><a href="/it/{{product_link}}/">{{sku}}</a></p>'+
'              <div class="aj-hit-bottominfos">' +
'                <div class="aj-hit-price">{{prezzo}} €</div>' +
'                <div class="aj-hit-stock">{{inventario_quantità}} auf Lager </div>'+
'                <div  class="aj-hit-link"><a href="/it/{{product_link}}/">per il sito di produzione</a></div>'+
'             </div>'+
             '</div>'+
             '
' +
           '</div>'+
         ''+
     '');

Questo modello è inserito come "script". Questo è il modo raccomandato dai documenti di Algolia.

È usato per rendere un risultato di ricerca, o hit.

Qui, dentro aj-hit abbiamo:

  • aj-hit-imageusando {{prodotto_link}} e {{immagine}} come segnaposto per inserire i valori corretti in seguito
  • aj-hit-titleusando {{{_highlightResult.title.value}} - mi collego anche al {{variant_title}} per fornire un titolo completo per le variazioni
  • aj-hit-descriptionper rendere la descrizione del prodotto - {{{_highlightResult.body_html_safe.value}}}
  • aj-hit-price per il {{prezzo}} - non dimenticare di aggiungere la tua valuta (o aggiungerla modificando la variabile passata al modello)
  • aj-hit-stockper mostrare quanto {{inventario_quantità}} abbiamo
  • aj-hit-link - infine, un link alla pagina del prodotto. {{link_prodotto}}

Tutto questo è ben (IMHO) stilizzato con il mio file CSS. Lo styling è al di fuori dello scopo di questo blogpost, fate riferimento a buyzero.de per un po' di ispirazione e poi codificate il vostro.

Più su {{{_highlightResult.title.value}}

Le variabili visualizzate utilizzando tre parentesi graffe non saranno sottoposte a escape da Algolia per HTML. Questo è usato qui, per permettere l'evidenziazione.

Algolia metterà automaticamente i tag intorno alle parti del titolo, ecc. che sono state abbinate nel _highlightResultato variabile. Potete usare la variabile nell'output, per mostrare all'utente perché il risultato della ricerca è ritenuto pertinente alla sua ricerca.

Più tardi vi mostrerò come modificare i valori che vengono passati al modello, dato che non vorrete rendere l'intero corpo della descrizione del prodotto, per esempio.

aj_setup_search

var pb = aj_setup_search();

Per gestire la ricerca in seguito, restituiamo una variabile dalla funzione setup (chiamata var point_both all'interno della funzione setup_search. pb è la sua abbreviazione).

	
var search = instantsearch({
	  appId: 'YOUR_APP_ID',
	  apiKey: 'YOUR_API_KEY', // search only API key, no ADMIN key
	  indexName: 'shopify_buyzero_de_products',
	  urlSync: true,
	  searchParameters: {
		hitsPerPage: 10
	  },
	  searchFunction(my_helper){
		  point_both.ihelper = my_helper;
		  //search.helper.setQuery('Pi 3'); //sic!
		  //my_helper.search(); //sic!
		  
		  if(my_helper.state.query === '') {	
				return;
			}
		  my_helper.search();
	  } //end searchFunction
	});//end instantsearch setup

Qui impostiamo la ricerca (come detto prima, instantsearch è già incluso e disponibile nella pagina attraverso un altro file .js).

Devi passare:

  • il tuo appId
  • apiKey
  • indexName

li otterrete dal vostro backend Algolia. Lì potete anche sfogliare le vostre strutture di dati, e vedere quali parametri potete usare per il faceting, per esempio.

La parte veramente importante è la funzione searchFunction (my_helper).

L'helper permette di pilotare la ricerca tramite il proprio script, invece di attivarla da un widget di casella di ricerca che è impostato con instantsearch di Algolia.

È importante creare un riferimento a questo helper, in questa particolare funzione.

point_both.ihelper = my_helper;

Accedendo all'helper dalla variabile di ricerca in seguito non lavoro.

In effetti avete bisogno di entrambi. Vedete questo codice di esempio che ho commentato?

//search.helper.setQuery('Pi 3'); //sic!

//my_helper.search(); //sic!

sic è la parola latina per "come questo". Significa che bisogna effettivamente accedere in due modi diversi per impostare la query e poi eseguire la ricerca.

Inoltre, tu bisogno di per aggiungere my_helper.search() qui dentro. Questo - se ricordo bene - permetterà ai vostri widget di aggiornare correttamente la ricerca... se trovate che i vostri risultati non vengono aggiornati, controllate se l'avete inserito!

Dopo aver aggiunto i widget - di cui parleremo più avanti - concludiamo la configurazione della ricerca con il seguente codice:

search.start();
punto_both.search = ricerca;
ritorno punto_both;

Qui aggiungiamo anche un riferimento all'oggetto di ricerca stesso, e lo restituiamo alla funzione aj_setup.

Notate che point_both ha ora accesso all'oggetto "search", e all'oggetto helper speciale "ihelper" che abbiamo ottenuto dall'interno della funzione searchFunction.

Aggiungere il primo widget

aggiungeremo il risultato come primo widget:

search.addWidget(
   instantsearch.widgets.hits({
     container: '#aj-search-results',
     modelli: {
       item: document.getElementById('aj-hit-template').innerHTML,
       vuoto: "Es konnten leider keine Resultate für die Suchanfrage "{{query}}" gefunden werden".
     },
     transformData: {
         voce: funzione (mio_risultato) {
         //console.log(my_result);
         //console.log(my_result._highlightResult.body_html_safe.value);
         se (my_result["variant_title"] == 'Default Title'){
             my_result["variant_title"] = ";
         }
         else
         {
             my_result["variant_title"] = ' :: ' + my_result["variant_title"];
         }
         //my_result["body_html_safe"] = my_result["body_html_safe"].substring(0,175) + '...';
         //non vogliamo multilinee, vogliamo abbinare la fine REALE della stringa. /m corrisponderebbe alla fine della riga ...
         var pattern_a = /(.*?)(]*)?$/i;
         var pattern_b = /[^<]+$/i;
        
         //prendere il primo gruppo abbinato - che esclude il secondo abbinamento.
         var body_string = my_result._highlightResult.body_html_safe.value.substring(0,175).replace(pattern_a, "$1″);
        
         se (pattern_b.test(body_string)){
             body_string = body_string + "
"
         }
         //ricerca di pi 3 b+
         //identificativo del prodotto https://buyzero.de/products/budget-kit-raspberry-pi-3-model-b?variant=698066665499
         my_result._highlightResult.body_html_safe.value = body_string + '...';
        
         my_result["product_link"] = "https://buyzero.de/products/” + my_result["handle"] + "?variant=" + my_result["id"];
         restituire il mio_risultato;
         }
     }
   })
);

Il contenitore in cui mettere l'output è selezionato come '#aj-search-results', il modello per rendere i risultati è selezionato qui: item: document.getElementById('aj-hit-template').innerHTML.

Presumo che l'abbiano messo in un tag , perché il contenuto non viene reso come HTML dal browser.

Per il vuoto passiamo semplicemente una stringa come template.

Davvero semplice finora, vero?

Poi usiamo transformData per preparare una versione abbreviata del corpo del testo del tuo prodotto e altre variabili passate al modello di hit discusso in precedenza.

Poiché abbiamo introdotto i nell'output della ricerca - usando l'evidenziazione automatica di Algolia - abbiamo bisogno di accorciare il testo in modo sicuro. Ho preparato le mie espressioni regolari per questo, nel mio codice di esempio.

Se c'è una dichiarazione incompleta che inizia con corrispondente), viene tagliata dall'output.

Se c'è un tag senza il corrispondente tag per chiuderlo, lo aggiungiamo.

Il link del prodotto è costruito ottenendo il manico e impostando l'id come variante.

Aggiungere la paginazione

aggiungere altri widget è facile:

// Aggiungere questo dopo le altre chiamate a search.addWidget()
search.addWidget(
   instantsearch.widgets.pagination({
     container: '#aj-search-pagination',
     render: function(my_obj){
         console.log("render");
         console.log(my_obj);
     },
     getConfiguration: function(my_obj){
         console.log("getConfiguration");
         console.log(my_obj);
     }
   })
);

non vuoi l'output del log della console ... Stavo usando questo per il debug, e apparentemente ho dimenticato di toglierlo. Mi dispiace. Sono umano.

Di nuovo, il contenitore di output del widget è impostato. #aj-ricerca-paginazione".

Non hai davvero bisogno di nient'altro per far funzionare la paginazione - imposta il widget e dagli uno stile - sarai a posto.

Sfaccettatura

Con il faceting il tuo utente può raffinare la sua ricerca:

// Sfaccettatura
search.addWidget(
   instantsearch.widgets.refinementList({
     container: '#aj-facet-brand',
     attributeName: 'vendor',
     operatore: 'o',
     limite: 5,
     showMore: vero,
     cssClasses: {
         intestazione: 'aj-refine-header',
         contare: 'aj-refine-count'
     },
     modelli: {
       intestazione: 'Marke / Marca'.
     }
   })
);

  • devi guardare i possibili attributeNames nel tuo backend Algolia - ti mostrerà le sfaccettature disponibili per i tuoi dati (vedi lo screenshot qui sotto).
  • Il limite di 5 non si riferisce ai vostri risultati di ricerca, ma al limite di voci che sono mostrate da Algolia per la vostra lista di raffinamento
  • I raffinamenti disponibili saranno aggiornati automaticamente se gli altri parametri di ricerca vengono modificati (ad esempio, se non c'è corrispondenza per una marca specifica, questa marca non sarà mostrata)
  • showMore: mostrerà un link per mostrare di più nella parte inferiore del widget
  • contare: 'aj-refine-count' - puoi dare un po' di stile ai tuoi risultati di ricerca. Probabilmente più di quello che ho usato qui -. fare riferimento alla documentazione ufficiale

immagine

Widget Sfaccettature chiare

search.addWidget(
   instantsearch.widgets.clearAll({
     container: '#aj-clear-all',
     modelli: {
       link: 'Filter zurücksetzen / Reset'
     },
     autoHideContainer: falso,
     cancellaQuery: vero,
   })
);

usalo per permettere al cliente di cancellare la sfaccettatura (cioè gli verranno mostrati di nuovo tutti i risultati che corrispondono alla sua richiesta).

Non c'è bisogno di configurare oltre a questo.

Non parlerò degli altri widget - date un'occhiata al mio codice se siete interessati.

Legame con la casella di ricerca

Non stiamo usando il widget di ricerca di Algolia, ma ci leghiamo a un evento keyup sul nostro input del modulo di ricerca, come questo:

    var pb = aj_setup_search();
     //#search_query è l'input che vogliamo
     $("#search_query").keyup(function(search) {
       aggiornamentoRicerca(pb);
     });   
}

(abbiamo discusso di aj_setup_search poco fa, è aggiunto qui per mostrarvi da dove viene pb).

Lo facciamo in modo da poter fare ulteriori elaborazioni quando l'evento keyup viene attivato - nascondendo il contenuto che stavamo visualizzando precedentemente nella pagina, e aggiungendo i risultati della ricerca, ecc.

funzione updateSearch(pb){
     var my_query = $("#search_query").val();
     //$(".main-content").html(my_query);
     se (mia_query) {
         $(".main-content").hide();
         $("#megamenu-header-menu2").hide();
         $("#ajr_na").show();
         $("#sc-query").html(my_query);
         $("#aj-search-container").show();
         pb.search.helper.setQuery(my_query);
         //console.log(search_handle.helper.state);
         pb.ihelper.search();
     }
     else {
         $("#aj-search-container").hide();
         $(".main-content").show();
         $("#ajr_na").hide();
         $("#megamenu-header-menu2").show();
     }

}

Usiamo jQuery per ottenere il valore del campo di ricerca. Se non è vuoto, nascondiamo il contenuto principale che stavamo visualizzando prima e mostriamo il contenitore di ricerca.

Impostiamo sc-query per mostrare all'utente che stiamo rispondendo alla sua voce: $("#sc-query").html(my_query);

Infine, i pezzi importanti sono questi qui:

pb.search.helper.setQuery(my_query);
pb.ihelper.search();

come vedete, abbiamo bisogno di usare due diversi helper per impostare la query ed eseguire la ricerca vera e propria. Sì, è così che deve essere fatto - per fortuna ho trovato qualcuno che si lamentava di questo comportamento.

Infine, se la stringa di ricerca è vuota (l'utente ha premuto Escape, o l'ha cancellata, o noi l'abbiamo cancellata, o qualsiasi altra cosa...) nascondiamo la ricerca, e mostriamo il contenuto principale.

Grazie per aver letto

Grazie per l'attenzione, spero che questo aiuti qualcuno che vuole implementare instantsearch.js senza usare il widget di ricerca di Algolia.

Riferimenti

Tampermonkey

Algolia

Bonus