Atualizar automaticamente o preço e o preço de referência quando houver alterações no custo do fornecedor
September 3, 2026
Seu fornecedor aumenta o custo de uma variante de 4,00 para 5,20. Nada no Shopify reage a isso. O preço de varejo permanece o mesmo, e a margem que você planejou desaparece discretamente até que alguém perceba isso durante um inventário, semanas depois.
Shopify Flow Isso por si só não resolve o problema, pois o **Shopify** não possui um gatilho integrado para alterações no custo por item. Ele também não possui nenhuma ação que recalcule o preço a partir desse valor.
Este guia resolve ambas as lacunas. Quando o custo por item muda em qualquer variante, um Flow é iniciado, e uma função curta grava o novo preço e o preço de referência de volta no Shopify. A configuração leva cerca de dez minutos e, depois disso, o processo é executado sempre que houver uma mudança no custo, indefinidamente.
O que você vai desenvolver
- Workflow Trigger Extensions detecta a alteração no custo e inicia um fluxo, incluindo a variante, seu SKU e os custos antigo e 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 por meio da API de administração.
A regra de precificação está definida em um único lugar, no código que você controla; portanto, alterá-la posteriormente significa editar apenas uma linha, em vez de reconstruir todo um fluxo de trabalho.
Passo 1: Ativar o gatilho de custo
No site Workflow Trigger Extensions, abra a página “Triggers”, localize o grupo “Inventário” e ative a opção “Alteração no custo da variante do produto”.
Este gatilho requer acesso aos dados de estoque, pois o custo por item está associado ao item de estoque e não à própria variante. Se a permissão ainda não tiver sido concedida, ao ativar o gatilho, será solicitada em uma única caixa de diálogo. Até que seja concedida, o gatilho permanece ativado, mas exibe um aviso de “Permissão necessária” e não será acionado.
O que o gatilho oferece a você
Assim que for acionado, seu Flow terá 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 é incluído como referência, de modo que você pode adicionar condições do Flow com base no fornecedor, tipo, tags ou coleção antes mesmo de qualquer preço ser alterado.
Etapa 2: Criar a função
No arquivo **Workflow Functions**, crie uma nova função e cole o código abaixo.
Antes de salvar, ative a opção “Precisa de dados dShopify”. É isso que expõe ctx.shopify.graphql(...) ao seu código, para que ele possa ler e modificar os dados da loja. Em seguida, abra a página “Permissões” em Workflow Functions e conceda permissão para “gravação de produtos”, que é o escopo necessário para que essa função altere 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 sobre o código:
- Ele aceita um ID numérico simples ou um GID completo. O
toGidnormaliza ambos, então você não precisa se preocupar com o formato que o Flow fornecer. - Ela consulta o produto pai somente quando necessário. A função
productVariantsBulkUpdateexige um ID de produto; se você não passar um, a função o busca automaticamente. PassarproductIdna entrada evita essa ida e volta. - Ele verifica o código de resposta
userErrors, e não apenas erros de transporte. Uma chamada GraphQL pode retornar o código HTTP 200 e, mesmo assim, recusar a gravação. Esse é o motivo mais comum pelo qual uma atualização de preço parece ter sido bem-sucedida, mas nada muda. - A remoção do
compare-até intencional. Ao passarcompareAtPrice: nullou uma string vazia, ele é removido, em vez de ser considerado um erro.
Etapa 3: Teste a função antes de fazer a conexão elétrica
Utilize a aba “Teste” com um ID de variante real da sua loja. Escolha um a partir de qualquer URL de produto no painel de administração ou do histórico de eventos do gatilho.
Defina um preço que você reconheça, para poder confirmar que a gravação foi bem-sucedida.
{
"variantId": "gid://shopify/ProductVariant/54589751394579",
"price": "24.99",
"compareAtPrice": "39.99"
}Etapa 4: Fazer a conexão do Flow
Crie um fluxo de trabalho no Shopify Flow:
- Gatilho: Alteração no custo da variante do produto
- Ação: Execute a função em Workflow Functions e selecione a função que você acabou de criar
No campo de entrada JSON, cole isto. O Flow substitui o código Liquid por valores reais a cada vez que é executado.
{
"variantId": "{{variantCostChange.variantId}}",
"price": "{{variantCostChange.newCost.amount | times: 5}}",
"compareAtPrice": "{{variantCostChange.newCost.amount | times: 7}}"
}Essa é toda a regra de precificação: cinco vezes o custo como preço de venda e sete vezes o custo como preço de referência, para que o produto sempre apresente um desconto consistente.
Esses multiplicadores são apenas um exemplo, não uma recomendação. Substitua times: 5 pelo valor que sua categoria realmente suporta. O Liquid cuida da parte aritmética; portanto, uma margem fixa em vez de um multiplicador é plus: 12, e uma margem percentual é times: 1.6.
Se você vende em várias moedas, lembre-se de que newCost.amount está na moeda da loja. O Markets cuida da conversão no momento da exibição, portanto, você não precisa fazer isso.
Confirme se funciona de ponta a ponta
- Abra qualquer variante de produto no painel de administração dShopify e altere o custo por item
- Salvar
- Em poucos segundos, o preço e o preço de referência são atualizados automaticamente
Se nada acontecer, siga estas etapas nesta ordem, pois cada uma delas descarta a anterior:
| Verificar | Onde |
|---|---|
| O gatilho disparou? | Histórico de eventos no Workflow Trigger Extensions |
| O Flow funcionou? | Shopify Flow registro de atividades |
| A função foi executada? E o que foi registrado no log? | Histórico de execuções no Workflow Functions |
A causa mais comum de uma execução que apresenta falha é a ausência de um escopo. O recurso ctx.shopify só está disponível quando a opção “Needs Shopify data” está ativada, e a gravação só é bem-sucedida após a concessão dos produtos de gravação.
Para onde ir a seguir
Esse mesmo padrão se aplica a qualquer situação em que haja uma variação de custo. Basta alterar o corpo da função para marcar um produto para revisão quando o custo aumentar mais de 10%, publicar a margem antiga e a nova no Slack ou gravar a alteração em um metacampo para fins de relatório.
O gatilho é a parte que o Shopify não fornece. O que acontece a seguir é código comum.
Workflow Functions documentação
- Permissões e acesso aos dados da loja — ativando a opção “Precisa de dados do Shopify” e concedendo escopos
- Passando variáveis para 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 solução de problemas

