Atualizar automaticamente o preço e o preço de referência quando o custo do fornecedor se alterar
September 3, 2026
O seu fornecedor aumenta o custo de uma variante de 4,00 para 5,20. Nada no Shopify reage a isso. O preço de venda ao público mantém-se inalterado e a margem que planeou desaparece discretamente, até que alguém repara nisso durante um inventário, semanas mais tarde.
Shopify Flow Isso, por si só, não resolve o problema, porque o Shopify não dispõe de um gatilho integrado para uma alteração no custo por unidade. Também não possui nenhuma ação que recalcule o preço a partir desse valor.
Este guia colmata ambas as lacunas. Quando o custo por artigo muda em qualquer variante, é iniciado um «Flow» e uma função curta grava o novo preço e o preço de referência de volta no Shopify. A configuração demora cerca de dez minutos e, depois, é executada sempre que houver uma alteração no custo, de forma contínua.
O que vais construir
- Workflow Trigger Extensions deteta a alteração no custo e inicia um Fluxo, incluindo a variante, o seu SKU e tanto o custo antigo como o novo.
- Shopify Flow passa esses valores para uma função no formato JSON.
- Workflow Functions executa algumas linhas de JavaScript que calculam os novos preços e os enviam de volta através da API de administração.
A regra de preços está definida num único local, no código que controlas, pelo que alterá-la posteriormente implica editar apenas uma linha, em vez de ter de reconstruir um fluxo de trabalho.
Passo 1: Ativar o gatilho de custos
No site Workflow Trigger Extensions, abra a página «Triggers», localize o grupo «Inventário» e ative a opção «Alteração do custo da variante do produto».
Este gatilho requer acesso aos dados de inventário, uma vez que o custo por artigo está associado ao artigo em si e não à própria variante. Se a autorização ainda não tiver sido concedida, ao ativar o gatilho será solicitada essa autorização numa única caixa de diálogo. Até que a autorização seja concedida, o gatilho permanece ativado, mas exibe uma indicação de «Autorização necessária» e não será acionado.
O que o gatilho lhe proporciona
Assim que for acionado, o seu Flow tem acesso a:
| Campo | Exemplo |
|---|---|
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 |
O próprio produto também está incluído como referência de produto, pelo que pode adicionar condições do Flow com base no fornecedor, tipo, etiquetas ou coleção antes de qualquer preço ser alterado.
Passo 2: Criar a função
Em «Workflow Functions», crie uma nova função e cole o código abaixo.
Antes de guardar, ative a opção «Necessita de dados dShopify». É isso que expõe ctx.shopify.graphql(...) ao seu código, para que este possa ler e modificar os dados da loja. Em seguida, abra a página «Permissões» em Workflow Functions e conceda permissão para escrever em produtos, que é o âmbito de que esta função necessita para alterar um preço.
Sem essa opção, o objeto ctx.shopify não está disponível e a função falha na primeira chamada à API de administração.
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 };
}
}Algumas observações a destacar sobre o código:
- Aceita um identificador numérico simples ou um GID completo. O
toGidnormaliza ambos, pelo que não precisa de se preocupar com o formato que o Flow lhe fornece. - A função só procura o produto pai quando é necessário. A função
productVariantsBulkUpdaterequer um ID de produto; se não for passado nenhum, a função obtém-no. Ao passarproductIdna entrada, evita-se essa ida e volta. - Verifica o código de estado
userErrors, e não apenas erros de transporte. Uma chamada GraphQL pode devolver um código HTTP 200 e, mesmo assim, recusar a gravação. Esta é a razão mais comum pela qual uma atualização de preço parece ter sido bem-sucedida, mas nada muda. - A remoção do «compare-at» é intencional. Ao passar
compareAtPrice: nullou uma cadeia de caracteres vazia, este é removido, em vez de ser considerado um erro.
Passo 3: Testar a função antes de a ligar
Utilize o separador «Teste» com um ID de variante real da sua loja. Escolha um a partir de qualquer URL de produto na área de administração ou do histórico de eventos do gatilho.
Defina um preço que consiga reconhecer, para poder confirmar que a mensagem foi recebida.
{
"variantId": "gid://shopify/ProductVariant/54589751394579",
"price": "24.99",
"compareAtPrice": "39.99"
}Passo 4: Ligar o Flow
Criar um fluxo de trabalho no Shopify Flow:
- Desencadeador: Alteração do custo de uma variante do produto
- Ação: Executar função em Workflow Functions e selecionar a função que acabou de criar
No campo de introdução de dados JSON, cole isto. O Flow substitui o Liquid por valores reais sempre que é executado.
{
"variantId": "{{variantCostChange.variantId}}",
"price": "{{variantCostChange.newCost.amount | times: 5}}",
"compareAtPrice": "{{variantCostChange.newCost.amount | times: 7}}"
}Essa é toda a regra de fixação de preços: cinco vezes o custo como preço de venda e sete vezes o custo como preço de referência, para que o produto apresente sempre um desconto consistente.
Esses multiplicadores são um exemplo, não uma recomendação. Altere times: 5 para o valor que a sua categoria realmente suporta. O Liquid trata dos cálculos, pelo que uma margem fixa, em vez de um multiplicador, é plus: 12, e uma margem percentual é times: 1.6.
Se vender em várias moedas, tenha em atenção que newCost.amount está na moeda da loja. O Markets trata da conversão no momento da visualização, pelo que não precisa de o fazer.
Confirme se funciona de ponta a ponta
- Abra qualquer variante de produto no painel de administração dShopify e altere o custo por unidade
- Guardar
- Em poucos segundos, o preço e o preço de referência atualizam-se automaticamente
Se nada acontecer, siga estes passos por esta ordem, pois cada passo exclui o anterior:
| Verificar | Onde |
|---|---|
| O gatilho disparou? | Histórico de eventos no Workflow Trigger Extensions |
| O Flow funcionou? | Shopify Flow registo de atividades |
| A função foi executada e o que foi registado no log? | Histórico de execuções no Workflow Functions |
A causa mais comum de uma execução que apresenta uma falha é a ausência de um âmbito. A função ctx.shopify só está disponível quando a opção «Needs Shopify data» está ativada, e a gravação só é bem-sucedida depois de ter sido concedida a autorização para gravar produtos.
Para onde ir a seguir
O mesmo padrão aplica-se a qualquer situação em que ocorra uma alteração de custo. Basta trocar o corpo da função e poderá marcar um produto para revisão quando o custo aumentar mais de 10 por cento, publicar a margem antiga e a nova no Slack ou registar a alteração num metacampo para efeitos de relatório.
O gatilho é a parte que o Shopify não te fornece. O que se segue é código normal.
Workflow Functions documentação
- Permissões e acesso aos dados da loja - ativar a opção «Necessita de dados do Shopify» e conceder âmbitos
- Passar variáveis para a sua função - como funcionam a entrada JSON e o Liquid
- Configure a ação «Executar função» em Shopify Flow
- Histórico de execução e resolução de problemas

