Gatilhos personalizados
Os gatilhos integrados abrangem as alterações que mais interessam à maioria das lojas. Um gatilho personalizado abrange o resto: basta escolher um evento Shopify, escrever algumas linhas de JavaScript para determinar se é relevante e o que enviar, e este torna-se um gatilho que pode utilizar em Shopify Flow.
Três coisas que resolve e que um gatilho integrado não consegue:
- Execute apenas se a sua condição for satisfeita. «Apenas quando uma encomenda superior a 500 EUR receber a etiqueta
vip» é uma única linha de código, em vez de um fluxo de trabalho que é executado em todas as encomendas e, posteriormente, as filtra. - Aplique a condição a uma transição, não a um estado. O seu código vê o valor antes e depois da alteração, pelo que é possível dizer que «o estado passou de rascunho para ativo» ou que «o stock desceu abaixo de 5». Uma condição baseada no valor atual não consegue expressar isso.
- Envie exatamente os campos que pretende. Reestruture o evento de acordo com os valores que o seu fluxo de trabalho utiliza efetivamente, em vez de os ler novamente um a um.
Um gatilho personalizado nem sequer precisa de um evento Shopify: também pode ser executado de acordo com uma programação e determinar por si próprio o que mudou.
Como funciona
- Escolha o que o faz funcionar: um evento Shopify ou um horário.
- Para um evento, selecione o evento ao qual este está associado - qualquer evento do tipo Shopify que a aplicação já receba - ou comece a partir de um modelo, que seleciona o evento e preenche o código.
- Capture uma carga útil real. Faça essa alteração na sua loja e a aplicação irá capturar o corpo exato do evento.
- Escreva uma transformação - devolva um objeto para acionar, devolva um
nullo para ignorar. - Teste-o com o evento capturado e veja exatamente o que o seu fluxo de trabalho receberia.
- Liga-o.

Escrever a transformação
O teu «trigger» é um módulo JavaScript que exporta uma função chamada transform. Recebe quatro argumentos:
payload- o corpo do evento Shopify em formato bruto, tal como é recebido.topic- qual o evento que foi disparado, por exemplo,PRODUCTS_UPDATE.shop- o teu domínio myshopify.ctx-ctx.log(...)apresenta resultados no painel de registo ao lado do editor,ctx.shopify(...)executa uma consulta GraphQL de administração ectx.fetch(...)acede a um endereço URL na Internet pública.
O que devolveres determina o que vai acontecer:
- Devolve um objeto e o gatilho é acionado, transportando esse objeto.
- Se devolver «
null», o evento é ignorado. É assim que funciona a filtragem - não é necessário aprender nenhuma linguagem de filtragem específica. - Deixe o ficheiro vazio e ele será acionado sempre que ocorrer um evento desse tipo.
/**
* Only fire for high-value orders carrying the vip tag.
*/
export async function transform(payload, topic, shop, ctx) {
const total = parseFloat(payload.total_price || "0");
const tags = (payload.tags || "").split(",").map(t => t.trim());
if (total < 500) return null;
if (!tags.includes("vip")) return null;
ctx.log("firing for", payload.name, total);
return {
orderId: payload.admin_graphql_api_id,
orderNumber: payload.name,
total,
currency: payload.currency,
customerEmail: payload.email,
};
}O valor antes da alteração
Shopify
Nas atualizações de produto, de encomenda e de cliente, payload._changes apresenta todos os campos monitorizados que foram alterados por essa atualização, cada um com oldValue e newValue:
- Produtos:
title,handle,description,status,vendor,productType,tags - Encomendas:
financialStatus,fulfillmentStatus,tags,note,lineItemsecustomAttributes.<name> - Clientes:
tags,note,state(ENABLED,DISABLED,INVITED,DECLINED)
É uma lista vazia quando a atualização não incidiu sobre esses campos - uma alteração no inventário, por exemplo - ou quando a aplicação está a visualizar o registo pela primeira vez. O evento de exemplo que capturas no editor mostra o campo, para que possas ver a sua estrutura real antes de introduzires dados nele.
/**
* Fire only when a product BECOMES active - not on every later edit of an
* active product, which is what a condition on the current status would do.
*/
export async function transform(payload, topic, shop, ctx) {
const change = (payload._changes || []).find((c) => c.field === "status");
if (!change) return null;
if (change.oldValue !== "draft" || change.newValue !== "active") return null;
return {
productId: payload.admin_graphql_api_id,
title: payload.title,
oldStatus: change.oldValue,
newStatus: change.newValue,
};
}Os eventos mais específicos têm os seus próprios valores antigos e novos, pelo que não é necessário utilizar _changes nesses casos: uma alteração de preço tem oldPrice, newPrice e percentChange; uma alteração de inventário tem _oldAvailable, _newAvailable e _delta; uma alteração de metacampo tem previousValue a par de metafield.value.
Começar a partir de um modelo
Na secção «Fires on» do editor, a opção «Começar a partir de um modelo» seleciona o evento e insere código funcional. Edite as constantes na parte superior, teste e, em seguida, guarde. Cada modelo lê um valor antes e depois da alteração:
- Um campo de um produto, encomenda ou cliente mudou de um valor para outro - o estado passou de «rascunho» para «ativo», uma encomenda passou para «paga», uma conta foi ativada.
- O preço baixou mais de N por cento - uma verdadeira redução, não uma simples alteração de preço.
- O stock desceu abaixo de um limiar - dispara uma vez, no momento em que o stock ultrapassa o limite, e não a cada venda enquanto já se encontra baixo.
- O valor de um metacampo do produto ultrapassou um limiar - uma classificação ficou abaixo de 3, uma margem ultrapassou os 40.
- Encomenda paga por um cliente de alto valor - analisa o valor total gasto pelo cliente na sua loja ao longo do tempo e só é acionada quando esse valor ultrapassa o montante que definiu.

Obter dados adicionais com ctx.shopify
Os corpos dos webhooks contêm apenas os campos enviados pelo Shopify. Quando precisar de outra informação - o número de encomendas de um cliente, o stock de uma variante, um metacampo - , efetue uma consulta à API de Administração diretamente a partir da sua transformação:
export async function transform(payload, topic, shop, ctx) {
const data = await ctx.shopify(`
query($id: ID!) {
customer(id: $id) { numberOfOrders tags }
}
`, { id: payload.customer.admin_graphql_api_id });
// Only fire for repeat customers
if (data.customer.numberOfOrders < 5) return null;
return {
orderId: payload.admin_graphql_api_id,
orderCount: data.customer.numberOfOrders,
};
}Devolve o objeto data da consulta e lança uma exceção se a consulta apresentar erros, para que o erro seja visível no seu teste, em vez de simplesmente não produzir qualquer resultado sem aviso prévio.
Três limites que vale a pena conhecer:
- Até 10 chamadas por execução. O enriquecimento requer algumas; mais do que isso, normalmente implica um ciclo. Recupere o que precisar numa única consulta, sempre que possível.
- A aplicação lê, não escreve. Utiliza as permissões que concedeu, e a aplicação só solicita acesso de leitura. Uma consulta aos dados das encomendas falhará, a menos que o «Acesso aos dados das encomendas» esteja concedido na página «Permissões». Para alterar algo na sua loja, faça-o nas ações do Flow que se seguem ao gatilho.
- As credenciais da sua loja nunca chegam ao seu código. A consulta é executada pela aplicação em seu nome, pelo que não existe nenhum token de acesso dentro da sandbox que possa ser divulgado.
ctx.fetch(url, options) Funciona como o fetch do navegador para qualquer conteúdo na Internet pública: o feed de stock de um fornecedor, uma taxa de câmbio, a sua própria API. Os endereços de redes internas e privadas são rejeitados. Se o seu código de ativação estiver guardado no GitHub, não inclua uma chave de API nesse código.
Gatilhos que são executados de acordo com um horário definido
Shopify Flow reage quando algo acontece. Não pode reagir quando nada acontece e não consegue ver nada fora da sua loja. Para isso, selecione «De acordo com um horário» na secção «O que faz com que isto seja executado». Não existe nenhum evento Shopify por trás deste tipo de gatilho: o seu código é executado a intervalos, desde a cada 30 segundos até uma vez por dia, e decide por si próprio o que conta como uma alteração.
Trata-se da mesma função transform, com um payload diferente e um valor de retorno diferente:
payload.state- o valor que o seu código devolveu comostatena execução anterior.nullna primeira execução.payload.nowepayload.lastRunAt- registos de data e hora.{ state, events }devolvido: o novo estado a memorizar (até 32 KB) e uma lista de eventos a disparar (até 100 por execução). Cada evento dispara o Custom Trigger uma vez; o parâmetroresourceIdde um evento, caso seja definido, passa a ser o ID do registo no Flow.nulldevolvido quando não há nada a comunicar.
Na primeira execução, lembre-se apenas de nunca disparar. Na primeira execução, o seu código não tem nada com que comparar, pelo que tudo parecerá novo. Guarde o que vir e não devolva quaisquer eventos; assim, ativar o gatilho nunca sobrecarregará os seus fluxos de trabalho. Todos os modelos fazem isto.

// Fires when a value at a JSON URL changes, with the value before and after.
const URL = "https://api.example.com/stock/1042"
export async function transform(payload, topic, shop, ctx) {
const res = await ctx.fetch(URL, { headers: { accept: "application/json" } })
if (!res.ok) throw new Error("The URL answered with HTTP " + res.status)
const value = String((await res.json()).stock)
// The first run only remembers the value.
const previous = payload.state ? payload.state.value : undefined
if (previous === undefined || previous === value) return { state: { value } }
return {
state: { value },
events: [{ oldValue: previous, newValue: value }],
}
}Modelos para acionadores programados, na secção «Iniciar a partir de um modelo» do cartão «Agendamento»:
- Produto, encomenda ou cliente não atualizado há N dias - revisões de catálogo desatualizadas, encomendas em espera, reconquista de clientes. Cada registo é acionado uma vez por período de inatividade, e os registos que já estivessem em atraso no momento em que a funcionalidade for ativada não são acionados todos de uma só vez.
- Foi alterado um valor fora dShopify: um feed de stock de fornecedor, uma taxa de câmbio, uma lista de preços, com a diferença e a percentagem para os números.
- Novo item num feed RSS ou Atom - notícias do fornecedor, um feed de listagem, uma página de estado.
- Sem encomendas durante N horas - um sinal de vida para a sua loja. É acionado uma vez quando as encomendas param e outra vez quando voltam.
O Test executa o seu código uma vez, sem acionar nada e sem guardar o estado, pelo que pode executá-lo quantas vezes quiser.
Utilização no Shopify Flow
Todos os gatilhos personalizados chegam ao Flow com o mesmo nome: Gatilho Personalizado. Adicione-o a um fluxo de trabalho e, em seguida, adicione uma condição do tipo «O identificador do gatilho é igual ao identificador do seu gatilho».
Esse identificador aparece na página do gatilho e nunca muda, mesmo que renomeie o gatilho - assim, o seu fluxo de trabalho continua a funcionar.
Cada chave que a sua transformação devolve torna-se um campo no gatilho, e o objeto completo também está disponível em formato JSON, caso prefira analisá-lo por conta própria.
Guarda o código no GitHub
Pode ligar um repositório do GitHub para que o seu código de acionamento fique sob controlo de versões. As alterações ficam disponíveis para revisão numa solicitação de integração, pode ver quem alterou o quê e pode reverter uma transformação que tenha deixado de funcionar.
Ligue-o na página «Desenvolvedor», na secção «Ligações». Pode escolher quais os repositórios a que a aplicação tem acesso e pode revogar esse acesso no GitHub a qualquer momento.
Assim que um repositório for selecionado, todos os gatilhos existentes são gravados nesse repositório imediatamente, e a sincronização mantém-se em ambos os sentidos:
| O que fazes | O que acontece |
|---|---|
| Criar, editar ou duplicar um gatilho na aplicação | O ficheiro foi submetido ao seu repositório |
| Eliminar um gatilho na aplicação | O ficheiro foi removido do seu repositório |
| Enviar uma alteração para o ramo ligado | O código do gatilho é atualizado na aplicação |
Cada trigger é um ficheiro com o nome do seu identificador, que contém exatamente o módulo que se vê no editor - sem nada à sua volta. Isso significa que pode abri-lo no seu próprio editor, executá-lo e submetê-lo a uma verificação de código, tal como qualquer outro ficheiro JavaScript.
Voltar a uma versão anterior
Não é necessário saber usar o Git para reverter uma alteração. Assim que um repositório estiver ligado, o editor apresenta um menu suspenso «Versão» que lista todas as versões anteriores desse ficheiro, com a respetiva data e autor. Escolha uma e esta será carregada no editor como uma alteração não guardada, para que possa lê-la primeiro - é ao guardar que a alteração é revertida.
Teste enquanto edita localmente
Se estiver a editar o ficheiro no seu próprio editor, pode executá-lo com o evento de amostra capturado sem ter de o guardar primeiro na aplicação. Utilize uma chave de API com o nível de execução disponível na página do Desenvolvedor:
curl -X POST https://shopify.workflow-trigger-extensions.app/api/v1/triggers/custom/high-value-vip-order/test \
-H "Authorization: Bearer ftk_your_key_here" \
-H "Content-Type: application/json" \
-d "$(jq -Rn --rawfile c flow-triggers/high-value-vip-order.js '{code:$c}')"Recebe o mesmo resultado que o botão «Testar» da aplicação apresenta: se a função seria executada, o objeto de saída, as suas linhas de ctx.log e o tempo de execução.
Este ponto final não** aciona nada nem guarda nada**, e não consome qualquer quota do plano - por isso, é seguro executá-lo sempre que houver um salvamento a partir de um observador de ficheiros. (O botão «Executar teste» dentro da aplicação aciona o seu fluxo de trabalho do Flow, para que possa acompanhar a sua execução do início ao fim; isso também é gratuito.)
Também pode descarregar a carga útil de exemplo separadamente com uma chave de leitura, guardá-la localmente e executar o ficheiro totalmente offline:
curl https://shopify.workflow-trigger-extensions.app/api/v1/triggers/custom/high-value-vip-order/test \
-H "Authorization: Bearer ftk_your_key_here"Um gatilho personalizado consome a minha franquia do plano?▾
Sim, e conta todos os eventos que analisa - não apenas aqueles em que é acionado. Se o teu gatilho estiver a monitorizar a «Atualização de Produto» e a tua loja tiver 60 000 atualizações de produto por mês, isso equivale a 60 000 eventos, mesmo que o teu código seja acionado em apenas 100 deles.
Recebemos, deduplicamos e colocamos em fila cada um desses eventos e, em seguida, executamos o seu código num ambiente isolado - tudo isto antes de o seu código decidir se deve ser executado. A contagem reflete esse trabalho.
Dito de outra forma: custa o mesmo que custaria o gatilho integrado para o mesmo evento. Não há custos adicionais pela filtragem e os testes são sempre gratuitos. Um gatilho agendado conta uma vez por execução.
O teste é gratuito?▾
Sim. Tanto o botão «Executar teste» na aplicação como o ponto de extremidade da API /test estão isentos, apesar de o botão «Executar teste» ativar efetivamente o seu fluxo de trabalho no Flow para que possa observá-lo a ser executado. Apenas as execuções em tempo real consomem a sua cota, pelo que pode iterar sobre uma transformação quantas vezes quiser.
Por que é que o `payload._changes` está vazio?▾
Ou a atualização não se referia aos campos monitorizados - uma alteração no inventário ou numa variante de um produto, por exemplo - ou a aplicação ainda não dispõe de uma linha de base para esse registo. A linha de base é armazenada na primeira vez que a aplicação deteta um registo; por isso, a primeira atualização de um registo que nunca tenha sido detetado não contém nenhum valor anterior. Todas as atualizações posteriores a essa já o fazem.
O meu código pode alterar os dados na minha loja?▾
N.º ctx.shopify funciona com as permissões de leitura que concedeu, e a aplicação nunca solicita acesso de escrita. Isso é intencional: um gatilho que edita o registo que está a monitorizar volta a ativar-se, o que constitui o ciclo vicioso pelo qual o Shopify desativa os fluxos de trabalho. Altere os dados nas ações do Flow que se seguem ao gatilho.
Posso trocar a pega mais tarde?▾
Não, e isso é intencional. O teu fluxo de trabalho do Flow filtra com base no identificador; por isso, alterá-lo interromperia silenciosamente a execução desse fluxo de trabalho. Podes renomear o gatilho à vontade - o identificador permanece inalterado.
O nome de utilizador é também o nome do ficheiro no teu repositório do GitHub, pelo que também nunca muda.
O que acontece se o meu código tiver um erro?▾
O evento é ignorado e o erro é registado no gatilho, para que possa ver o que correu mal. Uma transformação com falha nunca bloqueia nada mais - os seus outros gatilhos, personalizados ou integrados, continuam a funcionar sem serem afetados.
Onde é que o meu código é executado?▾
Num ambiente isolado, separado do resto da aplicação, com um limite de tempo curto e sem acesso às credenciais da sua loja. Este ambiente apenas tem acesso à carga útil do evento que capturou, além do que obtiver através de ctx.shopify ou ctx.fetch.
E se eu editar o ficheiro no GitHub e na aplicação ao mesmo tempo?▾
Aquilo que guardar por último é o que prevalece. Ao guardar na aplicação, o código é submetido ao ficheiro, e ao enviar para o ramo ligado, o código guardado na aplicação é substituído. Se trabalhar principalmente no seu repositório, considere o editor da aplicação como sendo apenas de leitura, para evitar surpresas.
Um ficheiro no meu repositório pode criar um novo gatilho?▾
Não. Um gatilho também precisa de saber a que evento Shopify está a ouvir, e o ficheiro contém apenas código - tentar adivinhar o evento levaria a associá-lo ao elemento errado. Crie primeiro o gatilho na aplicação e, em seguida, edite o ficheiro à vontade.
Pode ser acionado por eventos que a aplicação ainda não receba?▾
Não. Um gatilho personalizado monitoriza os eventos aos quais a aplicação já está subscrita para a sua loja, o que depende das permissões que concedeu. Ao conceder permissão a um recurso, os seus eventos ficam também disponíveis para os gatilhos personalizados. Para qualquer outra situação, execute-o de acordo com um horário definido.
Próximos passos
- API para programadores, MCP, GitHub e simulação de gatilhos - gerir e testar gatilhos a partir do seu próprio código ou de um assistente de IA.
- Gerar código de trigger com IA - descreva o gatilho em linguagem simples e deixe que a IA escreva o código.
- Planos e utilização - o que se considera um evento e como funciona o subsídio.
- Como funcionam os gatilhos - os gatilhos integrados e a forma como são acionados.

