I'm working on a Craft Commerce project where users can register for paid events. The events have a different price for members and non-members of the organization the site belongs to. I'm not sure what the best way to represent this member discount is. My ideas:

  1. Create a discount that takes a fixed amount or percentage amount off, and use a Match Customer rule to only apply to users in the Member group. However, I need to build this discount into the system into several functions and templates, and it looks like you're not supposed to build around the assumption that a specific discount will always exist. Discounts aren't tracked in the project config, so a specific discount may or may not exist on the production site. I can use a migration to create the discount, but it can still be deleted. Discounts also don't have handles, so there isn't even a way to fetch a specific discount in a template to see whether it exists. I also need to show prices for members and non-members without the context of a cart, and there doesn't seem a simple way to do that, since discounts can only apply to orders or carts. Feels like this solution would require a lot of small hacks to deeply integrate into templates and functionality, doesn't feel like the best solution.
  2. Use product variants – each event gets a variant for members and one for non-members. I could use hooks to ensure only members can buy the member-only variant. However, this would require editors to manually add both variants for all events, which is error-prone and a lot of unnecessary work.
  3. Write a custom adjuster that discounts events for members automatically. This feels like the cleanest solution, but feels like a lot of work for a rather 'basic' requirement. I only want to try that once I'm sure there's no better solution.
  4. Use the Events plugin, which supports creating different tickets. This would probably work, but has some other issues that prevent me from using it (most prominently that it's still in beta for Craft 4).

Which of those approaches is the best? Is there a simpler solution that I'm not seeing? I think discounts are probably the intended way to handle this scenario, but how can I handle the problems mentioned above in this case?

1 Answer 1


Options #1 and #3 are the two options you'll want to decide between, and you've hit the nail on the head in terms of the pros and cons of each.

If a discount code being deleted / modified poses a danger to you codebase, then the price adjustment is cleaner.

If you can code defensively, always checking that the discount you're expecting exists before trying to call it, you can use option #1 and know that deleting that discount from the CMS (or forgetting to add it, and spell it correctly on deployment) is an existing failure point.

The answer comes down to what yourself and your client are comfortable with in terms of risk.

  • Thank you for your insights! In regards to code defensively, is there any way to uniquely refer to a specific discount to check if it exists or not? They don't have handles and their IDs are specific to each environment. I guess I can only iterate through existing discounts to check if the 50% discount exists? Or just build everything in a generic way so that it works with all kinds of discounts?
    – MoritzLost
    Mar 2, 2023 at 9:58
  • 1
    I'm always a fan of setting up generic approaches that set you up for future use cases and also give CMS managers expectable outcomes to the changes they make. That said, if you needed to do a check you'd want to do craft.commerce.discounts.getDiscountByCode('CODE') to see if it exists (not null) and to use for any comparisons.
    – cherrykoda
    Mar 2, 2023 at 18:30
  • @cherrycode Thanks! I'll see how we can build this function in a way that works with any discounts but also integrate the member discount into the interface. But the last part won't work, as the member discount is just based on a specific user group – there's no discount code to be applied.
    – MoritzLost
    Mar 3, 2023 at 9:10
  • 1
    Oh, that's far trickier. I'll poke around the docs but I'm not sure if there will be a consistently good way to always get the right one.
    – cherrykoda
    Mar 3, 2023 at 17:55
  • 1
    Yeah I had a look as well, doesn't seem like there's a way to uniquely identify specific discount. I guess that makes sense since they're designed to be "ephemeral" in a sense. Maybe I'll look into writing an adjuster instead on monday.
    – MoritzLost
    Mar 3, 2023 at 19:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.