İndirim kodu kaldırıldı uyarıları
“İndirim Kodu Kaldırıldı” durumu için bir Shopify Flow iş akışı oluşturun ve webhook tabanlı bir Slack iş akışıyla etki özetini Slack’e gönderin.
Bu iş akışını ne zaman kullanmalı?
Bir indirim kodu kaldırıldığında ve bunun hangi öğeleri etkilediğine dair anında bir kayıt tutmanız gerektiğinde bu iş akışını kullanın. Bu iş akışı, kaldırılan kodu, kullanım sayısını, kampanya ayrıntılarını ve Slack üzerinden finans veya operasyon departmanlarına gönderebileceğiniz bir özeti kaydetmenize yardımcı olur.
Bu, özellikle sızdırılmış influencer kodları, plan dışı kupon yayınları veya bir kodun kaldırılmasının ardından belgelenmiş bir etki raporuna ihtiyaç duyulduğu her türlü durumda oldukça yararlıdır.
Ne geliştireceksiniz?
- Bir webhook'tan
textdeğişkenini alan ve aynı metni bir Slack kanalına gönderen bir Slack iş akışı. - İndirim Kodu Kaldırıldı olayıyla tetiklenen bir Shopify Flow iş akışı.
- Tetikleyiciden alınan kimliği kullanarak indirimi arayan bir İndirim Al veri adımı.
- Bir kaldırma raporunu biçimlendiren bir Kod çalıştır adımı.
- Raporu Slack’e gönderen bir HTTP Request adımı.
Başlamadan önce
- Uygulamanın yüklü olduğundan ve Shopify yönetici panelinde **Uygulamalar > Workflow Trigger Extensions **altında göründüğünden emin olun.
- Shopify Flow'a erişiminiz olduğundan emin olun.
- Uyarıların görüntüleneceği bir Slack kanalı oluşturun veya seçin.
- Bir webhook ile başlayan ve
textalanını kabul eden bir Slack iş akışı oluşturun.
Video Kılavuzu
Uygulamanın tamamını gösteren videoyu da izleyebilirsiniz.
Öncelikle Slack iş akışını oluşturun
Slack'te, Webhook ile başlar tetikleyicisine sahip bir iş akışı oluşturun. text adlı bir metin değişkeni ekleyin, ardından aynı text değişkenini kullanarak seçtiğiniz kanala mesaj gönderen mesaj adımını ekleyin.

Workflow Trigger Extensions’da İndirimli Erişim İzni Verme
Shopify Flow'da tetikleyici görünmeden önce, uygulamada indirim erişimini etkinleştirin.
Shopify yönetici panelinde, **Uygulamalar > Workflow Trigger Extensions **seçeneğine gidin.
Kontrol Panelinde kurulum kontrol listesini bulun.
İndirim Erişimi Ver seçeneğini etkinleştirin. Bu, İndirim Oluşturuldu, İndirim Güncellendi, İndirim Silindi, İndirim Kodu Eklendi, İndirim Kodu Kaldırıldı ve İndirim Süresi Doldu gibi indirimle ilgili tetikleyicileri etkinleştirir.

Shopify Flow'u oluşturun
Shopify Flow'u açın ve yeni bir iş akışı oluşturun.
İndirimle ilgili tetikleyicileri arayın ve Workflow Trigger Extensions bölümünden İndirim Kodu Kaldırıldı seçeneğini seçin.

Shopify’ın “İndirim verilerini al” eylemini ekleyin.
Verileri filtrelemek için bir sorgu seçin bölümünde Gelişmiş seçeneğini seçin. Sorguyu düzenle bölümünde, tetikleyiciden alınan indirim kimliğini kullanın ve Shopify GID önekini kaldırın:
id:"{{discount.id|remove:'gid://shopify/DiscountCodeNode/'}}"
İndirim verilerini al adımından sonra bir Kodu çalıştır adımı ekleyin.
Önceki adımlarda seçtiğiniz girişlerde aşağıdaki GraphQL sorgusunu kullanın:
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
}
}
}
}
}
}
}Çıktıları şu şekilde tanımlayın:
"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!
}Ardından bu kodu Kod yaz alanına yapıştırın:
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,
};
}
HTTP Request eylemini ekleyin. Değişkenler veya Gövde Geçersiz Kılma (JSON) alanına, Run code adımının döndürdüğü özeti gönderin:
{
"body": {
"text": "{{runCode.summary}}"
}
}Bu işlem, oluşturulan özeti text değişkenini kullanarak Slack webhook iş akışına gönderir.

Tüm adımlar tamamlandıktan sonra iş akışını kaydedin.
Test etmek için, indirim kampanyanızdan bir indirim kodunu silin ve Slack kanalının özet mesajını aldığını doğrulayın.

Slack uyarısında neler yer alır?
- Kaldırılan indirim kodu
- İster toplu taşıma olsun
- Kampanyanın adı
- İndirim tutarı
- Başlangıç ve bitiş tarihleri
- Kaldırılan kod için kullanılan süreler
- Kaldırılan kodun tahmini etkisi
- Kampanya genelinde kullanım ve etki
- Mümkün olduğunda kod bazında ayrıntılı döküm
- Silme işleminin gerçekleştirildiği zaman damgası
Sorun Giderme
Uygulamalar > İş Akışı Tetikleyici Uzantıları’na (Workflow Trigger Extensions) geri dönün ve İndirim Erişimi Ver seçeneğinin etkinleştirildiğini kontrol edin. İndirim tetikleyicileri, erişim izni verildikten sonra görünür.
Sorguyu Düzenle bölümündeki gelişmiş sorguyu bir kez daha kontrol edin. Kimlik, tam olarak gösterildiği gibi temizlenmiş olmalıdır:
id:"{{discount.id|remove:'gid://shopify/DiscountCodeNode/'}}"Slack iş akışının bir webhook ile başladığından, webhook URL’sinin HTTP isteğinizde kullanılan URL ile aynı olduğundan ve istek gövdesinde text alanının bulunduğundan emin olun.
Bazı silme işlemleri toplu işlemlerin bir parçası olabilir veya tam kullanım ayrıntılarını döndürmeyebilir. Bu durumlarda özet, yine de mevcut en iyi bilgileri gönderecek ve eksik değerleri açıkça belirtecektir.
En iyi uygulamalar
- Bu uyarıları genel destek kanalı yerine, finans veya operasyonlara özel bir kanala gönderin.
- İş akışı adını, örneğin İndirim Kodu Kaldırıldı gibi net ve belirgin bir şekilde belirleyin; böylece Shopify Flow ve Slack’te kolayca tanınabilir.
- Öncelikle, mesaj biçimini ve webhook davranışını doğrulamak için üretim ortamı dışındaki bir indirim koduyla test yapın.
