Aggiornamento automatico del prezzo e del prezzo di riferimento in caso di variazioni del costo del fornitore
September 3, 2026
Il tuo fornitore aumenta il costo di una variante da 4,00 a 5,20. Nessuna funzione di Shopify reagisce. Il prezzo al dettaglio rimane invariato e il margine che avevi previsto svanisce silenziosamente, finché qualcuno non se ne accorge durante un inventario, settimane dopo.
Shopify Flow In questo caso non può essere d'aiuto da solo, perché Shopify non dispone di un trigger integrato per la modifica del costo unitario. Inoltre, non prevede alcuna azione che ricalcoli il prezzo in base a tale valore.
Questa guida colma entrambe le lacune. Quando il costo unitario di una variante subisce una variazione, viene avviato un flusso e una breve funzione reinserisce il nuovo prezzo e il prezzo di riferimento nell’Shopify. La configurazione richiede circa dieci minuti, dopodiché il flusso viene eseguito ad ogni variazione di costo, a tempo indeterminato.
Cosa realizzerai
- Workflow Trigger Extensions rileva la variazione di costo e avvia un flusso, riportando la variante, il relativo SKU e sia il costo precedente che quello nuovo.
- Shopify Flow passa tali valori a una funzione in formato JSON.
- Workflow Functions esegue alcune righe di codice JavaScript che calcolano i nuovi prezzi e li inviano tramite l'API di amministrazione.
La regola di determinazione dei prezzi è definita in un unico punto, nel codice che controlli tu, quindi modificarla in un secondo momento significa modificare una sola riga anziché ricostruire l'intero flusso di lavoro.
Passaggio 1: Attivare il trigger di costo
In "Workflow Trigger Extensions", apri la pagina "Trigger", individua il gruppo "Inventario" e attiva l'opzione "Modifica del costo della variante di prodotto".
Questo trigger richiede l'accesso ai dati di magazzino, poiché il costo per articolo è associato all'articolo di magazzino e non alla variante stessa. Se l'autorizzazione non è stata ancora concessa, l'attivazione del trigger richiederà di concederla tramite una singola finestra di dialogo. Finché l'autorizzazione non viene concessa, il trigger rimane attivo ma mostra un indicatore "Autorizzazione richiesta" e non verrà attivato.
Cosa ti offre il trigger
Una volta attivato, il tuo Flow avrà accesso a:
| Campo | Esempio |
|---|---|
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 |
Il prodotto stesso è incluso come riferimento, quindi è possibile aggiungere condizioni di flusso relative a fornitore, tipo, tag o collezione prima ancora di modificare il prezzo.
Fase 2: Creare la funzione
In “Workflow Functions”, crea una nuova funzione e incolla il codice riportato di seguito.
Prima di salvare, attiva l'opzione "Richiede dati dShopify". In questo modo il tuo codice avrà accesso a ctx.shopify.graphql(...) e potrà leggere e modificare i dati del negozio. Quindi apri la pagina "Autorizzazioni" all'indirizzo Workflow Functions e concedi l'autorizzazione alla scrittura sui prodotti: è l'ambito di cui questa funzione ha bisogno per modificare un prezzo.
Senza quell’opzione, l’oggetto ctx.shopify non è disponibile e la funzione fallisce alla prima chiamata all’API di amministrazione.
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 };
}
}Alcune cose da tenere presenti riguardo al codice:
- Accetta un ID numerico semplice o un GID completo.
toGidnormalizza entrambi, quindi non devi preoccuparti del formato con cui Flow te lo fornisce. - Cerca il prodotto principale solo quando è necessario. La funzione
productVariantsBulkUpdaterichiede un ID prodotto; se non ne viene specificato uno, la funzione lo recupera automaticamente. PassandoproductIdnell'input si evita questa operazione. - Verifica l'
userErrorse, non solo gli errori di trasporto. Una chiamata GraphQL può restituire un codice HTTP 200 e comunque rifiutare la scrittura. Questo è il motivo più comune per cui un aggiornamento del prezzo sembra andare a buon fine, ma in realtà non cambia nulla. - La rimozione di “compare-at” è intenzionale. Passando
compareAtPrice: nullo una stringa vuota, tale valore viene rimosso, anziché essere considerato un errore.
Fase 3: Verificare il funzionamento della funzione prima di effettuare il cablaggio
Utilizza la scheda "Test" inserendo un ID variante reale del tuo negozio. Prendine uno da qualsiasi URL di prodotto nell'area di amministrazione o dalla cronologia degli eventi del trigger.
Imposta un prezzo che ti sia familiare, in modo da poter verificare che il messaggio sia stato ricevuto.
{
"variantId": "gid://shopify/ProductVariant/54589751394579",
"price": "24.99",
"compareAtPrice": "39.99"
}Fase 4: Cablaggio del Flow
Creare un flusso di lavoro in Shopify Flow:
- Condizione: Modifica del costo di una variante del prodotto
- Azione: Esegui la funzione da Workflow Functions e seleziona la funzione appena creata
Nel campo di immissione JSON, incolla questo testo. Flow sostituisce il codice Liquid con valori reali ogni volta che viene eseguito.
{
"variantId": "{{variantCostChange.variantId}}",
"price": "{{variantCostChange.newCost.amount | times: 5}}",
"compareAtPrice": "{{variantCostChange.newCost.amount | times: 7}}"
}Ecco la regola completa per la determinazione dei prezzi: il prezzo di vendita è pari a cinque volte il costo, mentre il prezzo di riferimento è pari a sette volte il costo, in modo che il prodotto mostri sempre uno sconto costante.
Questi moltiplicatori sono solo un esempio, non una raccomandazione. Sostituisci times: 5 con il valore effettivamente supportato dalla tua categoria. Liquid si occupa dei calcoli, quindi un ricarico fisso al posto di un moltiplicatore è plus: 12, mentre un margine percentuale è times: 1.6.
Se vendi in diverse valute, tieni presente che l'newCost.amounte è espressa nella valuta del negozio. Markets si occupa della conversione al momento della visualizzazione, quindi non devi farlo tu.
Verifica che funzioni dall’inizio alla fine
- Apri una qualsiasi variante di prodotto nell'area di amministrazione di Shopify e modifica il costo unitario
- Salva
- Nel giro di pochi secondi, il prezzo e il prezzo di riferimento si aggiornano automaticamente
Se non succede nulla, procedi in questo ordine, poiché ogni passaggio esclude quello precedente:
| Verifica | Dove |
|---|---|
| Il grilletto ha sparato? | Cronologia degli eventi in Workflow Trigger Extensions |
| Il Flow ha funzionato? | Shopify Flow registro delle attività |
| La funzione è stata eseguita? E cosa è stato registrato nel log? | Cronologia delle esecuzioni in Workflow Functions |
La causa più comune di un'esecuzione che segnala un errore è la mancanza di uno scope. L'opzione ctx.shopify è disponibile solo quando l'impostazione "Needs Shopify data" è attivata, e la scrittura va a buon fine solo dopo che è stata concessa l'autorizzazione "write products".
Dove andare dopo
Lo stesso schema funziona per qualsiasi elemento interessato da una variazione di costo. Basta sostituire il corpo della funzione per contrassegnare un prodotto affinché venga sottoposto a revisione quando il costo aumenta di oltre il 10%, pubblicare su Slack il margine precedente e quello nuovo oppure registrare la variazione in un metafield ai fini della rendicontazione.
Il trigger è la parte che Shopify non ti fornisce. Quello che segue è codice standard.
Workflow Functions documentazione
- Autorizzazioni e accesso ai dati dell'app store - attivazione della funzione "Richiede i dati di Shopify" e concessione degli ambiti
- Come passare variabili alla funzione: come funzionano l'input JSON e Liquid
- Configura l'azione "Esegui funzione" su Shopify Flow
- Cronologia delle esecuzioni e risoluzione dei problemi

