EP
05 of 08
Client work
05 — Frontend, at GUT

Reward andredemption flows

The work I am proudest of: one route that renders whatever the visitor has already done — chosen, claimed, shared, redeemed someone else’s offer, or all of it — componentised well enough that the next campaign started from it.

ClientMcDonald’s Spain · eme studios
Stack
Vue 3PiniaREST APIsTypeScript
Context

What the problem was

The Halloween campaign asks for one decision: trick, an offer for you, or treat, an offer you can only give away — redeemable by anyone except the person who shared it. That decision is stored, which means the page is never the same page twice. Come back after claiming and you should see your offer and the option to go and share; come back after doing both and you should see a third screen; arrive on a friend’s link and you should see theirs. Getting it wrong means showing someone the chooser again for something they have already spent.

Intro animation: a cobwebbed door with knocking text over it
The knock, before any of it
The knock, before any of itStill
Approach

What I did

01

Drew the state graph before the screens

Every state and every way into it, including the ones only reachable by leaving and coming back. The list of screens fell out of that graph rather than out of the design file.

02

Made the route a function of stored progress

One entry point, not a URL per outcome. What is stored for that user decides which screen renders, so a returning visitor lands where they left off and no state can be reached by guessing a link.

03

Treated the shared offer as a second actor

A shared offer has two sides: the person who gave it, who must not be able to redeem it, and the person who received it, who gets a screen of their own with its own next step — and who can then be pulled into the other half of the campaign.

04

Componentised it so it outlived the campaign

States, screens and the progress they read from are separate pieces rather than one page full of conditionals. San Valentín ran the same machine with a different skin and a different offer split, and the eme studios drop reused it for points-to-merch redemption.

Performance

How it stays fast

  • Progress resolved before first paint, so nobody sees the chooser flash before their real screen
  • The server owns what has been claimed; the client renders that rather than deciding it
  • Pinia holds the resolved state for the session, so moving between screens costs no round trip
Outcome

Three campaigns ran on the same structure. The later ones were a reskin and an offer change rather than a rebuild, which is exactly what the first one was designed to buy.

Visuals

Selected media

Choice screen with trick and treat side by side, neither chosen yet
The two-way choice
The two-way choiceStill
State after choosing trick, showing the claimed offer and a prompt to try treat too
Trick — the offer that is yours
Trick — the offer that is yoursStill
State after choosing treat, showing the shareable offer and a share button
Treat — the offer you give away
Treat — the offer you give awayStill
Recipient screen for a shared treat, with a redeem button
Arriving on someone else’s link
Arriving on someone else’s linkStill
Summary state showing both the claimed trick and the shareable treat
Both done, one screen
Both done, one screenStill
Variant summary state for someone who claimed their own offer and redeemed one shared with them
Claimed yours, redeemed theirs
Claimed yours, redeemed theirsStill
Valentine’s campaign choice screen: fries for yourself, or fries for someone else
San Valentín — the same machine
San Valentín — the same machineStill
eme studios collaboration landing page with the access pass and how to get it
eme studios — the drop
eme studios — the dropStill
State after choosing the offer for yourself, with the claim route into the app
Offer taken, waiting on the app
Offer taken, waiting on the appStill
Confirmation screen after sharing, with the window both people have to use the offer
After the share
After the shareStill
eme studios hoodie redemption screen showing the points price and a redeem button
Points for merch
Points for merchStill
Client work built at GUT — the artwork belongs to the brandEyman Pashaliev