coupon-management
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCoupon Management
优惠券管理
Overview
概述
Coupon systems let merchants create promotional codes with configurable rules: percentage or fixed-amount discounts, minimum order requirements, usage limits per coupon or per customer, and expiration dates. Every major e-commerce platform includes a built-in coupon system — you almost never need to build one from scratch. This skill walks you through setting up coupon management on each platform and explains when to reach for an app or plugin for advanced requirements like bulk unique codes or campaign tracking.
优惠券系统允许商家创建可配置规则的促销码:百分比或固定金额折扣、最低订单要求、单优惠券或单客户使用限制,以及有效期。所有主流电商平台都内置了优惠券系统,你几乎不需要从零开始搭建。本指南将教你如何在各个平台上配置优惠券管理功能,并说明何时需要使用应用或插件来满足批量唯一码生成或活动追踪等高级需求。
When to Use This Skill
何时使用本指南
- When adding promotional codes to a checkout flow for the first time
- When migrating from a simple discount field to a rule-based coupon engine
- When running marketing campaigns that require unique, single-use codes for each recipient
- When building an admin interface to create and monitor coupon performance
- When enforcing complex coupon rules such as product/category exclusions or customer segment restrictions
- 首次在结算流程中添加促销码功能时
- 从简单的折扣字段迁移到基于规则的优惠券引擎时
- 开展需要为每个接收方提供唯一一次性码的营销活动时
- 搭建用于创建和监控优惠券效果的管理界面时
- 需要执行复杂的优惠券规则,比如商品/品类排除或客户群体限制时
Core Instructions
核心操作说明
Step 1: Determine the merchant's platform and the right tool
步骤1:确定商家的平台和合适的工具
| Platform | Built-in Capability | When to Add an App/Plugin |
|---|---|---|
| Shopify | Shopify Discounts — supports percentage, fixed amount, free shipping, BOGO; usage limits, expiry, minimum purchase | When you need bulk unique codes (Shopify supports import), customer-group-specific coupons, or loyalty integration (Smile.io, LoyaltyLion) |
| WooCommerce | WooCommerce Coupons — built into core; percentage, fixed cart, fixed product, free shipping types | When you need bulk unique code generation: WooCommerce Smart Coupons plugin; advanced rules: YITH WooCommerce Dynamic Pricing & Discounts |
| BigCommerce | Coupon codes built in — percentage, fixed amount, free shipping, free product types | When you need B2B-specific codes or advanced restrictions; BigCommerce app marketplace has options like Coupon Manager Pro |
| Custom / Headless | Must build — see Custom section below | N/A — you are building the system |
| 平台 | 内置能力 | 何时需要添加应用/插件 |
|---|---|---|
| Shopify | Shopify Discounts — 支持百分比折扣、固定金额折扣、免邮、买一送一;支持使用限制、有效期、最低消费 | 需要批量唯一码(Shopify支持导入)、特定客户群体优惠券或忠诚度系统集成(Smile.io、LoyaltyLion)时 |
| WooCommerce | WooCommerce Coupons — 核心内置功能;支持百分比折扣、固定购物车折扣、固定商品折扣、免邮类型 | 需要批量生成唯一码时可使用WooCommerce Smart Coupons插件;需要高级规则时可使用YITH WooCommerce Dynamic Pricing & Discounts |
| BigCommerce | 内置优惠券码功能 — 支持百分比折扣、固定金额折扣、免邮、免费商品类型 | 需要B2B专属码或高级限制规则时;BigCommerce应用市场有Coupon Manager Pro等可选工具 |
| 自定义 / Headless | 必须自行搭建 — 见下方自定义部分 | 不适用 — 你正在自主构建系统 |
Step 2: Set up standard coupons on your platform
步骤2:在你的平台上配置标准优惠券
Shopify
Shopify
- Go to Discounts in the Shopify admin sidebar
- Click Create discount and choose the type:
- Amount off products — percentage or fixed amount off specific products/collections
- Amount off order — percentage or fixed amount off the entire cart
- Buy X get Y — BOGO and bundle offers
- Free shipping — removes shipping cost when code is applied
- Configure the code:
- Enter a code (e.g., ) or click Generate code for a random one
SUMMER20 - Set Minimum purchase requirements (minimum subtotal or minimum quantity)
- Set Customer eligibility — all customers, specific customer segments, or specific customers
- Set Maximum discount uses — total uses and/or one use per customer
- Set Active dates — start and optional end date
- Enter a code (e.g.,
- Click Save discount
Bulk unique codes on Shopify:
- In the same Discounts screen, choose Generate codes instead of entering a single code
- Set the quantity (up to 100 at a time from the UI; use the Shopify Admin API for larger volumes)
- All generated codes share the same rules (discount value, expiry, usage limits)
- Export the codes to CSV for use in your email marketing platform
Shopify Plus — Shopify Scripts for advanced stacking:
- Use Shopify Scripts (Shopify Plus only) for custom coupon logic: e.g., different discount percentages by customer tag, auto-apply coupons without a code
- Access via Apps → Script Editor in your Shopify admin
- 进入Shopify后台侧边栏的Discounts模块
- 点击Create discount并选择类型:
- Amount off products — 特定商品/系列的百分比或固定金额折扣
- Amount off order — 整个购物车的百分比或固定金额折扣
- Buy X get Y — 买一送一和捆绑优惠
- Free shipping — 应用优惠码后免除运费
- 配置优惠码:
- 输入优惠码(例如)或点击Generate code获取随机码
SUMMER20 - 设置Minimum purchase requirements(最低购买要求:最低小计金额或最低购买数量)
- 设置Customer eligibility(客户资格:所有客户、特定客户群体或特定客户)
- 设置Maximum discount uses(最大折扣使用次数:总使用次数和/或单客户仅用一次)
- 设置Active dates(生效日期:开始日期和可选的结束日期)
- 输入优惠码(例如
- 点击Save discount
Shopify批量唯一码生成:
- 在同一折扣页面,选择Generate codes而非输入单个代码
- 设置数量(UI界面一次最多生成100个;更大批量可使用Shopify Admin API)
- 所有生成的代码共享相同规则(折扣值、有效期、使用限制)
- 将代码导出为CSV,用于你的邮件营销平台
Shopify Plus — 高级叠加规则使用Shopify Scripts:
- 使用Shopify Scripts(仅Shopify Plus支持)实现自定义优惠券逻辑:例如根据客户标签设置不同的折扣比例、无需输入代码自动应用优惠券
- 可通过Shopify后台的Apps → Script Editor访问
WooCommerce
WooCommerce
- Go to WooCommerce → Coupons → Add coupon
- Set the Coupon code (unique identifier customers type at checkout)
- Under General tab:
- Discount type: Percentage discount, Fixed cart discount, Fixed product discount
- Coupon amount: The discount value
- Free shipping: Toggle to make this code grant free shipping
- Coupon expiry date: Date after which the code stops working
- Under Usage restriction tab:
- Minimum spend: Cart subtotal must exceed this amount
- Maximum spend: Cart subtotal cannot exceed this amount
- Individual use only: Cannot be combined with other coupons
- Exclude sale items: Don't apply to already-reduced items
- Products and Exclude products: Restrict or exclude specific products
- Product categories and Exclude categories: Restrict or exclude by category
- Email restrictions: Limit to specific customer emails
- Under Usage limits tab:
- Usage limit per coupon: Total number of times this code can be used
- Usage limit per user: How many times a single customer can use it
- Click Publish
Bulk unique codes on WooCommerce:
- Install WooCommerce Smart Coupons (premium plugin, ~$99/year from StoreApps)
- Go to WooCommerce → Smart Coupons → Generate Coupons
- Set quantity, discount amount, expiry, and prefix — generates a CSV of unique codes
- Import or distribute via your email platform
- 进入WooCommerce → Coupons → Add coupon
- 设置Coupon code(客户在结算时输入的唯一标识)
- 在General标签下:
- Discount type:百分比折扣、固定购物车折扣、固定商品折扣
- Coupon amount:折扣值
- Free shipping:开启后使用该码可享受免邮
- Coupon expiry date:超过该日期后码失效
- 在Usage restriction标签下:
- Minimum spend:购物车小计必须超过该金额
- Maximum spend:购物车小计不能超过该金额
- Individual use only:不可与其他优惠券叠加
- Exclude sale items:不适用于已经降价的商品
- Products和Exclude products:限制或排除特定商品
- Product categories和Exclude categories:按品类限制或排除
- Email restrictions:仅特定客户邮箱可使用
- 在Usage limits标签下:
- Usage limit per coupon:该码总共可使用的次数
- Usage limit per user:单个客户可使用的次数
- 点击Publish
WooCommerce批量唯一码生成:
- 安装WooCommerce Smart Coupons(付费插件,StoreApps出品,约99美元/年)
- 进入WooCommerce → Smart Coupons → Generate Coupons
- 设置数量、折扣金额、有效期和前缀 — 会生成包含唯一码的CSV文件
- 导入或通过你的邮件平台分发
BigCommerce
BigCommerce
- Go to Marketing → Coupon Codes → Create Coupon Code
- Fill in:
- Code: The code customers enter (or use the auto-generate button)
- Type: Percentage off order, Dollar amount off order, Percentage off product, Dollar amount off product, Free shipping, Free product
- Discount amount: The value
- Applies to: All items, items from specific categories, or specific products
- Under Restrictions:
- Minimum order: Subtotal must exceed this amount
- Max uses: Total redemptions allowed
- Max uses per customer: Per-account limit
- Expiration date: When the code stops working
- Click Save
Bulk codes on BigCommerce:
Use the BigCommerce Promotions API () to generate codes programmatically, then export for distribution.
POST /v2/coupons- 进入Marketing → Coupon Codes → Create Coupon Code
- 填写:
- Code:客户输入的优惠码(或使用自动生成按钮)
- Type:订单百分比折扣、订单固定金额折扣、商品百分比折扣、商品固定金额折扣、免邮、免费商品
- Discount amount:折扣值
- Applies to:所有商品、特定品类商品或特定商品
- 在Restrictions下:
- Minimum order:小计必须超过该金额
- Max uses:总兑换次数上限
- Max uses per customer:单账号使用上限
- Expiration date:码失效的日期
- 点击Save
BigCommerce批量码生成:
使用BigCommerce Promotions API()以编程方式生成码,然后导出用于分发。
POST /v2/couponsCustom / Headless
自定义 / Headless
For headless stores, you need to build the validation and redemption logic. The key requirements are atomic redemption (prevent race conditions when two customers use the last available redemption simultaneously) and idempotent order processing.
typescript
// Coupon validation at checkout
async function validateCoupon(
code: string,
customerId: string,
orderSubtotalCents: number
): Promise<{ valid: boolean; discountCents: number; error?: string }> {
const coupon = await db.coupons.findOne({ code: code.toUpperCase().trim(), is_active: true });
if (!coupon) return { valid: false, discountCents: 0, error: 'Code not found' };
const now = new Date();
if (coupon.expires_at && coupon.expires_at < now) return { valid: false, discountCents: 0, error: 'Code expired' };
if (coupon.usage_limit && coupon.usage_count >= coupon.usage_limit) return { valid: false, discountCents: 0, error: 'Code fully used' };
if (coupon.min_order_cents && orderSubtotalCents < coupon.min_order_cents) return { valid: false, discountCents: 0, error: `Minimum order $${coupon.min_order_cents / 100}` };
// Per-customer limit check
if (coupon.per_customer_limit) {
const uses = await db.couponRedemptions.count({ coupon_id: coupon.id, customer_id: customerId });
if (uses >= coupon.per_customer_limit) return { valid: false, discountCents: 0, error: 'Already used' };
}
const discountCents = coupon.type === 'percentage'
? Math.round(orderSubtotalCents * (coupon.value / 100))
: Math.min(coupon.value_cents, orderSubtotalCents);
return { valid: true, discountCents };
}
// Atomic redemption — use inside the order creation transaction
async function redeemCoupon(tx: Tx, couponId: string, customerId: string, orderId: string, discountCents: number) {
// Atomic increment with guard — prevents over-redemption under concurrency
const result = await tx.raw(
`UPDATE coupons SET usage_count = usage_count + 1
WHERE id = ? AND (usage_limit IS NULL OR usage_count < usage_limit)
RETURNING id`,
[couponId]
);
if (result.rowCount === 0) throw new Error('COUPON_EXHAUSTED');
await tx.couponRedemptions.insert({ coupon_id: couponId, customer_id: customerId, order_id: orderId, discount_cents: discountCents });
}Bulk code generation for email campaigns:
typescript
import crypto from 'crypto';
function generateCode(prefix = 'PROMO', length = 8): string {
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // no ambiguous chars
return prefix + '-' + Array.from(crypto.randomBytes(length))
.map(b => chars[b % chars.length]).join('');
}
async function bulkGenerate(template: CouponTemplate, quantity: number): Promise<string[]> {
const codes: string[] = [];
while (codes.length < quantity) {
const batch = Array.from({ length: Math.min(500, quantity - codes.length) }, () => generateCode(template.prefix));
const inserted = await db.coupons.insertMany(
batch.map(code => ({ ...template, code, usage_limit: 1, per_customer_limit: 1 })),
{ onConflict: 'ignore' }
);
codes.push(...inserted.map(r => r.code));
}
return codes;
}对于Headless店铺,你需要自行构建校验和兑换逻辑。核心要求是原子兑换(防止两个客户同时使用最后一个可兑换额度时出现竞态条件)和幂等订单处理。
typescript
// Coupon validation at checkout
async function validateCoupon(
code: string,
customerId: string,
orderSubtotalCents: number
): Promise<{ valid: boolean; discountCents: number; error?: string }> {
const coupon = await db.coupons.findOne({ code: code.toUpperCase().trim(), is_active: true });
if (!coupon) return { valid: false, discountCents: 0, error: 'Code not found' };
const now = new Date();
if (coupon.expires_at && coupon.expires_at < now) return { valid: false, discountCents: 0, error: 'Code expired' };
if (coupon.usage_limit && coupon.usage_count >= coupon.usage_limit) return { valid: false, discountCents: 0, error: 'Code fully used' };
if (coupon.min_order_cents && orderSubtotalCents < coupon.min_order_cents) return { valid: false, discountCents: 0, error: `Minimum order $${coupon.min_order_cents / 100}` };
// Per-customer limit check
if (coupon.per_customer_limit) {
const uses = await db.couponRedemptions.count({ coupon_id: coupon.id, customer_id: customerId });
if (uses >= coupon.per_customer_limit) return { valid: false, discountCents: 0, error: 'Already used' };
}
const discountCents = coupon.type === 'percentage'
? Math.round(orderSubtotalCents * (coupon.value / 100))
: Math.min(coupon.value_cents, orderSubtotalCents);
return { valid: true, discountCents };
}
// Atomic redemption — use inside the order creation transaction
async function redeemCoupon(tx: Tx, couponId: string, customerId: string, orderId: string, discountCents: number) {
// Atomic increment with guard — prevents over-redemption under concurrency
const result = await tx.raw(
`UPDATE coupons SET usage_count = usage_count + 1
WHERE id = ? AND (usage_limit IS NULL OR usage_count < usage_limit)
RETURNING id`,
[couponId]
);
if (result.rowCount === 0) throw new Error('COUPON_EXHAUSTED');
await tx.couponRedemptions.insert({ coupon_id: couponId, customer_id: customerId, order_id: orderId, discount_cents: discountCents });
}邮件活动批量码生成:
typescript
import crypto from 'crypto';
function generateCode(prefix = 'PROMO', length = 8): string {
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // no ambiguous chars
return prefix + '-' + Array.from(crypto.randomBytes(length))
.map(b => chars[b % chars.length]).join('');
}
async function bulkGenerate(template: CouponTemplate, quantity: number): Promise<string[]> {
const codes: string[] = [];
while (codes.length < quantity) {
const batch = Array.from({ length: Math.min(500, quantity - codes.length) }, () => generateCode(template.prefix));
const inserted = await db.coupons.insertMany(
batch.map(code => ({ ...template, code, usage_limit: 1, per_customer_limit: 1 })),
{ onConflict: 'ignore' }
);
codes.push(...inserted.map(r => r.code));
}
return codes;
}Best Practices
最佳实践
- Normalize codes to uppercase — store and compare codes in uppercase and trim whitespace to prevent "code not found" errors from minor formatting differences
- Use single-use codes for targeted campaigns — set usage limit to 1 per code when distributing unique codes via email to prevent sharing
- Validate at order creation, not just at cart — re-check coupon validity (expiry, usage limits) when the order is actually placed to handle race conditions
- Soft-delete coupons — deactivate rather than delete to preserve redemption history for accounting
- Track discount abuse — if a customer has abandoned and recovered with a discount code three or more times, consider excluding them from discount campaigns
- Cap maximum discount amounts — for percentage coupons, set a maximum dollar discount to prevent runaway promotions (e.g., 20% off capped at $50)
- 将码统一转为大写存储 — 存储和比对码时统一转为大写并修剪空白字符,避免因微小格式差异导致的「码未找到」错误
- 定向活动使用一次性码 — 通过邮件分发唯一码时,将单码使用限制设为1,防止码被共享
- 订单创建时再次校验,而非仅在购物车阶段校验 — 订单实际提交时重新检查优惠券有效性(有效期、使用限制),处理竞态条件
- 软删除优惠券 — 停用而非删除优惠券,以保留兑换历史用于财务核算
- 追踪折扣滥用 — 如果客户三次或以上使用折扣码遗弃后又恢复订单,可考虑将其排除在折扣活动之外
- 设置最大折扣金额上限 — 对于百分比折扣优惠券,设置最高美元折扣上限,避免促销成本失控(例如20%折扣,上限50美元)
Common Pitfalls
常见问题
| Problem | Solution |
|---|---|
| Two customers redeem the last use simultaneously | Use atomic |
| Coupon still valid after order cancellation | Decrement the usage count when an order is cancelled or refunded; Shopify does this automatically |
| Per-customer limit bypassed with multiple accounts | Supplement customer-ID checks with email checks; for high-value campaigns, require verified phone numbers |
| Bulk-generated codes collide with existing ones | Use |
| Free-shipping coupon stacks with a percentage discount unexpectedly | Define your stacking policy explicitly; on Shopify, use the "Can be combined with" settings on each discount |
| 问题 | 解决方案 |
|---|---|
| 两个客户同时兑换最后一次使用额度 | 自定义构建时使用原子 |
| 订单取消后优惠券仍显示已使用 | 订单取消或退款时扣减使用次数;Shopify会自动处理该逻辑 |
| 使用多个账号绕过单客户限制 | 在客户ID校验之外补充邮箱校验;高价值活动要求验证手机号 |
| 批量生成的码与已有码冲突 | 使用 |
| 免邮优惠券意外与百分比折扣叠加 | 明确定义叠加规则;在Shopify中可在每个折扣的「可叠加使用」设置中配置 |
Related Skills
相关技能
- @discount-engine
- @price-rules-engine
- @ab-testing-pricing
- @loyalty-points-system
- @checkout-flow-optimization
- @discount-engine
- @price-rules-engine
- @ab-testing-pricing
- @loyalty-points-system
- @checkout-flow-optimization