Alertas de código de desconto removido
Quando usar esse fluxo de trabalho
Utilize este fluxo de trabalho quando um código de desconto for removido e você precisar de um registro imediato do que foi afetado. Ele ajuda a registrar o código removido, o número de utilizações, os detalhes da campanha e um resumo que você pode enviar ao departamento financeiro ou de operações pelo Slack.
Isso é especialmente útil no caso de códigos de influenciadores que vazaram, divulgação não planejada de cupons ou em qualquer situação em que seja necessário um relatório documentado do impacto após a remoção de um código.
O que você vai criar
- Um fluxo de trabalho do Slack que recebe uma variável
textde um webhook e publica esse mesmo texto em um canal do Slack. - Um fluxo de trabalho Shopify Flow acionado pela remoção do código de desconto.
- Uma etapa de dados “Obter desconto” que consulta o desconto usando o ID do gatilho.
- Uma etapa de execução de código que formata um relatório de remoção.
- Uma etapa de solicitação HTTP que envia o relatório para o Slack.
Antes de começar
- Verifique se o aplicativo está instalado e visível no painel de administração do Shopify, em Apps > Workflow Trigger Extensions.
- Certifique-se de ter acesso ao site Shopify Flow.
- Crie ou escolha um canal do Slack onde os alertas devem aparecer.
- Crie um fluxo de trabalho no Slack que seja acionado por um webhook e aceite um campo
text.
Guia em vídeo
Você também pode assistir ao vídeo completo da implementação.
Primeiro, crie o fluxo de trabalho do Slack
No Slack, crie um fluxo de trabalho com o gatilho “Começa com um webhook”. Adicione uma variável de texto chamada text e, em seguida, adicione a etapa de mensagem que envia uma mensagem para o canal escolhido usando essa mesma variável text.

Conceder acesso com desconto no Workflow Trigger Extensions
Antes que o gatilho apareça no Shopify Flow, habilite o acesso aos descontos no aplicativo.
No painel de administração do Shopify, acesse Aplicativos > Workflow Trigger Extensions.
No Painel, procure a lista de verificação de configuração.
Ative a opção “Conceder acesso a descontos”. Isso habilita os gatilhos relacionados a descontos, como “Desconto criado”, “Desconto atualizado”, “Desconto excluído”, “Código de desconto adicionado”, “Código de desconto removido” e “Desconto expirado”.

Construa o Shopify Flow
Acesse Shopify Flow e crie um novo fluxo de trabalho.
Procure por gatilhos relacionados a descontos e selecione “Código de desconto removido” em “Workflow Trigger Extensions”.

Adicione a ação Shopify para obter os dados de descontos.
Em “Selecione uma consulta para filtrar dados”, escolha “Avançado”. Em “Editar consulta”, use o ID do desconto do gatilho e remova o prefixo GID Shopify:
id:"{{discount.id|remove:'gid://shopify/DiscountCodeNode/'}}"
Adicione uma etapa “Executar código” após “Obter dados de desconto”.
Use a seguinte consulta GraphQL nas entradas “Selecionar” das etapas anteriores:
query {
redeemCode {
code
usageCount
bulkRemoval
}
getDiscountData {
discount {
... on DiscountCodeBasic {
title
startsAt
endsAt
asyncUsageCount
codes {
code
asyncUsageCount
}
customerGets {
value {
... on DiscountAmount {
amount { amount currencyCode }
}
... on DiscountPercentage {
percentage
}
}
}
}
}
}
}Defina as saídas da seguinte maneira:
"Output of discount code removal report"
type Output {
"Discount code that was removed"
code: String!
"Discount campaign title"
title: String!
"Campaign start date"
startsAt: String!
"Campaign end date"
endsAt: String!
"Number of times it was redeemed"
usageCount: Int!
"Total discount impact as a formatted string"
totalImpact: String!
"When it was removed"
removedAt: String!
"Full summary for alerts"
summary: String!
}Em seguida, cole este código na área “Escrever código”:
export default function main(input) {
// ── Trigger: removed code ──
const removedCode = input?.redeemCode?.code ?? "Unknown";
const usageCount = input?.redeemCode?.usageCount ?? null; // null = bulk removal or unknown
const bulkRemoval = input?.redeemCode?.bulkRemoval ?? false;
const currency = input?.shop?.currencyCode ?? "";
const shopName = input?.shop?.name ?? "(not bound)";
const removedAt = new Date().toISOString();
// ── Find matching discount ──
const dataItems = input?.getDiscountData ?? [];
let matchedDiscount = null;
for (const item of dataItems) {
const d = item?.discount?.DiscountCodeBasic ?? item?.discount;
if (!d) continue;
const codesArray = Array.isArray(d.codes)
? d.codes.map(c => (typeof c === "string" ? c : c?.code ?? ""))
: [];
if (codesArray.includes(removedCode)) {
matchedDiscount = d;
break;
}
}
// fallback to first entry if removed code already gone from list
if (!matchedDiscount && dataItems.length > 0) {
matchedDiscount =
dataItems[0]?.discount?.DiscountCodeBasic ?? dataItems[0]?.discount ?? null;
}
const title = matchedDiscount?.title ?? "Untitled";
const startsAt = matchedDiscount?.startsAt ?? "N/A";
const endsAt = matchedDiscount?.endsAt ?? "None (no expiry)";
const totalUsageCount = matchedDiscount?.asyncUsageCount ?? null;
// ── Discount value ──
const valueWrapper = matchedDiscount?.customerGets?.value ?? {};
const pctObj = valueWrapper?.DiscountPercentage ?? null;
const amtObj = valueWrapper?.DiscountAmount ?? valueWrapper?.amount ?? null;
let discountLabel = "Unknown";
if (pctObj?.percentage != null) {
discountLabel = `${(pctObj.percentage * 100).toFixed(0)}% off`;
} else if (amtObj?.amount != null) {
const cur = amtObj.currencyCode || currency;
discountLabel = `${cur} ${parseFloat(amtObj.amount).toFixed(2)} off`;
}
// ── This code's impact ──
let thisCodeImpact;
if (bulkRemoval) {
thisCodeImpact = `Not available - removed as part of bulk deletion`;
} else if (usageCount === null) {
thisCodeImpact = `Could not be determined`;
} else if (pctObj?.percentage != null) {
thisCodeImpact = `${discountLabel} × ${usageCount} use(s)`;
} else if (amtObj?.amount != null) {
const perUse = parseFloat(amtObj.amount);
const cur = amtObj.currencyCode || currency;
thisCodeImpact = `${cur} ${(perUse * usageCount).toFixed(2)} (${cur} ${perUse.toFixed(2)} × ${usageCount} uses)`;
} else {
thisCodeImpact = "Unknown";
}
// ── Campaign-wide impact using asyncUsageCount on the discount ──
let campaignImpact;
if (totalUsageCount === null) {
campaignImpact = "Not available";
} else if (pctObj?.percentage != null) {
campaignImpact = `${discountLabel} × ${totalUsageCount} total use(s) across all codes`;
} else if (amtObj?.amount != null) {
const perUse = parseFloat(amtObj.amount);
const cur = amtObj.currencyCode || currency;
campaignImpact = `${cur} ${(perUse * totalUsageCount).toFixed(2)} total (${cur} ${perUse.toFixed(2)} × ${totalUsageCount} uses)`;
} else {
campaignImpact = "Unknown";
}
// ── Per-code breakdown ──
const codesNodes = Array.isArray(matchedDiscount?.codes)
? matchedDiscount.codes
: [];
const allCodes = codesNodes
.map(c => (typeof c === "string" ? c : c?.code ?? ""))
.filter(Boolean);
const codesRoster = codesNodes.length
? codesNodes.map(c => {
const code = typeof c === "string" ? c : c?.code ?? "";
const used = c?.asyncUsageCount ?? "?";
const flag = code === removedCode ? " ← REMOVED" : "";
return `${code} (used ${used}×)${flag}`;
}).join("\n ")
: "N/A";
const usageCountLabel = bulkRemoval
? "N/A (bulk removal)"
: usageCount !== null
? String(usageCount)
: "Unknown";
const summary =
`DISCOUNT CODE REMOVED\n` +
`─────────────────────\n` +
`Store: ${shopName}\n` +
`Code removed: ${removedCode}\n` +
`Bulk removal: ${bulkRemoval ? "Yes" : "No"}\n` +
`Campaign: ${title}\n` +
`Discount: ${discountLabel}\n` +
`Valid from: ${startsAt}\n` +
`Valid until: ${endsAt}\n` +
`\n` +
`THIS CODE\n` +
` Times used: ${usageCountLabel}\n` +
` Impact: ${thisCodeImpact}\n` +
`\n` +
`CAMPAIGN TOTAL\n` +
` Total uses: ${totalUsageCount ?? "Unknown"}\n` +
` Total impact: ${campaignImpact}\n` +
`\n` +
`CODE BREAKDOWN\n` +
` ${codesRoster}\n` +
`\n` +
`Removed at: ${removedAt}`;
const safeSummary = summary
.replace(/\\/g, "\\\\") // escape backslashes first
.replace(/"/g, '\\"') // escape quotes
.replace(/\n/g, "\\n") // escape newlines
.replace(/\r/g, "\\r");
return {
code: removedCode,
bulkRemoval,
title,
discountLabel,
startsAt,
endsAt,
usageCount: usageCount ?? 0,
usageCountLabel,
thisCodeImpact,
totalUsageCount: totalUsageCount ?? 0,
campaignImpact,
allCodes,
codesRoster,
removedAt,
summary: safeSummary,
};
}
Adicione a ação “Solicitação HTTP”. No campo “Variáveis” ou “Substituição do corpo (JSON)”, envie o resumo retornado pela etapa de código “Executar”:
{
"body": {
"text": "{{runCode.summary}}"
}
}Isso publica o resumo gerado no fluxo de trabalho do webhook do Slack usando a variável text.

Salve o fluxo de trabalho depois que todas as etapas estiverem configuradas.
Para testar, exclua um código de desconto da sua campanha de descontos e verifique se o canal do Slack recebe a mensagem de resumo.

O que o alerta do Slack inclui
- O código de desconto removido
- Seja uma remoção em grande volume
- O título da campanha
- O valor do desconto
- Datas de início e término
- Tempos utilizados para o código removido
- Impacto estimado da remoção do código
- Utilização e impacto em toda a campanha
- Uma análise detalhada código por código, quando disponível
- A data e hora em que a remoção foi processada
Solução de problemas
Volte para Aplicativos > Workflow Trigger Extensions e confirme se a opção “Conceder acesso a descontos” está ativada. Os gatilhos de desconto só aparecem depois que o acesso é concedido.
Verifique novamente a consulta avançada em “Editar consulta”. O ID deve estar formatado exatamente como mostrado:
id:"{{discount.id|remove:'gid://shopify/DiscountCodeNode/'}}"Certifique-se de que o fluxo de trabalho do Slack seja iniciado por um webhook, que a URL do webhook seja a mesma utilizada pela sua solicitação HTTP e que o corpo da solicitação inclua o campo text.
Algumas remoções podem fazer parte de uma ação em massa ou podem não retornar detalhes completos de uso. Nesses casos, o resumo ainda enviará as melhores informações disponíveis e identificará claramente os valores ausentes.
Melhores práticas
- Envie esses alertas para um canal específico de finanças ou operações, em vez de um canal geral de suporte.
- Escolha um nome específico para o fluxo de trabalho, como “Código de desconto removido”, para que seja fácil identificá-lo no Shopify Flow e no Slack.
- Teste primeiro com um código de desconto que não seja de produção para confirmar o formato da mensagem e o comportamento do webhook.

