Algolia en het gebruik van instantsearch.js van uw script voor Shopify
"Goede artiesten kopiëren, grote artiesten stelen." - Steve Jobs
Geïnspireerd door pimoroni.com Ik wilde een soortgelijke zoekopdracht implementeren op onze webshop, buyzero.de ook. buyzero.de wordt momenteel aangedreven door Shopify.
De zoekopdracht toont resultaten terwijl je typt - in de hoofdpagina, dynamisch vervangen van de eerder getoonde inhoud. Erg cool, erg nuttig - en erg, erg snel (dankzij Algolia!)
Aangezien ik moeite had met de beschikbare documentatie over Algolia, en hun onboarding service niet erg behulpzaam was, heb ik zelf dingen moeten uitzoeken, en door uitgebreid te Googlen.
Dit is een samenvatting van mijn ervaring met het implementeren van Algolia. Ik deed het in één dag, in een enkele sessie van ongeveer 12 - 14 uur coderen.
Voorgestelde voorbereiding: injectie van ontwikkelingscode in uw pagina
Ik stel voor om de Google Chrome extensie te gebruiken Tampermonkey voor het injecteren van CSS en Javascript van je lokale harde schijf terwijl je ontwikkelt.
Om dit te doen, moet je bestandstoegang voor Tampermonkey inschakelen. Open:
Klik op Details en schakel "Toegang tot bestands-URL's toestaan" aan
Maak het volgende nieuwe gebruikerscript in Tampermonkey:
// ==UserScript== // @name Algolia-Inject // @namespace https://pi3g.com/ // @versie 0.5 // @description injecteer een lokaal bestand om Algolia te testen! // @auteur Maximilian Batz // @grant 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);
Uitleg:
- moet je getResourceText en addStyle toekennen om het CSS bestand te kunnen openen en injecteren
- noframes voor het niet een tweede keer uitvoeren in de frames die Shopify blijkbaar laadt, en die ook zou overeenkomen met het domein
- include -> zal overeenkomen op buyzero.de. Je zou die regel kunnen veranderen
- bron gebruikt voor het importeren van CSS bestand. Geef het pad ... in Linux kan dat zijn file:///home/whatever/whatever - let op de drievoudige voorwaartse schuine streep
- require - neem je javascript bestand op
- userscript: dit is het userscript om het CSS bestand toe te voegen
De Algolia-code toevoegen
Met het "hoe te ontwikkelen" gedeelte uit de weg, hier is mijn code als voorbeeldcode in een mooi klein ZIP-bestand.
Gelieve niet te kopiëren plakken van deze blog, omdat ik niet zeker ben, of WordPress zal vernietigen de opmaak van de code ... gebruik de .js in het ZIP-bestand om te kopiëren van.
Houd er rekening mee dat de Algolia afhankelijkheden / JavaScript-bestanden al waren geïnstalleerd in ons Shopify-thema - door het installeren van de Algolia Shopify plugin. Ook onze datastore was opgezet, enz. Algolia bood (en biedt nog steeds) al zoekresultaten in een dropdown terwijl u in het zoekvak typt.
Ik zal je door de belangrijke delen van de code leiden:
we starten aj_setup() zodra het document klaar is, om onze nieuwe zoekfunctionaliteit te injecteren.
Merk op dat ik aj gebruik om mijn functies en id's voor dit script te preppen. U mag alles gebruiken wat u wilt, het is niet vereist door Algolia.
De container
in aj_setup() stel ik een nieuwe container in voor de zoekresultaten (het zou waarschijnlijk beter zijn om dit rechtstreeks in je thema-bestand op te nemen - voor het ontwikkelen was dit eenvoudiger).
dit is het HTML-gedeelte van de zoekopdracht
$(".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>Dergelijk resultaat voor: <span id='sc-query'></span></h1>" +
"" +" +
"" +
"" +
"" +
"" +
"
"" +" +
"" +
"" +
"" +
"</DIV" +
"
'</div></div></div></div></div></div></div></div>'
);
- Ik geef het de ID aj-zoek-container, om de volledige resultaten van de zoekcontainer te kunnen tonen/verbergen
- de meeste van de div's, inclusief container zijn nodig voor compatibele styling met ons huidige thema - gebruik waar nodig
- sc-query wordt gebruikt om de zoekopdracht te spiegelen die de gebruiker op dat moment heeft ingevoerd, om te laten zien dat het systeem de resultaten dynamisch namens hem bijwerkt (er is code om dit te doen - lees verder)
- aj-rechts-container bevat filters om de "facetten" van de zoekopdracht te bereiken. De gebruiker kan één of meerdere merken kiezen om te tonen, productcategorieën, en we voegen een prijsfilter toe
- aj-clear-all zal een link bevatten om facetting op te heffen - om alle resultaten terug te geven die overeenkomen met de zoekopdracht van de gebruiker
- aj-links-container bevat de zoekresultaten. aj-stats bevat de statistieken over de zoekopdracht (zoekresultaten + zoektijd), aj-search-results bevat de resultaten, en aj-search-pagination bevat de paginering
Het treffersjabloon
nogmaals, dit zou waarschijnlijk direct in uw pagina gaan in plaats van te worden geïnjecteerd via Javascript.
$(".main-content").before(''+
'+
' <div class="aj-hit">'+
' <div class="aj-hit-image">'+
' <a href="/nl/{{product_link}}/"><img src="{{image}}" alt="{{title}}"></a>'+
' </div>'+
' <div class="aj-hit-content">'+
' <div class="aj-hit-title"><a href="/nl/{{product_link}}/">{{_highlightResult.title.value}}{variant_title}}</a></div>'+
'<p class="aj-hit-description">{{_highlightResult.body_html_safe.value}} <a href="/nl/{{product_link}}/">" mehr</a></p>'+
'<p class="aj-hit-sku"><a href="/nl/{{product_link}}/">{{sku}}</a></p>'+
' <div class="aj-hit-bottominfos">' +
' <div class="aj-hit-price">{{prijs}} €</div>' +
' <div class="aj-hit-stock">{{inventory_quantity}} auf Lager </div>'+
' <div class="aj-hit-link"><a href="/nl/{{product_link}}/">zur Produktseite</a></div>'+
' </div>'+
'</div>'+
' +
'</div>'+
'+
'');Dit sjabloon wordt ingevoegd als "script". Dit is de aanbevolen manier door de Algolia docs.
Het wordt gebruikt om een zoekresultaat, of treffer, weer te geven.
Hier, binnen aj-hit hebben we:
- aj-hit-image, met {{product_link}} en {{image}} als plaatshouders om later de juiste waarden in te voegen
- aj-hit-title, met behulp van {{_highlightResult.title.value}} - Ik link ook in de {{variant_title}} om een volledige titel voor variaties te geven
- aj-hit-beschrijving, om de productbeschrijving weer te geven - {{_highlightResult.body_html_safe.value}}
- aj-hit-prijs voor de {{prijs}} - vergeet niet uw munteenheid toe te voegen (of voeg ze toe door de variabele te wijzigen die aan de template wordt doorgegeven)
- aj-hit-voorraadom te laten zien hoeveel {{inventory_quantity}} we hebben
- aj-hit-link - tenslotte, een link naar de productpagina. {{product_link}}
Dit alles is mooi (IMHO) gestyled met mijn CSS bestand. Styling valt buiten het bestek van deze blogpost, verwijs naar buyzero.de voor wat inspiratie en codeer dan je eigen.
Meer over {{_highlightResult.title.value}}
Variabelen die met drie gekrulde haakjes worden weergegeven, worden door Algolia voor HTML niet geëscaped. Dit wordt hier gebruikt, om de markering mogelijk te maken.
Algolia zal automatisch Tags voor u plaatsen rond de delen van de titel, enz. die overeenkwamen in de _highlightResult variabele. U kunt de in de uitvoer gebruiken, om de gebruiker te laten zien waarom het zoekresultaat relevant wordt geacht voor zijn zoekopdracht.
Ik zal later laten zien hoe je de waarden die aan het sjabloon worden doorgegeven kunt aanpassen, omdat je bijvoorbeeld niet de hele body van je productbeschrijving wilt renderen.
aj_setup_search
var pb = aj_setup_search();
Om het zoeken later te kunnen afhandelen, geven we een variabele terug uit de setup-functie (genaamd var point_both in de setup_search-functie. pb is de afkorting).
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 setupHier stellen we de zoekfunctie in (zoals eerder vermeld, is instantsearch al opgenomen en beschikbaar op de pagina via een ander .js bestand).
Je moet slagen:
- uw appId
- apiKey
- indexNaam
krijgt u deze van uw Algolia-backend. Daar kunt u ook door uw gegevensstructuren bladeren, en zien welke parameters u bijvoorbeeld voor faceting kunt gebruiken.
Het echt belangrijke stuk is de zoekfunctie (my_helper) functie.
Met de helper kunt u de zoekopdracht via uw eigen script aansturen, in plaats van via een zoekbox-widget die is ingesteld met Algolia's instantsearch.
Het is belangrijk om een verwijzing naar deze helper te maken, in deze specifieke functie.
point_both.ihelper = my_helper;
Het later benaderen van de helper vanuit de zoekvariabele zal niet werk.
In feite heb je beide nodig. Zie je deze voorbeeldcode, die ik heb uitgecommentarieerd?
//search.helper.setQuery('Pi 3'); //sic!
//mijn_helper.zoek(); //sic!
sic is het Latijnse woord voor "zoals dit". Dit betekent dat het inderdaad op twee verschillende manieren moet worden benaderd om de query in te stellen en vervolgens de zoekopdracht uit te voeren.
En, jij heb nodig om my_helper.search() hier in te voegen. Dit zal - als ik het me goed herinner - ervoor zorgen dat je widgets de zoekopdracht correct bijwerken ... als je merkt dat je resultaten niet worden bijgewerkt, controleer dan of je het er in hebt staan!
Na het toevoegen van de widgets - die we hieronder zullen bespreken - ronden we de zoek setup af met de volgende code:
search.start();
point_both.search = zoeken;
geef punt_beide terug;Hier voegen we ook een verwijzing naar het zoekobject zelf toe, en geven het terug aan de aj_setup functie.
Merk op dat point_both nu toegang heeft tot het "search" object, en het speciale helper-object "ihelper" dat we verkregen uit de searchFunctie functie.
De eerste widget toevoegen
zullen we het resultaat toevoegen als de eerste widget:
search.addWidget(
instantsearch.widgets.hits({
container: "#aj-zoekresultaten",
sjablonen: {
item: document.getElementById('aj-hit-template').innerHTML,
leeg: "Er zijn waarschijnlijk geen resultaten voor de vragen die beantwoord moeten worden."
},
transformData: {
item: functie (mijn_resultaat) {
//console.log(mijn_resultaat);
//console.log(mijn_result._highlightResult.body_html_safe.value);
indien (my_result["variant_title"] == "Standaardtitel"){
my_result["variant_title"] = ";
}
anders
{
mijn_result["variant_titel"] = ' :: ' + mijn_result["variant_titel"];
}
//my_result["body_html_safe"] = my_result["body_html_safe"].substring(0,175) + '...';
//we willen GEEN multiline, we willen overeenkomen met het ECHTE einde van de string. /m zou overeenkomen met het einde van de regel ..
var pattern_a = /(.*?)(]*)?$/i;
var pattern_b = /[^<]+$/i;
//neem de eerste gematchte groep - die de tweede gematchte groep uitsluit.
var body_string = mijn_result._highlightResult.body_html_safe.value.substring(0,175).replace(pattern_a, "$1″);
indien (pattern_b.test(body_string)){
body_string = body_string + ""
}
//zoek naar pi 3 b+
//product-id https://buyzero.de/products/budget-kit-raspberry-pi-3-model-b?variant=698066665499
mijn_result._highlightResult.body_html_safe.value = body_string + '...';
mijn_resultaat["product_link"] = "https://buyzero.de/products/” + my_result["handle"] + "?variant=" + my_result["id"];
geef mijn_resultaat terug;
}
}
})
);De container om de output in te plaatsen is geselecteerd als '#aj-search-results', het sjabloon om de resultaten te renderen is hier geselecteerd: item: document.getElementById('aj-hit-template').innerHTML.
Ik neem aan dat ze dit in een -tag hebben gezet, omdat de inhoud door de browser niet als HTML wordt weergegeven.
Voor leeg geven we gewoon een string terug als sjabloon.
Echt simpel tot nu toe, toch?
Vervolgens gebruiken we transformData om een verkorte versie voor te bereiden van de tekst van uw product en andere variabelen die zijn doorgegeven aan de eerder besproken hit template.
Omdat we 's in de zoekuitvoer hebben ingevoerd - met behulp van de automatische markering van Algolia - moeten we de tekst op een veilige manier inkorten. Ik heb mijn eigen reguliere expressies hiervoor voorbereid, in mijn voorbeeldcode.
Als er een onvolledige verklaring is die begint met ), wordt deze uit de uitvoer geknipt.
Als er een -tag is zonder overeenkomstige -tag om hem af te sluiten, voegen we die toe.
De product link wordt gemaakt door de handle te verkrijgen, en de id in te stellen als de variant.
Paginering toevoegen
extra widgets toevoegen is eenvoudig:
// Voeg dit toe na de andere search.addWidget() aanroepen
search.addWidget(
instantsearch.widgets.pagination({
container: "#aj-zoek-paginatie",
render: functie(mijn_obj){
console.log("render");
console.log(my_obj);
},
getConfiguration: function(my_obj){
console.log("getConfiguration");
console.log(my_obj);
}
})
);
je wilt de console log output niet ... Ik gebruikte dit om te debuggen, en vergat het er blijkbaar uit te halen. Sorry. Ik ben een mens.
Opnieuw wordt de uitvoercontainer van de widget ingesteld. #aj-zoek-paginatie
Je hebt eigenlijk niets anders nodig om paginering te laten werken - stel de widget in, en stijl hem - je bent goed.
Facetteren
Met faceting kan uw gebruiker zijn zoekopdracht verfijnen:
// Faceting
search.addWidget(
instantsearch.widgets.refinementList({
container: "#aj-facet-brand",
attributeName: "vendor",
operator: "of",
limiet: 5,
showMore: true,
cssClasses: {
header: "aj-refine-header",
count: "aj-refine-count
},
sjablonen: {
koptekst: "Marke / Merk
}
})
);
- moet u kijken naar mogelijke attribuutnamen in uw Algolia-backend - het zal u de beschikbare facetten voor uw gegevens tonen (zie onderstaande schermafbeelding).
- De limiet van 5 verwijst niet naar uw zoekresultaten, maar naar de limiet van inzendingen die door Algolia worden getoond voor uw verfijningsLijst
- De beschikbare verfijningen worden automatisch bijgewerkt als de andere zoekparameters worden gewijzigd (bv. als er geen overeenkomst is voor een specifiek merk, wordt dit merk niet getoond)
- showMore: toont een toon meer link aan de onderkant van de widget
- count: "aj-refine-count" - je kunt je zoekresultaten een beetje stylen. Waarschijnlijk meer dan ik hier nodig had - raadpleeg de officiële documentatie
Duidelijke Facetten widget
search.addWidget(
instantsearch.widgets.clearAll({
container: "#aj-clear-all",
sjablonen: {
link: "Filter zurücksetzen / Terugstellen
},
autoHideContainer: false,
clearsQuery: true,
})
);gebruik dit om de klant in staat te stellen de facetting te wissen (d.w.z. hij krijgt opnieuw alle resultaten te zien die overeenkomen met zijn zoekvraag).
Je hoeft niets te configureren, behalve dit.
Ik zal het niet hebben over de andere widgets - kijk maar eens naar mijn code als je geïnteresseerd bent.
Binding aan het zoekvak
We gebruiken niet de zoekwidget van Algolia, maar binden ons aan een keyup event op de invoer van ons zoekformulier, zoals dit:
var pb = aj_setup_search();
//#search_query is de invoer die we willen
$("#search_query").keyup(function(search) {
updateSearch(pb);
});
}(we bespraken aj_setup_search zojuist, het is hier toegevoegd om te laten zien waar pb vandaan komt).
We doen dit zodat we extra bewerkingen kunnen uitvoeren wanneer de keyup gebeurtenis wordt getriggerd - het verbergen van de inhoud die we eerder op de pagina lieten zien, en het toevoegen van de zoekresultaten, enz.
functie updateSearch(pb){
var mijn_query = $("#search_query").val();
//$(".main-content").html(mijn_query);
indien (mijn_query) {
$(".main-content").hide();
$("#megamenu-header-menu2").hide();
$("#ajr_na").show();
$("#sc-query").html(mijn_query);
$("#aj-search-container").show();
pb.search.helper.setQuery(mijn_query);
//console.log(search_handle.helper.state);
pb.ihelper.search();
}
anders {
$("#aj-search-container").hide();
$(".main-content").show();
$("#ajr_na").hide();
$("#megamenu-header-menu2").show();
}}
We gebruiken jQuery om de waarde van het zoekveld te verkrijgen. Als het niet leeg is, verbergen we de hoofdinhoud die we eerder lieten zien, en tonen we de zoekcontainer.
We stellen sc-query in om de gebruiker te laten zien dat we reageren op zijn invoer: $("#sc-query").html(mijn_query);
Tot slot, de belangrijke stukjes zijn deze hier:
pb.search.helper.setQuery(mijn_query);
pb.ihelper.search();
zoals je ziet, moeten we twee verschillende helpers gebruiken om de query in te stellen en de eigenlijke zoekactie uit te voeren. Ja, zo moet het. Gelukkig vond ik iemand die klaagde over dit gedrag.
Tenslotte, als de zoek string leeg is (de gebruiker drukte op Escape, of verwijderde het, of wij verwijderden het, of wat dan ook ...) verbergen we de zoekopdracht, en tonen de hoofdinhoud.
Dank u voor het lezen.
Dank u voor uw aandacht, ik hoop dat dit iemand helpt die instantsearch.js wil implementeren zonder Algolia's zoekwidget te gebruiken.
Referenties
Tampermonkey
Algolia
- Algolia instantsearch widgets documentatie
- https://community.algolia.com/shopify/instant_search.html
- https://www.algolia.com/doc/tutorials/search-ui/instant-search/build-an-instant-search-results-page/instantsearchjs/
- https://www.algolia.com/doc/guides/searching/highlighting-snippeting
- https://www.algolia.com/doc/guides/search-ui/building-a-search-ui/
- https://community.algolia.com/instantsearch.js/v2/widgets/hits.html#struct-HitsTransforms
- https://stackoverflow.com/questions/42672838/algolia-instantsearch-add-a-callback-after-results-are-displayed
- https://community.algolia.com/algoliasearch-helper-js/gettingstarted.html
- https://github.com/algolia/instantsearch.js/issues/1924
- https://jsfiddle.net/bobylito/bsjdch4m/1/
- https://stackoverflow.com/questions/49638646/algolia-instantsearch-with-multiple-indices-and-multiple-pagination-widgets/49796164?noredirect=1#comment86826994_49796164
- https://github.com/algolia/instantsearch.js/issues/2887
Bonus
- https://discourse.algolia.com/t/how-to-create-facet-widget-from-shopify-metafield/1710
- https://github.com/algolia/awesome-algolia