Adresse-autocomplete i Shopify
Shopify har en understøttet indgang til præcis det her: Address Autocomplete API'en lader dig udskifte udbyderen af adresseforslag i checkout. Peger du den mod DAR, får dine kunder rigtige danske adresser i stedet for et generisk internationalt opslag.
- Kunden skriver i adressefeltetShopify kalder dit suggest-target, som spørger din app-backend.
- Højst fem forslag fra DARHvert forslag har formattedAddress med, så Shopify kan udfylde felterne direkte.
- Postnummer og by udfyldesUden format-suggestion-targetet og uden et ekstra opslag.
Læs det her først: checkout UI extensions kræver Shopify Plus. Er du ikke på Plus, kan adresseforslagene i selve checkout ikke skiftes ud — checkout.liquid er udfaset, og vilkårlige scripts i checkout er ikke længere mulige. Du kan stadig bruge adresseopslaget andre steder i butikken og vaske de adresser, der allerede er kommet ind; se nederst.
Opsætning — og den ene linje, der vælter det
Checkout UI extensions er sandkassede. Glemmer du network_access, må extensionen ikke kalde ud, og opslaget fejler tavst — uden at der er noget galt med koden. Det er værd at sætte rigtigt fra start.
# shopify.extension.toml # api_version sættes af Shopify CLI, når den scaffolder extensionen — # brug den, den genererer, frem for at kopiere en fast værdi ind. api_version = "2025-10" [[extensions]] type = "ui_extension" name = "grundfast-adresse" handle = "grundfast-adresse" [[extensions.targeting]] target = "purchase.address-autocomplete.suggest" module = "./src/suggest.js" # UDEN denne må extensionen ikke lave netværkskald, og opslaget fejler. [extensions.capabilities] network_access = true
1. Forslag mens kunden skriver
Slå kun op, når det giver mening: dansk landekode, adressefeltet, og mindst to tegn. Kaldet går gennem din egen app-backend, så nøglen ikke ligger i noget, der kører hos kunden. Shopify viser højst fem forslag. Felterne i svaret står i API-referencen.
// src/suggest.js — target: purchase.address-autocomplete.suggest // Ingen import og ingen wrapper: det er en almindelig default async // funktion, og inputtet ligger på den globale 'shopify'. export default async () => { const { field, value, selectedCountryCode } = shopify.target; // Kun danske adresser giver mening at slå op mod DAR. if (selectedCountryCode !== 'DK' || field !== 'address1' || value.length < 2) { return { suggestions: [] }; } // Dit eget app-endpoint — nøglen bliver på din server, ikke i extensionen. // shopify.signal afbryder kaldet, når kunden skriver videre. const res = await fetch( 'https://din-app.example.com/adresse?q=' + encodeURIComponent(value), { signal: shopify.signal } ); if (!res.ok) return { suggestions: [] }; const { results } = await res.json(); // Shopify viser HØJST fem forslag. return { suggestions: results.slice(0, 5).map((r) => ({ id: r.adgangsadresse_id, label: r.betegnelse, // Ingen delstrenge at fremhæve — vi rangerer serverside. matchedSubstrings: [], // Fordi /v1/adresse/search allerede gav os de strukturerede felter, // kan vi levere den færdige adresse med det samme. Shopify udfylder // formularen med den, når kunden vælger forslaget. formattedAddress: { address1: [r.vejnavn, r.husnr].filter(Boolean).join(' '), address2: '', city: r.postnrnavn ?? '', zip: r.postnr ?? '', provinceCode: '', countryCode: 'DK', }, })), }; };
2. Endpointet i din app-backend
Her ligger den hemmelige nøgle. Shopify skriver, at extensionen kører i en Web Worker, hvis origin kan ændre sig uden varsel, og at et endpoint, den kalder, skal svare med Access-Control-Allow-Origin: *. Det er også grunden til, at en offentlig nøgle ikke hører hjemme i extensionen: den er låst til domæner, og her er der ikke noget fast domæne at låse den til.
// Fx en route i din Shopify-app (Remix/React Router) eller en edge-funktion. // Web-standard Request/Response, så den passer de fleste runtimes. export async function adresse(request) { const cors = { 'Access-Control-Allow-Origin': '*' }; const q = new URL(request.url).searchParams.get('q')?.trim() ?? ''; if (q.length < 2) return Response.json({ results: [] }, { headers: cors }); const res = await fetch( 'https://api.grundfast.dk/v1/adresse/search?per_side=5&q=' + encodeURIComponent(q), { headers: { Authorization: 'Bearer ' + process.env.GRUNDFAST_API_KEY } } ); // En fejl hos os må aldrig blokere checkout — svar tomt i stedet. if (!res.ok) return Response.json({ results: [] }, { headers: cors }); return Response.json(await res.json(), { headers: cors }); }
3. Det andet target, du formentlig ikke skal bruge
format-suggestion findes, fordi mange adresse-udbydere først kan levere den fulde adresse, når kunden har valgt — så koster valget et opslag mere. Sådan er det ikke her: fordi /v1/adresse/search allerede gav vejnavn, husnummer, postnummer og by i søgesvaret, sender du formattedAddress med hvert forslag, og Shopify udfylder formularen med den ved valget. Tag kun targetet med, hvis du af andre grunde vil slå op igen.
// src/format-suggestion.js — target: // purchase.address-autocomplete.format-suggestion // // Dette target er til udbydere, der FØRST kan levere den fulde adresse, // når kunden har valgt. Det behøver du ikke her: formattedAddress fulgte // allerede med forslaget ovenfor. Tag kun targetet med, hvis du af andre // grunde vil slå op igen ved valget. export default async () => { const { selectedSuggestion } = shopify.target; return { formattedAddress: selectedSuggestion.formattedAddress }; };
Adressefeltet i temaets egne formularer
Uden for checkout er temaet almindelig HTML på dit eget domæne. Dér virker adressefeltet med en offentlig nøgle (gf_pub_live_) uden nogen app: opret nøglen under Nøgler i dashboardet med butikkens domæner, fx din-butik.dk og din-butik.myshopify.com, og indsæt tagget under Online Store → Themes → Edit code i layout/theme.liquid. Selektorerne er eksempler — find dine egne felters id med browserens inspektør. Det gælder også for butikker, der ikke er på Plus.
{%- comment -%} layout/theme.liquid, lige før </body> {%- endcomment -%} <script src="https://grundfast.dk/widget/v1/grundfast-adresse.js" defer data-key="gf_pub_live_..." data-felt="#ContactForm-adresse" data-postnr="#ContactForm-postnr" data-by="#ContactForm-by" ></script>
Er du ikke på Plus
Så er checkout lukket land, og det skal siges rent ud frem for at sælge dig en løsning, der ikke kan installeres. To ting virker stadig, og de er ikke ingenting: adressefeltet i de formularer, du selv styrer i temaet (afsnittet ovenfor) — og datavask af de adresser, der allerede er kommet ind, med rangerede kandidater og konfidensbånd.
Spørgsmål
Ofte stillede spørgsmål
Nej. Checkout UI extensions — og dermed Address Autocomplete API’en — er forbeholdt Shopify Plus. Er du ikke på Plus, kan du ikke ændre adresseforslagene i selve checkout. Du kan stadig bruge Grundfast andre steder i butikken, fx i et adressefelt på en kundeprofil-side, i en formular i temaet eller i din backoffice — og du kan vaske de adresser, der allerede er kommet ind.
Ikke længere. checkout.liquid er udfaset, og Shopify-checkout kan ikke ændres med vilkårlige scripts. Address Autocomplete API’en findes netop for at give en understøttet indgang til at udskifte udbyderen af adresseforslag — brug den frem for at lede efter en vej udenom.
Nej, i praksis kun suggest. De to targets findes, fordi mange adresse-udbydere først kan levere den fulde adresse, når kunden har valgt et forslag — så henter format-suggestion den i et opslag mere. Vores /v1/adresse/search returnerer vejnavn, husnummer, postnummer og by allerede i søgesvaret, så du kan sende formattedAddress med hvert forslag. Shopify udfylder formularen med den ved valget, og andet opslag er overflødigt.
Sandsynligvis fordi extensionen ikke har fået lov til at gå på nettet. Checkout UI extensions er sandkassede, og netværkskald kræver network_access = true under [extensions.capabilities] i shopify.extension.toml. Uden den fejler opslaget, uden at der er noget galt med din kode.
Nej, ikke med god samvittighed. En offentlig nøgle virker kun fra de domæner, du skriver på den, men Shopify skriver selv, at extensionen kører i en Web Worker, hvis origin kan ændre sig uden varsel — og den er ikke din butiks domæne. Der er altså ikke noget at låse nøglen til. Lad extensionen kalde din app-backend, og hold en hemmelig nøgle dér.
I temaet: kontaktformularer, B2B-ansøgninger og andre formularer, du selv har i theme.liquid eller i en sektion. Dér er siden på dit eget domæne, og en offentlig nøgle med det domæne virker. Selve checkout styres kun gennem extensionen.
Vask dem mod DAR med /v1/datavask/adgangsadresser. Du får rangerede kandidater med A/B/C-konfidensbånd og bfe_nummer, så det sikre kan rettes automatisk og resten sendes til gennemsyn. Det virker uanset hvilken Shopify-plan du er på.
Se også
Test extensionen mod rigtige danske adresser
Gratis op til 5.000 kald/md · intet kreditkort · data fra Klimadatastyrelsen/Datafordeler, CC BY 4.0