
Shopify Admin Discount Hygiene Cleanup
- 7 installs
- 173 repo stars
- Updated June 26, 2026
- 40rty-ai/shopify-admin-skills
shopify-admin-discount-hygiene-cleanup is a Claude Code skill that finds expired, zero-usage, or duplicate Shopify discount codes and optionally deactivates or deletes them.
About
This Claude Code skill audits a Shopify store's discount catalog for expired codes, codes with zero redemptions, and duplicate prefixes, then optionally deletes the flagged codes. A store manager runs it to clear discount sprawl that accumulates over months of campaigns. It defaults to dry-run so the flagged list can be reviewed before any permanent delete.
- Finds expired, zero-usage, and duplicate discount codes
- Optionally deletes flagged codes via the Admin API with a dry-run default
- Reduces discount sprawl in the Shopify admin
Shopify Admin Discount Hygiene Cleanup by the numbers
- 7 all-time installs (skills.sh)
- Ranked #1,587 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
shopify-admin-discount-hygiene-cleanup capabilities & compatibility
Free skill; requires an authenticated Shopify store session with write_discounts scope
- Capabilities
- discount cleanup · code hygiene audit · catalog maintenance
- Use cases
- data analysis
- Runs
- Runs locally
- Pricing
- Free
What shopify-admin-discount-hygiene-cleanup says it does
Audits the discount catalog for expired codes, codes with zero redemptions, and duplicate code prefixes.
Discount sprawl accumulates over months of campaigns and makes the admin difficult to navigate. Optionally deletes flagged codes.
npx skills add https://github.com/40rty-ai/shopify-admin-skills --skill shopify-admin-discount-hygiene-cleanupAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 7 |
|---|---|
| repo stars | ★ 173 |
| Last updated | June 26, 2026 |
| Repository | 40rty-ai/shopify-admin-skills ↗ |
What it does
Audit and clean up expired, unused, and duplicate Shopify discount codes.
Who is it for?
Store managers clearing discount sprawl by finding and deleting stale codes
Skip if: Deleting codes that may be in a scheduled campaign, which needs a manual check first
When should I use this skill?
The discount catalog has grown cluttered with old or unused codes
What you get
Flagged expired, zero-usage, and duplicate codes, optionally deleted.
- discount_cleanup_<date>.csv listing flagged codes and actions
By the numbers
- zero_usage_min_age_days defaults to 30
- 2 GraphQL operations (discountNodes, discountCodeDelete)
Files
Purpose
Audits the discount catalog for expired codes, codes with zero redemptions, and duplicate code prefixes. Discount sprawl accumulates over months of campaigns and makes the admin difficult to navigate. Optionally deletes flagged codes. Replaces manual discount cleanup and builds on the discount-ab-analysis skill with a write step.
Prerequisites
- Authenticated Shopify CLI session:
shopify store auth --store <domain> --scopes read_discounts,write_discounts - API scopes:
read_discounts,write_discounts
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| store | string | yes | — | Store domain (e.g., mystore.myshopify.com) |
| flag_expired | bool | no | true | Flag/delete discounts past their end date |
| flag_zero_usage | bool | no | true | Flag/delete discounts with 0 redemptions older than N days |
| zero_usage_min_age_days | integer | no | 30 | Age threshold for zero-usage flags |
| dry_run | bool | no | true | Preview without executing mutations |
| format | string | no | human | Output format: human or json |
Safety
⚠️discountCodeDeletepermanently removes discount codes. Deleted codes cannot be recovered. Customers who received a deleted code will find it invalid. Run withdry_run: trueto review the flagged list before committing. Always check that expired codes are not referenced in active email campaigns before deleting.
Workflow Steps
1. OPERATION: discountNodes — query Inputs: first: 250, select discount { ... on DiscountCodeBasic { codes, usageLimit, asyncUsageCount, endsAt, status } }, pagination cursor Expected output: All discount codes with usage and expiry data; paginate until hasNextPage: false
2. Flag discounts matching: flag_expired (status = EXPIRED) and/or flag_zero_usage (asyncUsageCount == 0 AND created > zero_usage_min_age_days ago)
3. OPERATION: discountCodeDelete — mutation Inputs: id: <discount_node_id> Expected output: deletedCodeDiscountId, userErrors
GraphQL Operations
# discountNodes:query — validated against api_version 2025-01
query DiscountAudit($after: String) {
discountNodes(first: 250, after: $after) {
edges {
node {
id
discount {
... on DiscountCodeBasic {
title
status
createdAt
endsAt
asyncUsageCount
usageLimit
codes(first: 5) {
edges {
node {
id
code
}
}
}
}
... on DiscountCodeBxgy {
title
status
createdAt
endsAt
asyncUsageCount
usageLimit
}
... on DiscountCodeFreeShipping {
title
status
createdAt
endsAt
asyncUsageCount
usageLimit
}
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}# discountCodeDelete:mutation — validated against api_version 2025-01
mutation DiscountCodeDelete($id: ID!) {
discountCodeDelete(id: $id) {
deletedCodeDiscountId
userErrors {
field
message
}
}
}Session Tracking
Claude MUST emit the following output at each stage. This is mandatory.
On start, emit:
╔══════════════════════════════════════════════╗
║ SKILL: Discount Hygiene Cleanup ║
║ Store: <store domain> ║
║ Started: <YYYY-MM-DD HH:MM UTC> ║
╚══════════════════════════════════════════════╝After each step, emit:
[N/TOTAL] <QUERY|MUTATION> <OperationName>
→ Params: <brief summary of key inputs>
→ Result: <count or outcome>If dry_run: true, prefix every mutation step with [DRY RUN] and do not execute it.
On completion, emit:
For format: human (default):
══════════════════════════════════════════════
OUTCOME SUMMARY
Discounts scanned: <n>
Expired: <n>
Zero usage (> <n> days): <n>
Total flagged: <n>
Deleted: <n>
Errors: <n>
Output: discount_cleanup_<date>.csv
══════════════════════════════════════════════For format: json, emit:
{
"skill": "discount-hygiene-cleanup",
"store": "<domain>",
"started_at": "<ISO8601>",
"dry_run": true,
"outcome": {
"scanned": 0,
"flagged_expired": 0,
"flagged_zero_usage": 0,
"deleted": 0,
"errors": 0,
"output_file": "discount_cleanup_<date>.csv"
}
}Output Format
CSV file discount_cleanup_<YYYY-MM-DD>.csv with columns: discount_id, title, status, created_at, ends_at, usage_count, usage_limit, flag_reason, action
Error Handling
| Error | Cause | Recovery |
|---|---|---|
THROTTLED | API rate limit exceeded | Wait 2 seconds, retry up to 3 times |
userErrors on delete | Discount already deleted or active order using it | Log error, skip, continue |
| No discounts flagged | Clean discount catalog | Exit with ✅ no cleanup needed |
Best Practices
- Run quarterly — discount code sprawl accumulates quickly with seasonal campaigns.
- Check with your email marketing team before deleting zero-usage codes — they may be in a scheduled campaign that hasn't launched yet.
- Keep
flag_zero_usageage at 30+ days to avoid deleting codes from recently launched campaigns. - Automatic/percentage discounts (not code-based) are not cleaned up by this skill — those are managed separately.
Related skills
FAQ
Is deletion reversible?
No. discountCodeDelete permanently removes codes, so the skill defaults to dry_run:true to review the flagged list first.
What gets flagged as zero-usage?
Codes with zero redemptions older than zero_usage_min_age_days, which defaults to 30 days.