Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
v:2.0:coupons_and_discounts [2023/11/10 22:33] – [Tax-Inclusive Pricing with Coupons & Discounts] foxybrettv:2.0:coupons_and_discounts [2025/06/03 17:55] (current) – [Coupon Codes] foxybrett
Line 4: Line 4:
  
 <wrap tip>We've found that stores with coupon codes tend to generate 60% more revenue and 83% more transactions than stores not utilizing coupon codes</wrap>, and those numbers increase (significantly) as the number of coupon codes increases. (Stores with 10 or more coupon codes do 3.8x the revenue and 3x the transactions. According to our data, at least. No joke.) It's not a magic bullet, but simply having coupon codes available can motivate an otherwise "too busy" merchant or marketer to do some email marketing or advertisements promoting the coupon codes. Try it! According to our system-wide data, you won't regret it. <wrap tip>We've found that stores with coupon codes tend to generate 60% more revenue and 83% more transactions than stores not utilizing coupon codes</wrap>, and those numbers increase (significantly) as the number of coupon codes increases. (Stores with 10 or more coupon codes do 3.8x the revenue and 3x the transactions. According to our data, at least. No joke.) It's not a magic bullet, but simply having coupon codes available can motivate an otherwise "too busy" merchant or marketer to do some email marketing or advertisements promoting the coupon codes. Try it! According to our system-wide data, you won't regret it.
 +
 +===== Native v. Externally-Controlled Coupons =====
 +
 +This page covers "native" coupons in Foxy. For users on our Advanced and Enterprise plans, we offer "externally controlled coupons", which require the [[v:2.0:pre_cart_webhook|Pre-Cart Webhook]] functionality. If you //must// control discounts from an external system, reach out and we can discuss the details.
  
 ===== How They Work ===== ===== How They Work =====
Line 113: Line 117:
 ==== Coupon Codes ==== ==== Coupon Codes ====
 {{ :v:2.0:responsive_2.0_cart_coupons.png?direct&300|}} {{ :v:2.0:responsive_2.0_cart_coupons.png?direct&300|}}
-Unlike product or category quantity discounts, coupon codes apply one single discount as a line-item in the cart, and do not affect the individual product prices. Coupon codes also can apply to one or many categories, but cannot be product-specific (unless the product is the only product in a given category).+Unlike product or category quantity discounts, coupon codes apply one single discount as a line-item in the cart, and do not affect the individual product prices. Coupon codes also can apply to one or many categories, and/or one or many specific product codes.
  
 The default discount type for coupons is ''single''. The default discount type for coupons is ''single''.
Line 176: Line 180:
   ; Coupon Type   ; Coupon Type
   : The type of discount you want to apply (see above for details on that)   : The type of discount you want to apply (see above for details on that)
-  ; Coupon Details +  ; Rules 
-  : The discount logicsuch as ''incremental|1-5|2-10''+  : The rule builder allows you to build the discount logic using UI. The underlying data (accessible via the API) will look like the syntax above (such as ''incremental|1-5|2-10''), but the UI in the Foxy Admin makes it easy to generate. 
 +  ; Product code restrictions 
 +  : If you want to limit which products can use this coupon, you can enter a comma separated listed of product codes or partial product codes using ''*'' as a wild card at the beginning and/or end of the value. So ''abc123'', ''fun_*'', ''*-small'' would match ''abc123'', ''fun_'' and ''fun_times'', and ''example-small''. It wouldn't match ''abc12'', ''abc1234'', ''fun'', or ''good-smalls''. If a code starts with ''-'' it will be considered as a block instead, matching everything except products that match that code. For example ''-*-small'' would match every product that does not have a code that ends in ''-small''. Allow lists and block lists can also be combined, ''foo*, -foobar'' would match all products that begin with ''foo'' except any products with a code of ''foobar''. Currently restricted to a maximum length of 5000 characters. 
 +  ; Item option restrictions 
 +  : You may have arbitrary item options (like ''brand'', ''publisher'', ''size'', ''location'', etc.) that determine what type of discount to apply. Using this setting, you can restrict coupons using similar logic as the "restrict usage by product code" above. Instead of a single comma-separated list of values to match against, input here is per item option. Wildcards can be used in option //values// but not option //names//
 +  : The functionality is only available in the new admin and via the API. 
 +  : Though not technically item options, the following native item values can also be matched against: ''name'', ''parent_code'', ''url'', ''image'', ''sub_frequency''
 +  ; Customer attribute restrictions 
 +  : Coupons can be restricted so they only apply to products with specific options. For instance, if you sell books and want to have a coupon that discounts a specific all books from a specific author or imprint, you could add that here. 
 +  ; Customer subscription restrictions 
 +  : You can restrict coupons to only work for customers with an active subscription that contains specific products (based on the products' ''code''). The coupons will not apply a discount if the customer does not have a matching active subscription. 
 +  ; Auto-apply 
 +  : For the customer attribute and subscription restrictions, turning on "auto-apply" will (unsurprisingly) automatically apply the coupon when the customer authenticates on the checkout. This is useful for something like automatically applying a membership discount based on a customer's membership subscription, or for wholesalers via a customer attribute.
   ; Combinable   ; Combinable
   : If the "combinable" checkbox is left unchecked when creating a coupon it will not be added to the cart if another coupon is already in the cart. Similarly, if this coupon is added first, no other coupons will be able to be added to the cart. <wrap tip>Note: The discounts that coupons generate are based off the product subtotal,</wrap> and other coupons don't impact the generated discount. For instance, if you have a $100 transaction with both a $20 and a 10% off coupon, the order total will be $70 (and not $72, as would be the case if the % discount calculated //after// the $-discount.   : If the "combinable" checkbox is left unchecked when creating a coupon it will not be added to the cart if another coupon is already in the cart. Similarly, if this coupon is added first, no other coupons will be able to be added to the cart. <wrap tip>Note: The discounts that coupons generate are based off the product subtotal,</wrap> and other coupons don't impact the generated discount. For instance, if you have a $100 transaction with both a $20 and a 10% off coupon, the order total will be $70 (and not $72, as would be the case if the % discount calculated //after// the $-discount.
Line 196: Line 212:
   ; Apply to Categories   ; Apply to Categories
   : Similar to the category quantity discounts, but can be applied to multiple or all categories. So if a coupon code only applies to the T-Shirt category and there are no T-Shirts in the cart, no discount will be applied.   : Similar to the category quantity discounts, but can be applied to multiple or all categories. So if a coupon code only applies to the T-Shirt category and there are no T-Shirts in the cart, no discount will be applied.
-  ; Restrict Usage by Product Code 
-  : If you want to limit which products can use this coupon, you can enter a comma separated listed of product codes or partial product codes using ''*'' as a wild card at the beginning and/or end of the value. So ''abc123'', ''fun_*'', ''*-small'' would match ''abc123'', ''fun_'' and ''fun_times'', and ''example-small''. It wouldn't match ''abc12'', ''abc1234'', ''fun'', or ''good-smalls''. If a code starts with ''-'' it will be considered as a block instead, matching everything except products that match that code. For example ''-*-small'' would match every product that does not have a code that ends in ''-small''. Allow lists and block lists can also be combined, ''foo*, -foobar'' would match all products that begin with ''foo'' except any products with a code of ''foobar''. Currently restricted to a maximum length of 5000 characters. 
   ; # of Uses (Total)   ; # of Uses (Total)
   : If you want to limit the number of uses this coupon as a whole can be used, enter a number here. If, for example, only the first 50 customers can use the coupon, enter 50 here. This relates to coupon variants and the number of uses per code (below). If you have 1 coupon code and 10 uses, the coupon will not be able to be used after 10 successful transactions. If you have 1 coupon with 100 variants but only 50 uses, only the first 50 uses will be allowed, regardless of the number of uses per code.   : If you want to limit the number of uses this coupon as a whole can be used, enter a number here. If, for example, only the first 50 customers can use the coupon, enter 50 here. This relates to coupon variants and the number of uses per code (below). If you have 1 coupon code and 10 uses, the coupon will not be able to be used after 10 successful transactions. If you have 1 coupon with 100 variants but only 50 uses, only the first 50 uses will be allowed, regardless of the number of uses per code.
Line 215: Line 229:
 ===== Tax-Inclusive Pricing with Coupons & Discounts ===== ===== Tax-Inclusive Pricing with Coupons & Discounts =====
  
-Coupons and discounts get a little trickier, and how you want coupons to work in the context of [[./taxes|tax-inclusive pricing]] isn't as obvious or agreed-upon as we might have imagined. (Please read the docs on that page first, if you haven't, as it has important context for this section of our documentation.) In particular, percentage-based discounts are generally "easy", but set-amount discounts may require a few minutes to understand.+Coupons and discounts get a little trickier, and how you want coupons to work in the context of [[./taxes|tax-inclusive pricing]] isn't as obvious or globally agreed-upon as you might hope. (Please read the docs on that page first, if you haven't, as it has important context for this section of our documentation.) In particular, percentage-based discounts are generally "easy", but set-amount discounts may require a few minutes to understand. 
 + 
 +This is easiest to communicate by way of example. Assume an $100 (tax-exclusive) product ($110 tax-inclusive price), a 10% tax (inclusive), and a $15 coupon. Take a look at this table, and note the <wrap tip>tips</wrap> and <wrap important>warning</wrap>: 
 + 
 +^ **Scenario**                  ^ **#1**                ^ **#2**                ^ **#3**                ^ **#4**                ^ **#5**                ^   
 +| **Template Set**              | Tax-Exclusive         | Tax-Exclusive         | Tax-Inclusive         | Tax-Inclusive         | Tax-Inclusive         | 
 +| **Item Price (displayed)**    | 100.00€               | 100.00€               | 110.00€               | 110.00€               | 110.00€               | 
 +| **Item Price (actual)**       | 100.00€               | 100.00€               | 100.00€               | 100.00€               | 100.00€               | 
 +|                                                                                                                                             | 
 +| **Coupon's ''is_taxable''**   | false                 | true                  | false                 | false                 | true                  | 
 +| **Coupon's ''inclusive_tax_rate''** | 0               | 0                     | <wrap tip>0</wrap>    | <wrap tip>0.10</wrap> | 0                     | 
 +| **Coupon Discount (actual)**  | 15.00€                | 15.00€                | 15.00€                | 15.00€                | 15.00€                | 
 +| **Coupon Discount (displayed)** | 15.00€              | 15.00€                | 15.00€                | <wrap tip>13.64€</wrap> | 15.00€              | 
 +|                                                                                                                                             | 
 +| **Item Price, post coupon (not displayed)** | 85.00€  | 85.00€                | 95.00€                | 95.00€                | 95.00€                | 
 +| **Item Price, post coupon (actual)**        | 85.00€  | 85.00€                | 85.00€                | 86.36€                | 85.00€                | 
 +|                                                                                                                                             | 
 +| **Tax**                       | 8.50€                 | 10.00€                | 8.50€                 | <wrap tip>8.64€</wrap> | 10.00€               | 
 +|                                                                                                                                             | 
 +| **Order Total**               | 93.50€                | 95.00€                | <wrap important>93.50€</wrap> | 95.00€             | 95.00€                |
  
-This is easiest to communicate by way of exampleAssume an $100 (tax-exclusive) product ($110 tax-inclusive price), a 10% tax (inclusive)and a $15 coupon. There are three different ways different people want or expect that to look:+The three settings to note are: 
 +  - The template set's tax inclusive setting. 
 +  - The coupon's "taxable" setting. In some industries or situations, a discount might be "after tax". For instance, say you want to offer customers 100% off, but you still need to collect tax for the full sale amount. Set the coupon to taxable and the tax will be applied //before// the coupon's discount is applied. 
 +  The coupon's "inclusive tax rate" value. This gets a little more complicated, but if you compare scenario #3 and #4 above, you can see the impact. Setting a coupon's ''inclusive_tax_rate'' will decrease the //applied// (but not //displayed//) discount by that inclusive tax percentage. So a 15€ coupon becomes ''15 / 1.1 = 13.64''. The end result is a 15€ "tax-inclusive" discountas you can see in the Order Total row. 
 +    * <wrap tip>This is only important for "discount by an amount" coupons, not for "discount by percentage" coupons, as %-based coupons will result in the correct order total regardless tax-inclusive or tax-exclusive settings. 
 +    * Scenario #3 shows what would happen without an inclusive tax rate. (It behaves identically to scenario #1which is tax-exclusive.)  
 +    * The inclusive tax rate should be the default tax rate for the customers who'll use the coupon. This ensures your coupon is always for the expected amount, even if a customer's tax rate is different. This also prevents tax-exempt customers from receiving a higher-than-desired discount. 
 +    * The inclusive tax rate functionality behaves identicaly regardless the tax-inclusive or taxable settings, but it's generally only useful in the tax-inclusive scenarios.
  
-  - Item subtotal (display): $110. Item subtotal (tax-exclusive): $85. Discounts: -$15. Tax (inclusive): $10. Order total: $95. 
-    * This is the behaviour of a coupon with the "taxable" checkbox checked. The tax is applied to the //pre-discounted// item price. The result is a product sold for $85 ($100 tax-exclusive less the $15 coupon), and a tax of $10. Though this results in a $15 coupon providing a net $15 discount to the customer, $10 tax on an $85 purchase is actually a tax rate of 11.76%. 
-  - Item subtotal (display): $110. Item subtotal (tax-exclusive): $85. Discounts: -$15. Tax (inclusive): $8.50. Order total: $93.50. 
-    * In this scenario, the entire $15 discount is applied to the item's //tax-exclusive// price. The tax is then applied on the new, discounted amount. The end result, however, is a $15 coupon that results in a $16.50 discount on the tax-inclusive price. 
-    * This is how a "normal" coupon generally works in tax-exclusive regions, if it's helpful to think of it that way. 
-  - Item subtotal (display): $110. Item subtotal (tax-exclusive): $86.36. Discounts: -$13.64. Tax (inclusive): $8.64. Order total: $95. 
-    * This option requires you to enter a "tax-inclusive" discount amount. In this case, that'd be the "intended" discount of $15, divided by 1 plus the tax rate. ''13.64 = 15 / 1.1''. The result of this is a "tax-inclusive" $15 discount to the customer, even though the actual tax-exclusive discount is $13.64. 
-    * If this is the behaviour you'd like, you'll need to do the math yourself to enter the appropriate pre-tax discount. Note also that the actual discount (in this case $13.64) is displayed to the customer. (We may add some additional display-only changes based on user feedback, so please let us know if this is your preferred approach.) 
  
-Note also that if you're accepting multiple currencies and/or operate in different countries with different inclusive or exclusive tax rates, you'll want to ensure you test your coupons to ensure you're aware of how that will impact things. 
  
-<WRAP round tip>**We'd love to hear from you.** Please [[https://foxy.io/contact|send us a quick note]] about which of the above options you prefer, along with your country and industry.</WRAP>+<WRAP round tip>**We'd love to hear from you.** Please [[https://foxy.io/contact|send us a quick note]] if you have a requirement with taxes and coupons that's not covered here, along with your country and industry.</WRAP>
  
-<WRAP round important>**This topic can be complicated.** One of our team (in Paris) went through their receipts and pulled 3 of their orders from non-Foxy merchants, and we found each of their transactions mapped to a different of the approaches described above. If you're unsure which of the above approaches make sense to you, please contact your tax professional for what will surely be an exhilarating conversation. :)</WRAP>+<WRAP round important>**This topic can be complicated.** One of our team (in Paris) went through their receipts and pulled 3 of their orders from non-Foxy merchants, and we found each of their transactions mapped to scenarios 3, 4, and 5. If you're unsure which of the above approaches make sense to you, please contact your tax professional for what will surely be an exhilarating conversation. :)</WRAP>
  
 ===== Notes ===== ===== Notes =====

Site Tools