How to Create Event-Triggered Customer Rewards With Shopify Flow and Klaviyo

How to Create Event-Triggered Customer Rewards With Shopify Flow and Klaviyo

Most ecommerce promotions start with the code.

Someone creates WELCOME10, adds it to an email and sends it to a group of customers.

That works when the promotion is simple.

It gets more complicated when the reward itself depends on something the customer has done.

Maybe they have:

  • joined a membership;
  • renewed for another year;
  • reached a VIP threshold;
  • placed their second order;
  • completed a referral;
  • bought a qualifying product;
  • reached six months as a subscriber.

In those cases, the problem is no longer just:

How do I send someone a discount code?

It becomes:

How do I know when someone qualifies, determine which reward they should receive, create that reward in Shopify and trigger the right Klaviyo journey automatically?

That is where Shopify Flow becomes useful.


The use case

Imagine you run a paid membership programme.

When somebody becomes a member, they receive a welcome gift.

When an existing member renews, they receive a different anniversary gift.

Each reward:

  • should only go to an eligible customer;
  • should have its own unique promo code;
  • should only be redeemable once;
  • should expire after a defined period;
  • may unlock a specific free product;
  • needs to appear automatically in the customer's Klaviyo journey.

You could manage this manually.

Or you can turn the customer event itself into the trigger.

The architecture looks like this:

CUSTOMER EVENT

↓

CHECK ELIGIBILITY

↓

DETERMINE REWARD

↓

CREATE UNIQUE SHOPIFY CODE

↓

SEND EVENT TO KLAVIYO

↓

TRIGGER LIFECYCLE FLOW

From the customer's perspective, they qualify for a benefit and receive it.

Everything behind it happens automatically.


When would you actually use this?

This pattern makes sense when the reward depends on data or behaviour inside Shopify.

Shopify/customer event Automated reward
Customer joins membership Welcome gift
Membership renews Anniversary gift
Customer places second order Second-purchase reward
Customer reaches VIP tier VIP benefit
Customer reaches spend threshold Personal reward
Customer buys qualifying product Complimentary product
Referral completes Referral reward
Subscriber reaches milestone Loyalty gift

The common structure is:

Event β†’ Eligibility β†’ Reward β†’ Klaviyo

The promo code is simply the mechanism that delivers the reward.


When you probably don't need this

If your use case is:

Customer subscribes to email β†’ send them 10% off

then building a Shopify Flow workflow is probably unnecessary.

Klaviyo can usually handle a straightforward welcome incentive more simply.

This approach becomes useful when Shopify needs to answer questions such as:

  • Has this customer purchased the qualifying product?
  • Which membership state are they in?
  • Has the customer already received this benefit?
  • Which reward should they receive?
  • Which product should become free?
  • How long should their individual reward remain valid?
  • Should this customer be allowed to use the offer at all?

That is the distinction.

Simple promotion: let Klaviyo handle it.

Reward based on commerce logic: use Shopify to determine eligibility and create the reward, then use Klaviyo to communicate it.


A worked example: membership welcome and anniversary gifts

Here is the system we built for a membership programme.

A qualifying paid membership order creates one of two outcomes.

New or returning member

The customer receives a welcome reward.

Renewing member

The customer receives an anniversary reward.

The workflow first establishes that the order relates to the membership programme.

It then evaluates the customer's state and determines which reward should be generated.

Shopify creates a unique code.

The workflow then sends a Customer Reward Created event into Klaviyo containing the code and reward information.

Klaviyo takes over from there.

So rather than maintaining spreadsheets of promotional codes and trying to work out who should receive what, the decision happens automatically.


Step 1: Start with the Shopify event

The workflow needs something to trigger it.

In this implementation, that is:

Order paid

Using the paid order as the trigger means the customer has actually completed the qualifying purchase before their reward is created.

Shopify Flow can then use information from the order and customer throughout the workflow.

The important thing is to choose the event that represents the point at which the customer actually becomes eligible.


Step 2: Check whether the customer qualifies

You usually don't want every paid order to generate a reward.

So the next step is eligibility.

For example:

Order paid

↓

Does the order contain a qualifying membership SKU?

↓

No

Stop.

Yes

Continue.

This is where Shopify Flow conditions become useful.

You can evaluate things such as:

  • SKUs;
  • products;
  • order value;
  • customer tags;
  • customer metafields;
  • customer segments;
  • previous customer state;
  • other Shopify data available to the workflow.

The trigger tells you that something happened.

The eligibility logic determines whether it matters.


Step 3: Determine which reward applies

Qualification does not necessarily mean everybody receives the same benefit.

In our membership example, the workflow needs to distinguish between:

Welcome

and

Anniversary

That decision is based on customer membership state.

For more complex cases, Shopify Flow's Run code action can be used to transform customer and order data into a simpler value for the rest of the workflow.

For example:

rewardType = welcome

or:

rewardType = anniversary

The workflow can then branch accordingly.

This keeps the decision logic in one place rather than duplicating it across multiple email flows.


Step 4: Create the reward in Shopify

Once you know that the customer qualifies and which reward they should receive, Shopify can create the actual discount.

The workflow uses Shopify's Admin API to generate a unique customer-specific code.

That might look like:

WELCOME-123456-1042

or:

ANNIVERSARY-123456-1042

instead of giving every customer the same:

WELCOME10

The exact code structure isn't particularly important.

What matters is that the reward is generated for that specific customer and lifecycle event.


The discount can contain its own rules

The Shopify discount itself can define the commercial logic.

For example:

Spend Β£29

↓

Receive one specific gift product free

The workflow can also control things such as:

  • qualifying spend;
  • qualifying products;
  • reward product;
  • customer eligibility;
  • one use per customer;
  • total usage limit;
  • start date;
  • expiry date.

In our commercial workflow, the discount is also restricted to the customer who triggered it.

That makes the reward closer to a customer-specific entitlement than a generic promotional code.


Step 5: Pass the reward into Klaviyo

Creating the reward inside Shopify is only half the system.

The customer still needs to receive it.

Once Shopify generates the code, Flow sends a custom event into Klaviyo:

Event

Customer Reward Created

Alongside event properties such as:


{
  "reward_type": "welcome",
  "discount_code": "WELCOME-123456-1042",
  "reward_expires_at": "...",
  "reward_source": "shopify_flow",
  "order_number": "...",
  "gift_variant_id": "..."
}

For a renewal, the same event can carry:


{
  "reward_type": "anniversary",
  "discount_code": "ANNIVERSARY-123456-1042",
  "reward_expires_at": "...",
  "reward_source": "shopify_flow",
  "order_number": "...",
  "gift_variant_id": "..."
}

That gives Klaviyo everything it needs to send the correct message.


Step 6: Build the Klaviyo flow

The Klaviyo side can stay relatively simple.

Trigger

Customer Reward Created

↓

Conditional split

reward_type = welcome

↓

Welcome reward email

Otherwise:

reward_type = anniversary

↓

Anniversary reward email

You can then personalise the message directly from the event properties.

For example:

Your membership gift is ready.

Use your personal code:

{{ event.discount_code }}

You can also use:

  • reward_expires_at;
  • reward_type;
  • gift_variant_id;
  • order_number.

Shopify decides what the customer is entitled to.

Klaviyo decides how and when that entitlement is communicated.

That separation keeps the system much easier to manage.


Why pass the reward as event data?

A reward like this belongs to a specific moment.

The customer:

qualified for a reward

at a particular point in time.

That makes the reward a natural piece of event data rather than permanent customer state.

For example:

Event

Customer Reward Created

Event properties

reward_type = welcome

discount_code = WELCOME-123456-1042

reward_expires_at = ...

gift_variant_id = ...

The Klaviyo flow triggered by that event then has everything it needs to construct the message.

You may still choose to write a small amount of useful profile state, such as:

has_received_customer_reward = true

last_reward_type = welcome

last_reward_created_at = ...

But the actual code and specific reward details belong to the event.

This is also why understanding the difference between profile properties and event properties matters.

[Internal link: Customer Properties vs Event Properties in Klaviyo: What's the Difference?]


Why not create hundreds of codes in advance?

You could.

But generating them at the moment of eligibility has some useful advantages.

You only create rewards that are needed

No giant unused code bank.

The reward can be customer-specific

The discount can be restricted to the person who actually qualified.

Expiry can be relative to the customer

Customer A might qualify today.

Customer B might qualify three months from now.

Each can receive their own redemption window.

The customer journey becomes evergreen

You don't need somebody rebuilding anniversary campaigns every month.

The code is connected to the event

You can trace why the customer received it and which lifecycle moment created it.


Be careful with timing

One complication with event-driven ecommerce systems is that several automations can happen at roughly the same time.

For example:

Order paid

may trigger one process that updates customer membership data.

Another workflow may immediately try to read that data.

That can create a race condition where the second workflow runs before the first update has finished.

In our implementation, we use a short wait before evaluating the customer's membership state.

That isn't something every workflow needs.

But when one automation depends on data written by another, timing needs to be considered deliberately.


Build the fallback logic too

Automation should not just describe what happens when everything works.

Think about:

  • What if the customer has no email address?
  • What if the qualifying product isn't found?
  • What if a discount already exists?
  • What if the Shopify API request fails?
  • What if the Klaviyo event fails?
  • What if customer state is ambiguous?
  • What if the same event fires twice?

For commercial CRM automation, preventing duplicate or incorrect rewards is just as important as generating them.

This is where QA becomes part of the architecture rather than something you do at the end.


The broader pattern

Once you have built this once, you start to see a lot of other applications.

Second-order reward

Second order paid

β†’ generate personal reward

β†’ send Customer Reward Created

β†’ trigger Klaviyo retention journey.

VIP benefit

Customer reaches VIP threshold

β†’ determine tier

β†’ generate tier-specific benefit

β†’ send Klaviyo VIP communication.

Subscription milestone

Subscriber reaches six months

β†’ generate loyalty gift

β†’ trigger Klaviyo milestone journey.

Product-based reward

Customer purchases Product A

β†’ generate benefit for Product B

β†’ trigger Klaviyo cross-sell journey.

Referral

Successful referral recorded

β†’ generate referrer reward

β†’ trigger Klaviyo referral email.

Different programmes.

Same underlying architecture:

Trigger β†’ Qualify β†’ Decide β†’ Create β†’ Communicate β†’ Measure


The Brutish rule

You don't need Shopify Flow just because you can automate something.

Use the simplest system that can reliably execute the customer experience.

If Klaviyo can create and send a straightforward discount without additional commerce logic, use Klaviyo.

If the reward depends on Shopify behaviour, customer state, product rules, metafields or more complicated eligibility logic, let Shopify Flow make the decision and use Klaviyo for the lifecycle communication.

The goal isn't more automation.

It's a cleaner connection between what the customer did and what happens next.


Want the working workflow?

We're turning this implementation into a reusable Brutish Event-Triggered Rewards Automation Pack for Shopify + Klaviyo.

It will include:

  • Shopify Flow workflow files;
  • dynamic discount setup;
  • welcome and anniversary reward logic;
  • customer-specific eligibility;
  • Shopify Admin API configuration;
  • Klaviyo event setup;
  • event and profile property schema;
  • installation guide;
  • QA checklist;
  • troubleshooting.

Join the waitlist β†’


Need something more complicated?

Brutish builds CRM and ecommerce systems across Shopify, Klaviyo and automation tooling, including custom lifecycle logic, customer data architecture and API integrations.

Work with Brutish β†’


Leave a comment

This site is protected by hCaptcha and the hCaptcha Privacy Policy and Terms of Service apply.