From shopify-admin-skills
Bulk generates unique Shopify discount codes via GraphQL mutations for campaigns, giveaways, or partner distributions. Creates individual DiscountCodeBasic nodes with configurable usage limits and validity.
npx claudepluginhub 40rty-ai/shopify-admin-skills --plugin shopify-admin-skillsThis skill uses the workspace's default tool permissions.
Generates N unique discount codes (e.g., 100 codes for an influencer giveaway, 500 for a partner distribution drop) with a shared prefix and configurable value, usage limit, and validity window. Each code is created as a standalone `DiscountCodeBasic` discount node so it can be tracked independently in Shopify Admin and revoked individually if leaked. Typical use: handing each code to a differe...
Finds expired, zero-usage, or duplicate Shopify discount codes and optionally deactivates or deletes them via Admin GraphQL API.
Manages Wix coupons via REST API: queries active/expired/usage-based lists, creates fixed-amount/percentage discounts, supports campaign templates, conflict detection, margin calculations. For e-commerce discount strategies.
Configures Saleor promotions: catalog/order promotions, vouchers, manual discounts, gift cards, stacking rules. Guides GraphQL mutations for pricing setup.
Share bugs, ideas, or general feedback.
Generates N unique discount codes (e.g., 100 codes for an influencer giveaway, 500 for a partner distribution drop) with a shared prefix and configurable value, usage limit, and validity window. Each code is created as a standalone DiscountCodeBasic discount node so it can be tracked independently in Shopify Admin and revoked individually if leaked. Typical use: handing each code to a different recipient where each redemption must be tied to one person.
shopify store auth --store <domain> --scopes write_discountsread_discounts, write_discounts| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| store | string | yes | — | Store domain (e.g., mystore.myshopify.com) |
| format | string | no | human | Output format: human or json |
| dry_run | bool | no | true | Preview the codes that would be created without executing mutations |
| prefix | string | yes | — | Prefix for every generated code (e.g., GIVEAWAY produces GIVEAWAY-A4F2X9) |
| count | integer | yes | — | Number of unique codes to generate (max 1000 per run) |
| value_type | string | yes | — | Discount type: percentage, fixed_amount, or free_shipping |
| value | float | conditional | — | Numeric value: percent off (1–100) for percentage; currency amount for fixed_amount; ignored for free_shipping |
| usage_limit | integer | no | 1 | How many times each individual code can be redeemed |
| starts_at | string | no | now | ISO8601 datetime when codes become valid |
| ends_at | string | no | — | ISO8601 datetime when codes expire (omit for no expiry) |
| applies_to | string | no | order | Code applies to: order (entire order) or shipping_only (with free_shipping value type) |
⚠️ Step 1 executes one
discountCodeBasicCreatemutation per generated code. Once created, codes appear immediately in Shopify Admin and become redeemable atstarts_at. Codes cannot be deleted in bulk via the Admin API — they must be removed individually withdiscountCodeDelete. Run withdry_run: trueto confirm the count, prefix, and value before committing. The default isdry_run: true. For high counts (>100), confirmusage_limitmatches intent — a single high-limit code is usually preferable to N single-use codes if uniqueness per recipient is not required.
Generate count unique random suffixes (6 alphanumeric uppercase characters per suffix). Concatenate as <prefix>-<suffix>. Validate no in-memory duplicates and no length > 32.
OPERATION: discountCodeBasicCreate — mutation (one call per code)
Inputs: basicCodeDiscount.title: "<prefix> bulk generation <date>", basicCodeDiscount.code: <generated_code>, basicCodeDiscount.startsAt: <starts_at>, basicCodeDiscount.endsAt: <ends_at>, basicCodeDiscount.usageLimit: <usage_limit>, basicCodeDiscount.appliesOncePerCustomer: true, basicCodeDiscount.customerGets.value: percent / fixed-amount / free-shipping union per value_type, basicCodeDiscount.customerGets.items.all: true, basicCodeDiscount.customerSelection.all: true
Expected output: codeDiscountNode.id, codeDiscountNode.codeDiscount.codes.edges[0].node.code, userErrors
# discountCodeBasicCreate:mutation — validated against api_version 2025-01
mutation PromoCodeCreate($basicCodeDiscount: DiscountCodeBasicInput!) {
discountCodeBasicCreate(basicCodeDiscount: $basicCodeDiscount) {
codeDiscountNode {
id
codeDiscount {
... on DiscountCodeBasic {
title
startsAt
endsAt
usageLimit
appliesOncePerCustomer
codes(first: 1) {
edges {
node {
code
}
}
}
customerGets {
value {
... on DiscountPercentage {
percentage
}
... on DiscountAmount {
amount {
amount
currencyCode
}
}
... on DiscountOnQuantity {
effect {
... on DiscountPercentage {
percentage
}
}
}
}
}
}
}
}
userErrors {
field
message
code
}
}
}
Claude MUST emit the following output at each stage. This is mandatory.
On start, emit:
╔══════════════════════════════════════════════╗
║ SKILL: Promo Code Bulk Generator ║
║ 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):
══════════════════════════════════════════════
PROMO CODE BULK GENERATION
Prefix: <prefix>
Codes requested: <n>
Codes created: <n> (or "skipped — dry_run")
Value type: <type>
Value: <amount>
Usage limit/code: <n>
Valid: <starts_at> → <ends_at>
Errors: <n>
Output: promo_codes_<prefix>_<date>.csv
══════════════════════════════════════════════
For format: json, emit:
{
"skill": "promo-code-bulk-generator",
"store": "<domain>",
"started_at": "<ISO8601>",
"completed_at": "<ISO8601>",
"dry_run": true,
"prefix": "<prefix>",
"outcome": {
"codes_requested": 0,
"codes_created": 0,
"value_type": "<type>",
"value": 0,
"usage_limit_per_code": 1,
"starts_at": "<ISO8601>",
"ends_at": "<ISO8601 or null>",
"errors": 0,
"output_file": "promo_codes_<prefix>_<date>.csv"
}
}
CSV file promo_codes_<prefix>_<YYYY-MM-DD>.csv with columns:
code, discount_node_id, value_type, value, usage_limit, starts_at, ends_at, created_at, status
| Error | Cause | Recovery |
|---|---|---|
THROTTLED | API rate limit exceeded | Wait 2 seconds, retry up to 3 times |
userErrors.code: TAKEN | Code collision with existing discount | Regenerate suffix and retry that code |
userErrors invalid value | Percentage outside 1–100 or negative fixed amount | Validate before submission |
count > 1000 | Run-size guardrail | Split into multiple runs |
| Network failure mid-batch | Partial completion | CSV records created vs pending; rerun with the pending suffix list only |
usage_limit: 1 for influencer-style giveaways where each recipient gets a private code; use usage_limit: N only when codes are distributed publicly with a hard cap.prefix (e.g., INFLUENCER-Q2, GIVEAWAY-LAUNCH) so codes are easy to filter in Shopify Admin and in revenue reports.ends_at — open-ended codes lead to long-tail discount cost and complicate ROI analysis.dry_run: true first and inspect the generated suffixes; codes are not deletable in bulk if a mistake is made.free_shipping, set applies_to: shipping_only and leave value unset; Shopify ignores numeric value for free-shipping discounts.discount-roi-calculator after the campaign to measure ROI per code prefix.