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

  1. Workflow Trigger Extensions detecta a alteração no custo e inicia um fluxo, incluindo a variante, seu SKU e os custos antigo e novo.
  2. Shopify Flow passa esses valores para uma função no formato JSON.
  3. 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.

update-variant-price.jsjavascript
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 toGid normaliza 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 productVariantsBulkUpdate exige um ID de produto; se você não passar um, a função o busca automaticamente. Passar productId na 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 passar compareAtPrice: null ou 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.

test-input.jsonjson
{
  "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:

  1. Gatilho: Alteração no custo da variante do produto
  2. 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.

flow-input.jsonjson
{
  "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

  1. Abra qualquer variante de produto no painel de administração dShopify e altere o custo por item
  2. Salvar
  3. 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.

Related articlePermissões e acesso a dadosO que o acesso aos dados de estoque permite e como concedê-lo ou revogá-lo.Related articleReferência completa sobre gatilhosTodos os gatilhos do `Workflow Trigger Extensions`, com os campos que cada um contém.

Workflow Functions documentação