Algolia und Verwendung von instantsearch.js aus Ihrem Skript für Shopify

"Gute Künstler kopieren, große Künstler stehlen." - Steve Jobs

Inspiriert durch pimoroni.de Ich wollte eine ähnliche Suche in unserem Webshop einführen, buyzero.de auch. buyzero.de wird derzeit von Shopify betrieben.

Die Suche zeigt Ergebnisse an, während Sie tippen - auf der Hauptseite, wobei der zuvor angezeigte Inhalt dynamisch ersetzt wird. Sehr cool, sehr nützlich - und sehr, sehr schnell (dank der Algolia!)

Da ich mit der verfügbaren Dokumentation über Algolia nicht zurechtkam und der Onboarding-Service nicht sehr hilfreich war, musste ich die Dinge selbst herausfinden und ausgiebig googeln.

Dies ist eine Zusammenfassung meiner Erfahrungen mit der Implementierung von Algolia. Ich habe es an einem einzigen Tag gemacht, in einer einzigen Sitzung von etwa 12 - 14 Stunden Programmierung.

Empfohlene Vorbereitung: Einfügen von Entwicklungscode in Ihre Seite

Ich empfehle die Verwendung der Google Chrome-Erweiterung Stampermonkey zum Einfügen von CSS und Javascript von Ihrer lokalen Festplatte, während Sie entwickeln.

Dazu müssen Sie den Dateizugriff für Tampermonkey aktivieren. Öffnen:

chrome://extensions

Klicken Sie auf Details und schalten Sie "Zugriff auf Datei-URLs zulassen" ein

Bild

Bild

Erstellen Sie das folgende neue Benutzerskript in Tampermonkey:

// ==Benutzerskript==
// @Name Algolia-Inject
// @Namensraum https://pi3g.com/
// @Version 0.5
// @Beschreibung Lokale Datei zum Testen von Algolia injizieren!
// @Autor Maximilian Batz
// @Grant GM_getResourceText
// @Grant GM_addStyle
// @noframes
// @include https://buyzero.de/*
// @resource YOUR_CSS file://D:\algolia_jr.css
// @require datei://D:\algolia_jr.js

// ==/UserScript==

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

Erläuterung:

  • Sie müssen getResourceText und addStyle zulassen, um auf die CSS-Datei zugreifen und sie einfügen zu können
  • noframes, um die Frames, die Shopify anscheinend lädt, nicht ein zweites Mal auszuführen, was auch der Domain entsprechen würde
  • include -> wird auf buyzero.de passen. Vielleicht möchten Sie diese Zeile ändern Lächeln
  • Ressource, die für den Import von CSS-Dateien verwendet wird. Geben Sie den Pfad an ... unter Linux könnte er lauten file:///home/whatever/whatever - Beachten Sie den dreifachen Schrägstrich
  • require - fügt Ihre Javascript-Datei ein
  • userscript: Dies ist das Userscript zum Hinzufügen der CSS-Datei

Hinzufügen des Algolia-Codes

Damit ist die Frage, wie man sich entwickelt, vom Tisch, hier ist mein Code als Beispielcode in einer netten kleinen ZIP-Datei.

Bitte kopieren Sie nicht von diesem Blog, da ich nicht sicher bin, ob WordPress die Formatierung des Codes zerstört ... verwenden Sie die .js in der ZIP-Datei zum Kopieren.

Bitte beachten Sie, dass die Algolia-Abhängigkeiten / JavaScript-Dateien bereits in unserem Shopify-Theme installiert wurden - durch die Installation des Algolia-Shopify-Plugins. Auch unser Datenspeicher wurde eingerichtet, etc. Algolia lieferte (und liefert immer noch) bereits Suchergebnisse in einer Dropdown-Liste, während Sie in das Suchfeld eintippten.

Ich werde Sie durch die wichtigsten Teile des Codes führen:

wir starten aj_setup(), sobald das Dokument fertig ist, um unsere neue Suchfunktionalität einzubinden.

Bitte beachten Sie, dass ich aj verwende, um meine Funktionen und IDs für dieses Skript voranzustellen. Sie können verwenden, was Sie wollen, es ist nicht erforderlich für Algolia.

Der Container

in aj_setup() habe ich einen neuen Container für die Suchergebnisse eingerichtet (es wäre wahrscheinlich besser, dies direkt in die Theme-Datei aufzunehmen - für die Entwicklung war dies einfacher).

Dies ist der HTML-Teil der Suche

$(".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>SolcheErgebnisse für: <span id='sc-query'></span></h1>" +
                           "
" +
                             "
" +
                             "
" +
                             "
" +
                             "
" +
                           "
" +
                           "
" +
                               "
" +
                               "
" +
                               "
" +
                           "</DIV" +
                       "
" +
                       '</div></div></div></div></div></div></div></div>'
                       );
  • Ich gebe ihm die ID aj-such-container, die Möglichkeit, die gesamten Ergebnisse des Suchcontainers ein- und auszublenden
  • die meisten der Div's, einschließlich Container sind für die Kompatibilität mit unserem aktuellen Thema erforderlich - verwenden Sie sie nach Bedarf
  • sc-abfrage wird verwendet, um die Suche zu spiegeln, die der Benutzer gerade eingegeben hat, um zu zeigen, dass das System die Ergebnisse in seinem Namen dynamisch aktualisiert (es gibt Code, um dies zu tun - lesen Sie weiter)
  • aj-rechts-container enthält Filter, um die "Facetten" der Suche zu erfassen. Der Nutzer kann eine oder mehrere Marken auswählen, die angezeigt werden sollen, sowie Produktkategorien und einen Preisfilter.
  • aj-clear-all enthält einen Link zum Löschen der Facettierung - um alle Ergebnisse zurückzugeben, die mit der Anfrage des Nutzers übereinstimmen
  • aj-left-container enthält die Suchergebnisse. aj-stats enthält Statistiken über die Suche (Suchergebnisse + Suchzeit), aj-search-results enthält die Ergebnisse, und aj-search-pagination enthält die Paginierung

Die Treffervorlage

wieder, würde dies wahrscheinlich direkt in Ihre Seite gehen, anstatt über Javascript injiziert werden.

    $(".main-content").before(''+
       '+
'          <div class="aj-hit">'+
'            <div class="aj-hit-image">'+
'              <a href="/de/{{product_link}}/"><img src="{{image}}" alt="{{Titel}}"></a>'+
'            </div>'+
'            <div class="aj-hit-content">'+
'              <div class="aj-hit-title"><a href="/de/{{product_link}}/">{{{_highlightResult.title.value}}}{{variant_title}}</a></div>'+
               '<p class="aj-hit-description">{{_highlightResult.body_html_safe.value}} &nbsp; <a href="/de/{{product_link}}/">" mehr</a></p>'+
               '<p class="aj-hit-sku"><a href="/de/{{product_link}}/">{{sku}}</a></p>'+
'              <div class="aj-hit-bottominfos">' +
'                <div class="aj-hit-price">{{Preis}} €</div>' +
'                <div class="aj-hit-stock">{{inventory_quantity}} auf Lager </div>'+
'                <div  class="aj-hit-link"><a href="/de/{{product_link}}/">zur Produktseite</a></div>'+
'             </div>'+
             '</div>'+
            
' +
           '</div>'+
         '+
     '');

Diese Vorlage wird als "Skript" eingefügt. Dies ist der empfohlene Weg in den Algolia-Dokumenten.

Sie wird verwendet, um ein Suchergebnis oder einen Treffer darzustellen.

Hier, im Inneren aj-hit haben wir:

  • aj-hit-image, mit {{product_link}} und {{image}} als Platzhalter, um später die richtigen Werte einzufügen
  • aj-hit-title, unter Verwendung von {{_highlightResult.title.value}}} - ich verlinke auch in den {{variant_title}}, um einen vollständigen Titel für Variationen bereitzustellen
  • aj-hit-description, um die Produktbeschreibung darzustellen - {{_highlightResult.body_html_safe.value}}
  • aj-hit-price für den {{Preis}} - Vergessen Sie nicht, Ihre Währung hinzuzufügen (oder fügen Sie sie hinzu, indem Sie die an die Vorlage übergebene Variable ändern)
  • aj-hit-stock, um zu zeigen, wie viel {{Bestandsmenge}} wir haben
  • aj-hit-link - schließlich einen Link zur Produktseite. {{product_link}}

All dies ist (IMHO) mit meiner CSS-Datei schön gestaltet. Styling ist außerhalb des Rahmens dieses Blogposts, siehe buyzero.de um sich inspirieren zu lassen und dann Ihren eigenen Code zu erstellen.

Mehr zu {{_highlightResult.title.value}}

Variablen, die mit drei geschweiften Klammern dargestellt werden, werden von Algolia for HTML nicht escaped. Dies wird hier verwendet, um die Hervorhebung zu ermöglichen.

Algolia setzt automatisch Tags um die Teile des Titels usw., die in der _highlightResult Variable. Sie können die in der Ausgabe verwenden, um dem Nutzer zu zeigen, warum das Suchergebnis als relevant für seine Suche angesehen wird.

Später zeige ich Ihnen, wie Sie die Werte, die an die Vorlage übergeben werden, ändern können, da Sie z. B. nicht den gesamten Textkörper Ihrer Produktbeschreibung wiedergeben möchten.

aj_setup_search

var pb = aj_setup_search();

Für die spätere Suche geben wir eine Variable aus der Setup-Funktion zurück (var point_both innerhalb der setup_search-Funktion. pb ist ihre Abkürzung).

	
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

Hier richten wir die Suche ein (wie bereits erwähnt, ist instantsearch bereits enthalten und über eine andere .js-Datei auf der Seite verfügbar).

Sie müssen bestehen:

  • Ihre appId
  • apiKey
  • indexName

erhalten Sie diese von Ihrem Algolia-Backend. Dort können Sie auch Ihre Datenstrukturen durchsuchen und sehen, welche Parameter Sie z. B. für Facetten verwenden können.

Der wirklich wichtige Teil ist die Funktion searchFunction (my_helper).

Der Helper ermöglicht es Ihnen, die Suche über Ihr eigenes Skript zu steuern, anstatt sie über ein Suchfeld-Widget auszulösen, das mit Algolia's instantsearch eingerichtet ist.

Es ist wichtig, in dieser speziellen Funktion einen Verweis auf diese Hilfsfunktion zu erstellen.

point_both.ihelper = my_helper;

Der spätere Zugriff auf das Hilfsmittel über die Suchvariable wird nicht Arbeit.

Tatsächlich brauchen Sie beides. Sehen Sie diesen Beispielcode, den ich auskommentiert habe?

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

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

sic ist das lateinische Wort für "so". Das heißt, es muss in der Tat auf zwei verschiedene Arten zugegriffen werden, um die Abfrage festzulegen und dann die Suche auszuführen.

Außerdem können Sie brauchen um my_helper.search() hier hinzuzufügen. Dies wird - soweit ich mich erinnere - Ihren Widgets erlauben, die Suche korrekt zu aktualisieren ... wenn Sie feststellen, dass Ihre Ergebnisse nicht aktualisiert werden, überprüfen Sie, ob Sie es dort haben!

Nach dem Hinzufügen der Widgets - die wir weiter unten besprechen werden - schließen wir die Sucheinrichtung mit dem folgenden Code ab:

search.start();
point_both.search = Suche;
return point_both;

Hier fügen wir auch einen Verweis auf das Suchobjekt selbst hinzu und geben es an die Funktion aj_setup zurück.

Beachten Sie, dass point_both nun Zugriff auf das Objekt "search" und das spezielle Hilfsobjekt "ihelper" hat, das wir aus der Funktion searchFunction erhalten haben.

Hinzufügen des ersten Widgets

fügen wir das Ergebnis als erstes Widget hinzu:

search.addWidget(
   instantsearch.widgets.hits({
     Container: "#aj-Suchergebnisse",
     Vorlagen: {
       item: document.getElementById('aj-hit-template').innerHTML,
       leer: "Es konnten leider keine Ergebnisse für die Suchanfrage \"{{query}}" gefunden werden."
     },
     transformData: {
         item: function (my_result) {
         //console.log(my_result);
         //console.log(mein_Ergebnis._highlightResult.body_html_safe.value);
         if (my_result["variant_title"] == 'Standardtitel'){
             my_result["variant_title"] = ";
         }
         sonst
         {
             mein_Ergebnis["variant_title"] = ' :: ' + mein_Ergebnis["variant_title"];
         }
         //mein_Ergebnis["body_html_safe"] = mein_Ergebnis["body_html_safe"].substring(0,175) + '...';
         //Wir wollen NICHT mehrzeilig sein, sondern das ECHTE Ende der Zeichenkette abgleichen. /m würde am Zeilenende übereinstimmen ..
         var pattern_a = /(.*?)(]*)?$/i;
         var pattern_b = /[^<]+$/i;
        
         //nimm die erste übereinstimmende Gruppe - die die zweite Übereinstimmung ausschließt.
         var body_string = my_result._highlightResult.body_html_safe.value.substring(0,175).replace(pattern_a, "$1″);
        
         if (muster_b.test(body_string)){
             body_string = body_string + "
"
         }
         //Suche nach pi 3 b+
         //Produkt-ID 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"];
         return my_result;
         }
     }
   })
);

Der Container, in den die Ausgabe gestellt werden soll, wird als "#aj-search-results" ausgewählt, die Vorlage zum Rendern der Ergebnisse wird hier ausgewählt: item: document.getElementById('aj-hit-template').innerHTML.

Ich nehme an, dass sie dies in einem -Tag unterbringen, weil der Inhalt vom Browser nicht als HTML gerendert wird.

Bei leeren Dateien wird einfach eine Zeichenkette als Vorlage zurückgegeben.

So weit so einfach, oder?

Als nächstes verwenden wir transformData um eine gekürzte Version des Textkörpers Ihres Produkts und anderer Variablen vorzubereiten, die an die zuvor besprochene Treffervorlage übergeben werden.

Da wir 's in die Suchausgabe eingefügt haben - unter Verwendung der automatischen Hervorhebung von Algolia - müssen wir den Text auf eine sichere Weise kürzen. Dafür habe ich in meinem Beispielcode meine eigenen regulären Ausdrücke vorbereitet.

Befindet sich nach der Verkürzung eine unvollständige Anweisung, die mit ), wird sie aus der Ausgabe entfernt.

Wenn ein -Tag ohne entsprechendes -Tag zum Abschluss vorhanden ist, wird es hinzugefügt.

Die Produktverknüpfung wird unter Verwendung des Handles erstellt, wobei die id als Variante festgelegt wird.

Hinzufügen einer Paginierung

Das Hinzufügen zusätzlicher Widgets ist einfach:

// Fügen Sie dies nach den anderen Aufrufen von search.addWidget() hinzu
search.addWidget(
   instantsearch.widgets.pagination({
     Container: "#aj-Suche-Pagination",
     render: function(my_obj){
         console.log("render");
         console.log(my_obj);
     },
     getConfiguration: function(my_obj){
         console.log("getConfiguration");
         console.log(my_obj);
     }
   })
);

Sie wollen die Konsolenprotokollausgabe nicht ... Ich habe das zum Debuggen verwendet und offenbar vergessen, es herauszunehmen. Tut mir leid. Ich bin ein Mensch.

Auch hier wird der Ausgabecontainer des Widgets festgelegt. #aj-Suche-Pagination'

Sie brauchen nicht wirklich etwas anderes für die Paginierung zu arbeiten - richten Sie das Widget, und Stil es - Sie werden gut sein.

Facettierung

Mit der Facettierung kann Ihr Nutzer seine Suche verfeinern:

// Facettierung
search.addWidget(
   instantsearch.widgets.refinementList({
     Container: "#aj-Facette-Marke",
     AttributName: 'Verkäufer',
     Operator: 'oder',
     Grenze: 5,
     showMore: wahr,
     cssClasses: {
         Kopfzeile: 'aj-refine-header',
         zählen: 'aj-refine-count'
     },
     Vorlagen: {
       Überschrift: 'Marke / Brand'
     }
   })
);

  • müssen Sie sich die möglichen Attributnamen in Ihrem Algolia-Backend ansehen - dort werden Ihnen die verfügbaren Facetten für Ihre Daten angezeigt (siehe Screenshot unten).
  • Das Limit von 5 bezieht sich nicht auf Ihre Suchergebnisse, sondern auf die Anzahl der Einträge, die Algolia für Ihre refinementList anzeigt
  • Die verfügbaren Verfeinerungen werden automatisch aktualisiert, wenn die anderen Suchparameter geändert werden (z.B. wenn es keine Übereinstimmung für eine bestimmte Marke gibt, wird diese Marke nicht angezeigt)
  • showMore: zeigt einen "show more"-Link am unteren Rand des Widgets an
  • zählen: 'aj-refine-count' - Sie können Ihre Suchergebnisse ein wenig gestalten. Wahrscheinlich mehr als ich hier gebraucht habe - siehe die offizielle Dokumentation

Bild

Widget "Facetten löschen

search.addWidget(
   instantsearch.widgets.clearAll({
     Container: "#aj-clear-all",
     Vorlagen: {
       Link: 'Filter zurücksetzen / Reset'
     },
     autoHideContainer: false,
     clearsQuery: true,
   })
);

Verwenden Sie dies, um dem Kunden die Möglichkeit zu geben, die Facettierung zu löschen (d.h. ihm werden wieder alle Ergebnisse angezeigt, die zu seiner Anfrage passen).

Darüber hinaus sind keine weiteren Konfigurationen erforderlich.

Ich werde nicht über die anderen Widgets sprechen - schauen Sie sich meinen Code an, wenn Sie daran interessiert sind.

Bindung an das Suchfeld

Wir verwenden nicht das Such-Widget von Algolia, sondern binden uns an ein Keyup-Ereignis auf unserer Sucheingabe, etwa so:

    var pb = aj_setup_search();
     //#search_query ist die gewünschte Eingabe
     $("#search_query").keyup(function(search) {
       updateSearch(pb);
     });   
}

(wir haben gerade über aj_setup_search gesprochen, es wurde hier hinzugefügt, um Ihnen zu zeigen, woher pb kommt).

So können wir zusätzliche Verarbeitungsschritte durchführen, wenn das Keyup-Ereignis ausgelöst wird, d. h. wir blenden den Inhalt aus, der zuvor auf der Seite angezeigt wurde, und fügen die Suchergebnisse hinzu usw.

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

}

Wir verwenden jQuery, um den Wert des Suchfeldes zu ermitteln. Wenn es nicht leer ist, blenden wir den Hauptinhalt aus, den wir vorher angezeigt haben, und zeigen den Suchcontainer.

Wir setzen sc-query, um dem Benutzer zu zeigen, dass wir auf seine Eingabe reagieren: $("#sc-query").html(my_query);

Die wichtigsten Punkte sind diese hier:

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

wie Sie sehen, müssen wir zwei verschiedene Hilfsprogramme verwenden, um die Abfrage festzulegen und die eigentliche Suche durchzuführen. Ja, so muss es gemacht werden - zum Glück habe ich jemanden gefunden, der sich über dieses Verhalten beschwert.

Wenn der Suchstring leer ist (der Benutzer hat Escape gedrückt oder ihn gelöscht oder wir haben ihn gelöscht oder was auch immer ...), blenden wir die Suche aus und zeigen den Hauptinhalt an.

Vielen Dank für die Lektüre

Vielen Dank für Ihre Aufmerksamkeit, ich hoffe, das hilft jemandem, der instantsearch.js ohne Algolias Such-Widget implementieren möchte.

Referenzen

Stampermonkey

Algolia

Bonus