Oppdater pris og sammenligningspris automatisk når leverandørprisen endres
Leverandøren din øker prisen på en variant fra 4,00 til 5,20. Ingenting i Shopify reagerer på dette. Salgsprisen forblir uendret, og marginen du hadde planlagt, forsvinner i det stille helt til noen oppdager det under en lageropptelling flere uker senere.
Shopify Flow kan ikke hjelpe her på egen hånd, fordi Shopify ikke har noen innebygd utløser for endringer i kostnaden per vare. Det finnes heller ingen handling som beregner prisen på nytt ut fra denne kostnaden.
Denne veiledningen løser begge problemene. Når enhetsprisen endres på en hvilken som helst variant, startes en Shopify Flow, og en kort funksjon sender den nye prisen og sammenligningsprisen tilbake til Shopify. Det tar omtrent ti minutter å sette opp, og deretter kjører den ved hver prisendring - for alltid.
Hva du skal bygge
- Workflow Trigger Extensions registrerer endringen i kostnaden og setter i gang en Shopify Flow, som inneholder varianten, dens SKU samt både den gamle og den nye kostnaden.
- Shopify Flow sender disse verdiene til en funksjon i JSON-format.
- Workflow Functions kjører noen få linjer med JavaScript som beregner de nye prisene og sender dem tilbake via Admin API.
Prisreglene finnes på ett sted, i koden du selv har kontroll over, så hvis du vil endre dem senere, trenger du bare å redigere én linje i stedet for å bygge om hele arbeidsflyten.
Trinn 1: Slå på kostnadsutløseren
I Workflow Trigger Extensions åpner du siden Triggers, finner gruppen Inventory og aktiverer Product Variant Cost Changed.
Denne utløseren krever tilgang til lagerdata, fordi kostnaden per vare er knyttet til lagerartikkelen og ikke til selve varianten. Hvis tillatelsen ikke er gitt ennå, vil du bli bedt om å gi den i en enkelt dialogboks når du slår på utløseren. Inntil tillatelsen er gitt, forblir utløseren aktiv, men viser en melding om at tillatelse kreves og vil ikke utløses.
Hva utløseren gir deg
Når den utløses, har Shopify Flow-prosessen din tilgang 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å inkludert som en produktreferanse, slik at du kan legge til Shopify Flow-betingelser basert på leverandør, type, tagger eller kolleksjon før prisen endres.
Trinn 2: Opprett funksjonen
I Workflow Functions oppretter du en ny funksjon og limer inn koden nedenfor.
Før du lagrer, må du slå på «Trenger Shopify-data». Det er dette som gjør ctx.shopify.graphql(...) tilgjengelig i koden din, slik at den kan lese og endre butikkdata. Åpne deretter siden Tillatelser i Workflow Functions, og gi tillatelse til å skrive til produkter - dette er omfanget denne funksjonen trenger for å endre en pris.
Uten denne bryteren er ikke ctx.shopify-objektet tilgjengelig, og funksjonen mislykkes ved det første Admin API-kallet.
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 };
}
}Noen ting det er verdt å merke seg om koden:
- Den godtar enten en ren numerisk ID eller en fullstendig GID.
toGidomformer begge deler, så du trenger ikke å bekymre deg for hvilken form Shopify Flow gir deg. - Den henter opp overordnet produkt bare når det er nødvendig.
productVariantsBulkUpdatekrever en produkt-ID; hvis du ikke oppgir en, henter funksjonen den selv. Ved å oppgiproductIdi inndataene unngår du denne turen frem og tilbake. - Den sjekker
userErrors, ikke bare transportfeil. Et GraphQL-anrop kan returnere HTTP 200 og likevel avvise skrivingen. Dette er den vanligste årsaken til at en prisoppdatering ser ut til å lykkes, men at ingenting endres. - Det er meningen at
compareAtskal fjernes. Hvis man sender inn `compareAtPrice: null`` eller en tom streng, blir den fjernet, i stedet for at det blir tolket som en feil.
Trinn 3: Test funksjonen før du kobler den til
Bruk fanen Test med en ekte variant-ID fra nettbutikken din. Hent en fra en hvilken som helst produkt-URL i administrasjonspanelet, eller fra utløserens hendelseshistorikk.
Angi en pris du kjenner igjen, slik at du kan bekrefte at meldingen er mottatt.
{
"variantId": "gid://shopify/ProductVariant/54589751394579",
"price": "24.99",
"compareAtPrice": "39.99"
}Trinn 4: Konfigurer Shopify Flow
Opprett en arbeidsflyt i Shopify Flow:
- Utløser: Endring i kostnaden for en produktvariant
- Handling: Kjør funksjon fra Workflow Functions, og velg funksjonen du nettopp har opprettet
Lim inn dette i JSON-inndatafeltet. Shopify Flow erstatter Liquid-koden med reelle verdier hver gang den kjøres.
{
"variantId": "{{variantCostChange.variantId}}",
"price": "{{variantCostChange.newCost.amount | times: 5}}",
"compareAtPrice": "{{variantCostChange.newCost.amount | times: 7}}"
}Det er hele prisregelen: fem ganger kostprisen som salgspris, syv ganger kostprisen som sammenligningspris, slik at produktet alltid vises med en jevn rabatt.
Disse multiplikatorene er et eksempel, ikke en anbefaling. Endre times: 5 til det tallet som din kategori faktisk støtter. Liquid tar seg av regnestykket, så et fast påslag i stedet for en multiplikator er plus: 12, og en prosentvis margin er times: 1.6.
Hvis du selger i flere valutaer, må du være oppmerksom på at newCost.amount er angitt i butikkens valuta. Markets tar seg av valutaomregningen når beløpet vises, så du trenger ikke å gjøre det selv.
Bekreft at det fungerer fra start til slutt
- Åpne en hvilken som helst produktvariant i Shopify-administrasjonspanelet og endre Kostnad per enhet
- Lagre
- I løpet av få sekunder oppdateres prisen og sammenligningsprisen automatisk
Hvis ingenting skjer, må du gå gjennom trinnene i denne rekkefølgen, siden hvert trinn utelukker det forrige:
| Sjekk | Hvor |
|---|---|
| Gikk avtrekkeren av? | Hendelseshistorikk i utvidelser for arbeidsflyt-utløsere (Workflow Trigger Extensions) |
| Ble Shopify Flow-prosessen kjørt? | Shopify Flow-aktivitetslogg |
| Ble funksjonen kjørt, og hva ble logget? | Kjør historikk i Workflow Functions |
Den vanligste årsaken til at en kjøring melder feil, er at et omfang mangler. ctx.shopify er kun tilgjengelig når «Trenger Shopify-data» er aktivert, og skrivingen lykkes først når tillatelse til å skrive produkter er gitt.
Hvor skal vi dra videre?
Det samme mønsteret gjelder for alt som påvirkes av en kostnadsendring. Ved å bytte om funksjonskroppen kan du merke et produkt for gjennomgang når kostnaden stiger med mer enn 10 prosent, legge ut den gamle og den nye marginen på Slack eller skrive endringen til et metafelt for rapportering.
Utløseren er den delen som Shopify ikke gir deg. Det som skjer videre, er vanlig kode.
Dokumentasjon for Workflow Functions
- Tillatelser og tilgang til butikkdata - aktivere «Trenger Shopify-data» og gi tilgang til områder
- Overføring av variabler til funksjonen din - hvordan JSON-inndata og Liquid fungerer
- Konfigurer handlingen «Kjør funksjon» i Shopify Flow
- Kjøringshistorikk og feilsøking
