Meldingen over verwijderde kortingscodes
Wanneer moet deze workflow worden gebruikt?
Gebruik deze workflow wanneer een kortingscode wordt verwijderd en je direct wilt weten welke gegevens hierdoor zijn beïnvloed. Hiermee kun je de verwijderde code, het aantal keren dat deze is gebruikt, de campagnegegevens en een overzicht vastleggen dat je via Slack naar de financiële afdeling of de operationele afdeling kunt sturen.
Dit is met name handig bij gelekte influencercodes, onbedoelde bekendmaking van kortingsbonnen of in alle gevallen waarin je een gedocumenteerd effectrapport nodig hebt nadat een code is verwijderd.
Wat je gaat bouwen
- Een Slack-workflow die via een webhook de variabele
textontvangt en diezelfde tekst in een Slack-kanaal plaatst. - Een Shopify Flow-workflow die wordt geactiveerd door 'Discount Code Removed'.
- Een gegevensstap ‘Korting ophalen’ die de korting opzoekt aan de hand van het ID uit de trigger.
- Een stap ‘Code uitvoeren’ waarmee een verwijderingsrapport wordt opgemaakt.
- Een HTTP-verzoekstap waarmee het rapport naar Slack wordt verzonden.
Voordat je begint
- Zorg ervoor dat de app is geïnstalleerd en zichtbaar is in de beheerdersomgeving van Shopify onder Apps > Workflow Trigger Extensions.
- Zorg ervoor dat je toegang hebt tot Shopify Flow.
- Maak een Slack-kanaal aan of kies er een uit waarin meldingen moeten verschijnen.
- Maak een Slack-workflow die wordt gestart door een webhook en waarin het veld
textkan worden ingevuld.
Videogids
Je kunt ook de volledige implementatievideo bekijken.
Maak eerst de Slack-workflow aan
Maak in Slack een workflow aan met de trigger ‘Begint met een webhook’. Voeg een tekstvariabele toe met de naam text en voeg vervolgens de stap ‘Bericht’ toe, waarmee je een bericht naar het door jou gekozen kanaal verstuurt met behulp van diezelfde variabele text.

Kortingstoegang toekennen in de Workflow Trigger Extensions
Schakel de toegang tot kortingen in de app in voordat de trigger in Shopify Flow verschijnt.
Ga in de beheerdersomgeving van Shopify naar Apps > Workflow Trigger Extensions.
Zoek op het dashboard naar de installatiechecklist.
Schakel ‘Toegang tot kortingen toestaan’ in. Hierdoor worden kortingsgerelateerde triggers ingeschakeld, zoals ‘Korting aangemaakt’, ‘Korting bijgewerkt’, ‘Korting verwijderd’, ‘Kortingscode toegevoegd’, ‘Kortingscode verwijderd’ en ‘Korting verlopen’.

Bouw de Shopify Flow
Ga naar Shopify Flow en maak een nieuwe workflow aan.
Zoek naar triggers die verband houden met kortingen en selecteer ‘Kortingscode verwijderd’ uit ‘Workflow Trigger Extensions’.

Voeg de actie Shopify toe: ‘Kortingsgegevens ophalen’.
Kies bij ‘Selecteer een query om gegevens te filteren’ de optie ‘Geavanceerd’. Gebruik in ‘Query bewerken’ de kortings-ID uit de trigger en verwijder het GID-voorvoegsel Shopify:
id:"{{discount.id|remove:'gid://shopify/DiscountCodeNode/'}}"
Voeg een stap ‘Code uitvoeren’ toe na ‘Kortingsgegevens ophalen’.
Gebruik de volgende GraphQL-query in de invoervelden die je in de vorige stappen hebt geselecteerd:
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
}
}
}
}
}
}
}Definieer de uitgangen als volgt:
"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!
}Plak vervolgens deze code in het veld ‘Code invoeren’:
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,
};
}
Voeg de actie ‘HTTP-verzoek’ toe. Voer in het veld ‘Variabelen’ of ‘Body Override (JSON)’ de samenvatting in die door de stap ‘Code uitvoeren’ is geretourneerd:
{
"body": {
"text": "{{runCode.summary}}"
}
}Hiermee wordt de gegenereerde samenvatting naar de Slack-webhook-workflow verzonden met behulp van de variabele text.

Sla de workflow op zodra alle stappen zijn voltooid.
Probeer het volgende eens: verwijder een kortingscode uit je kortingscampagne en controleer of het Slack-kanaal het samenvattingsbericht ontvangt.

Wat de Slack-melding bevat
- De verwijderde kortingscode
- Of het nu ging om een grote opruiming
- De titel van de campagne
- De kortingswaarde
- Begin- en einddatum
- Tijden die voor de verwijderde code werden gebruikt
- Geschatte gevolgen van het verwijderen van de code
- Gebruik en impact op campagne-niveau
- Een uitsplitsing per code, indien beschikbaar
- Het tijdstip waarop de verwijdering is verwerkt
Problemen oplossen
Ga terug naar Apps > Workflow Trigger Extensions en controleer of ‘Toegang tot kortingen verlenen’ is ingeschakeld. De kortingstriggers verschijnen pas nadat toegang is verleend.
Controleer de geavanceerde zoekopdracht nogmaals in ‘Zoekopdracht bewerken’. Het ID moet precies zo zijn opgeschoond als hier weergegeven:
id:"{{discount.id|remove:'gid://shopify/DiscountCodeNode/'}}"Zorg ervoor dat de Slack-workflow begint met een webhook, dat de URL van de webhook dezelfde is als die in je HTTP-verzoek, en dat de verzoektekst het veld text bevat.
Sommige verwijderingen kunnen deel uitmaken van een bulkactie of geven mogelijk geen volledige gebruiksgegevens weer. In die gevallen bevat het overzicht nog steeds de best beschikbare informatie en worden ontbrekende waarden duidelijk aangegeven.
Beste praktijken
- Stuur deze meldingen naar een speciaal kanaal voor financiën of bedrijfsvoering in plaats van naar een algemeen ondersteuningskanaal.
- Geef de workflow een specifieke naam, zoals ‘Kortingscode verwijderd’, zodat deze gemakkelijk te herkennen is in Shopify Flow en Slack.
- Test eerst met een kortingscode die niet voor productiegebruik is bedoeld om het berichtformaat en het gedrag van de webhook te controleren.

