Ajax-filtrering
Teknisk dokumentation for Shoporamas /ajax-endpoint til filtrering af produkter. For udviklere og temadesignere.
Alle Shoporama-shops har et indbygget /ajax-endpoint, der returnerer produkter i JSON-format. Det gør det muligt at bygge dynamisk filtrering, lazy loading og infinite scroll uden at genindlæse siden, så kunden får en hurtig og moderne oplevelse.
Denne artikel er primært skrevet til udviklere og dem, der bygger eller tilpasser deres eget tema. Bruger du Delaware-temaet, har du allerede ajax-filtrering ud af kassen og behøver ikke selv kalde endpointet.
Sådan kalder du endpointet
Et simpelt kald, der henter produkter fra én eller flere kategorier:
fetch('/ajax?categories=123&limit=24')
.then(response => response.json())
.then(products => {
products.forEach(p => console.log(p.name, p.price));
});
Som standard returnerer endpointet et JSON-array med produkter. Vil du også have meta-data og pagination med, tilføjer du include_meta=1 og include_pagination=1. Så får du i stedet et objekt med products, meta og pagination.
Tilgængelige parametre
Flere af parametrene tager pipe-separerede værdier, så du kan filtrere på flere ting på én gang. Fx categories=12|34|56.
| Parameter | Beskrivelse |
|---|---|
| categories | Kategori-ID'er, pipe-separeret. Kombiner evt. med exclude=1 for at ekskludere i stedet |
| force_categories | Som categories, men gennemtvinger kategorierne uden at lade andre filtre indsnævre dem yderligere |
| price_range | Prisinterval som min|max, fx 100|500 |
| attribute_values | ID'er på attributværdier (fx farve, størrelse), pipe-separeret. Tag exclude=1 med for at ekskludere |
| attribute_tags | Filtrer attributværdier via deres tag i stedet for ID, fx red|blue |
| attribute_tags_in_stock | Som attribute_tags, men kun varianter på lager |
| attribute_tag | Filtrer på en hel attribut (ikke en bestemt værdi) ud fra dens tag, fx kun produkter der har attributten "farve" |
| extension[id] | Filtrér på ekstrafelter. id er ekstrafelt-ID'et, og værdien kan være pipe-separeret |
| brands | Brand-ID'er, pipe-separeret |
| suppliers | Leverandør-ID'er, pipe-separeret |
| landing_pages | Landingssides-ID'er, pipe-separeret |
| product_ids | Bestemte produkt-ID'er, pipe-separeret |
| atags | Filtrer efter produkt-tags |
| sort + sort_order | Sortér resultatet. sort_order er asc eller desc (default) |
| limit / offset | Pagination |
| meta | Bestemt meta-felt der skal med på hvert produkt. Brug _all for alle meta-felter, eller pipe-separer flere navne |
| only_in_stock_variants | Returnér kun varianter, der er på lager, i variant_stock-feltet på hvert produkt |
| include_meta | Sæt til 1 for at få attributter, kategorier og brands i resultatet (godt til at bygge filter-UI) |
| include_pagination | Sæt til 1 for at få offset, limit, count og total |
| pretty | Sæt til 1 for pænt formateret JSON (godt til debugging) |
| rebuild | Sæt til 1 for at tvinge en ny generering af cachen for den specifikke URL |
Bemærk: Parametrene category_id, tag, extra_field[..], price_from og price_to findes ikke. Brug i stedet categories, atags, extension[id] og price_range. De forkerte navne giver simpelthen 0 resultater eller bliver ignoreret, ikke en fejlmeddelelse.
Eksempel: Kategori, prisinterval og farve
Hent røde produkter mellem 100 og 500 kr. fra to kategorier, sorteret efter pris stigende:
const params = new URLSearchParams({
categories: '12|34',
price_range: '100|500',
attribute_tags: 'red',
sort: 'price',
sort_order: 'asc',
limit: 24
});
fetch('/ajax?' + params)
.then(r => r.json())
.then(products => renderProducts(products));
Eksempel: Filtrér med ekstrafelt og få meta-data
Ekstrafelter (på engelsk "extension fields") angives med ekstrafeltets ID i klammeparenteser. Du kan finde ID'et under Indstillinger → Udvidede felter i admin. Eksempel hvor ekstrafelt 5 (fx "materiale") skal være enten "bomuld" eller "linned":
// extension[5]=bomuld|linned
fetch('/ajax?categories=12&extension[5]=' + encodeURIComponent('bomuld|linned') + '&include_meta=1&include_pagination=1&limit=24')
.then(r => r.json())
.then(data => {
console.log(data.products);
console.log(data.meta.attributes);
console.log(data.pagination);
});
Felter på hvert produkt i svaret
Hvert produkt i products-arrayet har bl.a. følgende felter:
- product_id, own_id, name, description, list_description
- price, real_price, sale_price, price_dk (dansk formateret)
- stock, attr_stock, variant_stock, stock_string_da
- brand_name, supplier_id, supplier_name, profile_name
- category_ids, category_names
- thumbnail (200x200 fit), thumbnails (array af alle billeder i 200x200), url
- avg_rating, online_since, delivery_time, delivery_time_not_in_stock, approx_shipping
- has_campaigns, campaign_info
- meta_values (kun udfyldt hvis du sender meta=...)
Hvis webshoppen har slået "skjul lager via ajax" til, vil stock, attr_stock og lagermængder i variant_stock være null, så lagertallene ikke lækker offentligt.
Caching
Endpointet caches på serveren i 12 timer pr. unik URL. Svaret sendes også med korrekt Last-Modified- og Expires-headers, så browsere og mellemliggende caches kan returnere et hurtigt 304 Not Modified, hvis indholdet er uændret. Det gør responstider hurtige, men betyder også, at ændringer på et produkt først slår igennem efter cachen udløber. Du kan tvinge en genopbygning af cachen for en bestemt URL ved at tilføje rebuild=1.
Læs mere i artiklen Cache i Shoporama, der gennemgår cache-lagene generelt.
Implementering i dit tema
For at bygge en komplet ajax-filtreret produktliste skal udvikleren typisk:
- Bygge filter-UI med checkboxes eller dropdowns ud fra meta.attributes, meta.brands og meta.categories
- Lytte på ændringer i filtrene og samle dem til en query-string
- Kalde /ajax med de valgte parametre
- Opdatere produktlisten dynamisk og vise pagination ud fra pagination.total
Tip: Læs mere om filtrering generelt i Filtrering på din webshop. Bruger du Delaware-temaet, har du allerede ajax-filtrering ud af kassen.
Ofte stillede spørgsmål
Hvor finder jeg ID'et på et ekstrafelt eller en attributværdi?
I admin under Indstillinger → Udvidede felter for ekstrafelter og under Indstillinger → Profiler for attributværdier. ID'erne vises i listen, eller i URL'en når du redigerer et felt.
Hvorfor får jeg ingen resultater, når jeg bruger category_id=123?
Fordi parameteren ikke findes. Skift til categories=123 (i flertal). Det er en af de mest almindelige fejl, når man bygger ajax-filtrering første gang. Tjek samtidig at du ikke bruger price_from/price_to eller extra_field[..], som heller ikke findes.
Mine ændringer på et produkt slår ikke igennem på /ajax. Hvad gør jeg?
Endpointet caches i 12 timer. Vent, eller hent URL'en med &rebuild=1 for at tvinge en ny generering af netop den URL.
Påvirker mange ajax-kald min hjemmesidehastighed? (Mikkel, udvikler)
Cachen sørger for, at gentagne kald er hurtige. Pas dog på med at lave et nyt kald for hvert eneste tastetryk i et søgefelt. Brug "debounce", så du først kalder, når brugeren holder pause i 200-300 ms. Browseren udnytter også If-Modified-Since, så uændrede svar kommer som 304 og næsten ingen båndbredde bruges.
Får jeg det samme resultat som på kategorisiden?
Stort set. /ajax respekterer de samme regler som ProductFactory bruger på kategorisider, så filtrering, sortering og synlighed (fx skjulte produkter) opfører sig ens.
Kan jeg lave søgning oven på /ajax? (Sofie, nyansat)
/ajax tager ikke en fritekst-søgeparameter. Til søgning skal du bruge Shoporamas dedikerede søge-endpoint i temaet (typisk /search) eller filtrere på product_ids, hvis du selv står for søgningen og blot vil hente data om en kendt liste af produkter.
Hvor mange produkter må jeg hente i ét kald? (Jonas, skala)
Der er ingen hård grænse i koden, men hold dig praktisk under et par hundrede pr. kald for at holde JSON-payloaden lille og responsen hurtig. Brug limit og offset til at sidetælle, eller hent kun næste batch når brugeren scroller.
Bliver mine kunders lagerantal eksponeret offentligt? (Malene, marketing)
Som udgangspunkt indeholder svaret lagerantal. Skal det skjules (så konkurrenter eller robotter ikke kan se hvor meget I har på lager), kan din udvikler aktivere "skjul lager via ajax" på webshoppen, hvorefter stock-felterne sendes som null.
Kan jeg bruge /ajax som et "rigtigt" REST-API? (Mikkel, udvikler)
Nej, det er et offentligt cache-venligt produkt-endpoint til frontend-brug. Skal du oprette, opdatere eller integrere på et dybere niveau, så brug det egentlige REST API i stedet, der kræver en API-nøgle.
Skal jeg være bekymret for, at filtreringen virker forskelligt for kunder i forskellige sprog?
Endpointet kører i samme webshop-kontekst som forsiden, så priser, valuta og synlighed følger den webshop, kaldet rammer. Har du flere webshops eller sprog, så husk at hver webshop har sin egen URL, og dermed sin egen /ajax-cache.
Skal vi hjælpe med at bygge ajax-filtrering ind i dit tema, eller har du tekniske spørgsmål? Skriv til support@shoporama.dk.
Relaterade artiklar
Filtrering i din webbshop
Guide till hur du ställer in filtrering i din Shoporama-webbutik så att kunderna kan filtrera produkter.
Delaware-temaet konfiguration og tilpasning
Komplet guide til at konfigurere Delaware-temaet på din Shoporama-webshop. Footer, megamenu, farver, betalingsikoner, Trustpilot, Instagram-link og...
REST API
Komplett guide till Shoporamas REST API: autentisering, alla slutpunkter, exempel och Swagger-dokumentation.
Importera extra fält på produkter
Guide till import av extra fält via CSV-import av produkter i Shoporama.
Cache i Shoporama
Sådan virker cache i Shoporama. Hvor tit caches bygges, hvornår dine ændringer slår igennem, og hvordan du tvinger en nulstilling.