1:1 Coupon Assignment

Leverage Simon's Journeys product to allocate coupons 1:1 to users within different variants of a campaign.

📘

This feature leverages our Journeys Node Unique ID functionality. Read through our documentation to understand how it works!

Use Case

The solution outlined below allocates unique coupon codes 1:1 each contact in a segment or variant of a campaign. This is particularly valuable when you have the list of coupon codes that you want to assign out, but the set of contacts to whom you want to distribute them is defined by logic in Simon, making it impossible to allocate them via SQL in our Datasets product.

Note this solution does NOT cover coupon generation -- the assumption is that you have a table of pre-populated coupon codes available in your CDW.

How it works

We allocate coupon codes 1:1 by leveraging our Journeys Node Unique ID feature with Lookup tables. The Journeys Node Unique ID functionality ensures that each contact at each node in a Journey is assigned a unique number, starting at 1 for the first contact entering that node and increasing by 1 for each subsequent contact. At the same time, we can build a Lookup table that takes our table of coupon codes, and uses the ROW_NUMBER function in SQL to assign a unique number to each coupon code, starting with 1 for the first coupon code and increasing by 1 for each subsequent coupon code. By matching those numbers up (i.e. by using the Journey Node Unique ID as the key for your Lookup) you can achieve 1:1 coupon code assignment.

❗️

This feature is only available for Journeys.

Example

Lookup table

If we have our coupon codes in a table called coupons , we can build a Lookup table named coupon_codes like so:

select 
  coupon_code, row_number() over (order by random()) as lookup_key
from coupons

This will create a table with 1...N as the values for lookup_key (with N being the number of coupons available).

Journey

You can build a journey with as much internal complexity as you'd like. You can leverage branching and experimentation. If you want multiple nodes of your Journey to leverage couponing (say, if you want to experiment with different discount amounts) you can do that -- each node's contact_journey_node_unique_id is independent from one another. You'll also need to build a different Lookup like the above for each node leveraging coupons that contain the coupon codes you want to assign to the contacts at that node.

Custom Context

In order to use the couponing at any node in your Journey, you can leverage the Lookup you built in custom context by indexing into it using the contact_journey_node_unique_id:

{{ lookups.coupon_codes[simon.contact_journey_node_unique_id] }}

This will assign a unique row from the coupons table to each contact.

Edge Cases

Too many coupon codes

In the case where you have more coupon codes than contacts, you don't need to do anything. The extra coupon codes will simply go unused!

Too many contacts

In the case where you have more contacts than coupon codes, you'll need to catch Lookup errors. This case will manifest itself by a contact's simon.contact_journey_node_unique_id value being higher than any of the keys in your coupon lookup table. You can catch this error in Jinja and handle it however you'd like -- perhaps with skip_action() to prevent the send from occurring.

Skip Actions

Note that the contact_journey_node_unique_id increments from one contact to the next regardless of whether or not a message was sent. That means that if the content you're sending contains skip_action() statements that are frequently called, you will end up skipping coupon codes in your corresponding lookup table.