Opdater pris og sammenligningspris automatisk, når leverandørprisen ændrer sig
September 3, 2026
Din leverandør hæver prisen på en variant fra 4,00 til 5,20. Intet i Shopify reagerer på det. Salgsprisen forbliver uændret, og den margin, du havde planlagt, forsvinder stille og roligt, indtil nogen opdager det under en lageropgørelse nogle uger senere.
Shopify Flow Det kan ikke løse problemet på egen hånd her, fordi Shopify ikke har nogen indbygget udløser for en ændring af prisen pr. vare. Der er heller ingen handling, der genberegner prisen ud fra denne værdi.
Denne vejledning løser begge problemer. Når prisen pr. vare ændres for en hvilken som helst variant, startes der et Flow, og en kort funktion skriver den nye pris og sammenligningsprisen tilbage til Shopify. Det tager cirka ti minutter at sætte op, og derefter kører det ved hver prisændring - for altid.
Hvad du skal bygge
- Workflow Trigger Extensions registrerer ændringen i prisen og starter et Flow, der indeholder varianten, dens SKU samt både den gamle og den nye pris.
- Shopify Flow overfører disse værdier til en funktion som JSON.
- Workflow Functions kører et par linjer JavaScript, der beregner de nye priser og sender dem tilbage via Admin API’et.
Prisreglen findes ét sted, nemlig i den kode, du selv styrer, så hvis du senere vil ændre den, behøver du blot at redigere én linje i stedet for at genopbygge en hel arbejdsgang.
Trin 1: Aktivér omkostningstriggeren
I »Workflow Trigger Extensions« skal du åbne siden »Triggers«, finde gruppen »Inventory« og aktivere »Product Variant Cost Changed«.
Denne trigger kræver adgang til lagerdata, da enhedsprisen er knyttet til lagerartiklen og ikke til selve varianten. Hvis tilladelsen endnu ikke er tildelt, vil der blive bedt om den i en enkelt dialogboks, når triggeren aktiveres. Indtil tilladelsen er tildelt, forbliver triggeren aktiveret, men der vises en markering om, at der kræves tilladelse, og den udløses ikke.
Hvad udløseren giver dig
Når den udløses, har din Flow adgang til:
| Felt | Eksempel |
|---|---|
variantCostChange.variantId |
gid://shopify/ProductVariant/54589751394579 |
variantCostChange.variantTitle |
Medium / Black |
variantCostChange.sku |
TSHIRT-M-BLK |
variantCostChange.oldCost.amount |
4.00 |
variantCostChange.newCost.amount |
5.20 |
variantCostChange.newCost.currencyCode |
EUR |
Selve produktet er også medtaget som produktreference, så du kan tilføje Flow-betingelser baseret på leverandør, type, tags eller samling, inden prisen overhovedet berøres.
Trin 2: Opret funktionen
I filen »Workflow Functions« skal du oprette en ny funktion og indsætte nedenstående kode.
Inden du gemmer, skal du aktivere »Behov for Shopify-data«. Det er det, der giver din kode adgang til ctx.shopify.graphql(...), så den kan læse og ændre butiksdata. Åbn derefter siden »Tilladelser« på Workflow Functions og tildel skriveadgang til produkter, hvilket er det omfang, denne funktion har brug for for at kunne ændre en pris.
Uden denne indstilling er objektet ctx.shopify ikke tilgængeligt, og funktionen mislykkes ved det første Admin API-kald.
export default async function (input, ctx) {
const toGid = (value, type) => {
if (value === undefined || value === null) return null;
const str = String(value).trim();
if (!str) return null;
if (str.startsWith('gid://')) return str;
if (/^\d+$/.test(str)) return `gid://shopify/${type}/${str}`;
return str;
};
try {
const variantId = toGid(input.variantId || input.variant_id || input.id, 'ProductVariant');
if (!variantId) throw new Error('Missing "variantId" in input.');
const hasPrice = input.price !== undefined && input.price !== null && String(input.price).trim() !== '';
const hasCompareAt = Object.prototype.hasOwnProperty.call(input, 'compareAtPrice') || Object.prototype.hasOwnProperty.call(input, 'compare_at_price');
const rawCompareAt = input.compareAtPrice !== undefined ? input.compareAtPrice : input.compare_at_price;
if (!hasPrice && !hasCompareAt) throw new Error('Nothing to update: provide "price" and/or "compareAtPrice".');
const asMoney = (value) => {
const num = Number(value);
if (!Number.isFinite(num) || num < 0) throw new Error(`Invalid money value: ${JSON.stringify(value)}`);
return num.toFixed(2);
};
let productId = toGid(input.productId || input.product_id, 'Product');
if (!productId) {
const readQuery = `
query VariantForPriceUpdate($id: ID!) {
productVariant(id: $id) { id product { id } }
}`;
const readRes = await ctx.shopify.graphql(readQuery, { id: variantId });
if (readRes.errors) throw new Error('Failed to read variant: ' + JSON.stringify(readRes.errors));
const variant = readRes.data && readRes.data.productVariant;
if (!variant) throw new Error(`Variant not found: ${variantId}`);
productId = variant.product && variant.product.id;
if (!productId) throw new Error('Could not resolve the parent product id for the variant.');
}
const variantInput = { id: variantId };
if (hasPrice) variantInput.price = asMoney(input.price);
if (hasCompareAt) {
variantInput.compareAtPrice = rawCompareAt === null || String(rawCompareAt).trim() === '' ? null : asMoney(rawCompareAt);
}
ctx.log('Updating variant', variantId, 'on product', productId, variantInput);
const mutation = `
mutation UpdateVariantPrice($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {
productVariantsBulkUpdate(productId: $productId, variants: $variants) {
productVariants { id }
userErrors { field message }
}
}`;
const res = await ctx.shopify.graphql(mutation, { productId, variants: [variantInput] });
if (res.errors) throw new Error('GraphQL error updating variant: ' + JSON.stringify(res.errors));
const payload = res.data && res.data.productVariantsBulkUpdate;
if (!payload) throw new Error('Unexpected empty response from productVariantsBulkUpdate.');
if (payload.userErrors && payload.userErrors.length) {
throw new Error('Variant update failed: ' + payload.userErrors.map(e => `${(e.field || []).join('.')}: ${e.message}`).join('; '));
}
return { success: true };
} catch (err) {
ctx.log('Error updating variant price:', err.message);
return { success: false };
}
}Et par ting, der er værd at bemærke ved koden:
- Den accepterer enten et simpelt numerisk id eller et fuldt GID.
toGidnormaliserer begge dele, så du behøver ikke bekymre dig om, hvilken form Flow leverer. - Den søger kun efter overordnede produkter, når det er nødvendigt. Funktionen »
productVariantsBulkUpdate« kræver et produkt-id; hvis du ikke angiver et, henter funktionen det selv. Ved at angive »productId« i indgangen undgår man denne frem- og tilbagegang. - Den kontrollerer
userErrors, ikke blot transportfejl. Et GraphQL-kald kan returnere en HTTP 200-status og alligevel afvise skrivningen. Dette er den mest almindelige årsag til, at en prisopdatering ser ud til at lykkes, men der ikke sker nogen ændringer. - Sletning af »compare-at« er tilsigtet. Hvis man overfører »
compareAtPrice: null« eller en tom streng, fjernes den, i stedet for at det betragtes som en fejl.
Trin 3: Test funktionen, før du tilslutter den
Brug fanen »Test« med et rigtigt variant-id fra din butik. Vælg et fra en vilkårlig produkt-URL i adminpanelet eller fra triggerens hændelseshistorik.
Indstil en pris, du genkender, så du kan bekræfte, at beskeden er modtaget.
{
"variantId": "gid://shopify/ProductVariant/54589751394579",
"price": "24.99",
"compareAtPrice": "39.99"
}Trin 4: Tilslut Flow
Opret en arbejdsgang i Shopify Flow:
- Udløser: Ændring i pris på produktvariant
- Handling: Kør funktion fra »Workflow Functions«, og vælg den funktion, du netop har oprettet
Indsæt dette i JSON-indtastningsfeltet. Flow erstatter Liquid-koden med reelle værdier, hver gang det kører.
{
"variantId": "{{variantCostChange.variantId}}",
"price": "{{variantCostChange.newCost.amount | times: 5}}",
"compareAtPrice": "{{variantCostChange.newCost.amount | times: 7}}"
}Det er hele prisreglen: fem gange kostprisen som salgspris, syv gange kostprisen som sammenligningspris, så produktet altid vises med en ensartet rabat.
Disse multiplikatorer er blot et eksempel, ikke en anbefaling. Erstat times: 5 med det tal, som din kategori rent faktisk understøtter. Liquid tager sig af beregningerne, så et fast påslag i stedet for en multiplikator er plus: 12, og en procentuel margin er times: 1.6.
Hvis du sælger i flere valutaer, skal du være opmærksom på, at newCost.amount er angivet i butikkens valuta. Markets tager sig af valutaomregningen, når siden vises, så du behøver ikke selv at gøre det.
Bekræft, at det fungerer fra start til slut
- Åbn en vilkårlig produktvariant i Shopify-administrationspanelet, og rediger prisen pr. enhed
- Gem
- Inden for få sekunder opdateres prisen og sammenligningsprisen automatisk
Hvis der ikke sker noget, skal du følge vejledningen i denne rækkefølge, da hvert trin udelukker det foregående:
| Tjek | Hvor |
|---|---|
| Gik aftrækkeren af? | Begivenhedshistorik i »Workflow Trigger Extensions« |
| Kørte Flow? | Shopify Flow aktivitetslog |
| Kørte funktionen, og hvad blev der logget? | Kørselshistorik i Workflow Functions |
Den mest almindelige årsag til, at et kørsel rapporterer en fejl, er et manglende scope. »ctx.shopify« er kun tilgængeligt, når indstillingen »Needs Shopify« er aktiveret, og skrivningen lykkes først, når der er tildelt skriveadgang.
Hvor skal vi hen nu?
Det samme mønster gælder for alt, hvad en prisændring bør påvirke. Byt om på funktionskroppen, og du kan markere et produkt til gennemgang, når prisen stiger med mere end 10 procent, sende den gamle og den nye fortjenstmargen til Slack eller skrive ændringen til et metafelt til brug for rapportering.
Triggeren er den del, som Shopify ikke giver dig. Det, der sker derefter, er almindelig kode.
Workflow Functions dokumentation
- Tilladelser og adgang til butiksdata - aktivering af »Kræver data fra Shopify« og tildeling af omfang
- Overførsel af variabler til din funktion - hvordan JSON-input og Liquid fungerer
- Konfigurer handlingen »Kør funktion« i Shopify Flow
- Kørselshistorik og fejlfinding

