Workflows

    Custom Code & Experiences

    Run your own code when a survey is finished, and use ready-made interactive experiences for special use cases.

    Run custom code after a survey: personalised lines, numbered editions, prize draws, guest memory, print routing, live leaderboards and ready-made experiences such as aura booths, oracles, passports and team battles.

    Custom code action

    Add Run custom code to the After-Survey Actions step to do things a webhook can't: personalised lines, numbered editions, prize draws, quiz badges or QR coupons on the print. The code runs on the guest's device when the survey is finished, before the answers are saved, also offline. It fills Outputs (text or a picture) with setField. Map them onto your design in Dynamic Survey Mapping (they appear as "Code: …") or use {code:name} in messages. Try it runs the code with sample answers. If the code fails or takes too long, the guest just continues and the response shows the error.

    What the code can use

    answers (answers.Q1 or by question ID) · answer("Question title") · event · survey · guestNumber · setField(name, value) · await counter(name) (this device) · await sharedCounter(name, step, max) (every booth of the event) · random(min, max) · pick(list) · images(set) · pickImage(set, group) · groups(set) · await recall(key) · await remember(key, data, { merge }) · await faceRead() (smile, head tilt, number of people in the guest's photo) · await qrCode(text) · printOptions({ copies, printer, skip, message }) · tally(board, name, amount) · highScore(board, name, score) · confetti() · fireworks() · message({ text }) · sound(name) · wait(ms) · fetch()

    Print routing: printOptions({ copies: 2, printer: 'Photo printer' }) prints this guest's design with that many copies on that print-server printer, and printOptions({ skip: true, message: '…' }) shows the message instead of printing. Live leaderboard: tally('teams', 'Blue') adds to a total and highScore('quiz', 'Alex', 8) keeps each name's best score. Show them on a TV with /leaderboard?event_id=… or on the second screen with the Cast button (Live leaderboard). Offline, the scores wait on the device and are sent with the next guest.

    Guest memory: await remember(key, data) saves up to 2 KB for a guest and await recall(key) gives it back on their next visit (or null). Guests are matched by the key you pass in, for example their email (trimmed, lower case). Only a SHA-256 hash of the key is stored, never the email itself. Offline, a copy on the device is used and saves are sent when it is back online. In Try it both work in memory only. The event's Analytics page lists Remembered guests, with Clear all for after the event and Forget guests (never, or 1 to 365 days after a guest's last save). Several booths, one guest: with { merge: true } a save is added to what every booth saved (lists are joined, empty values never overwrite) and remember returns the combined data, so booths on different devices can fill the same passport. Shared counters: await sharedCounter('coupon') counts across every booth and device of the event; sharedCounter('win-bag', 1, 20) returns null once 20 is reached (prize stock). Offline, a booth counts from the last value it saw and catches up later. See or reset them under Shared counters in the event's Analytics.

    const email = answer('Email');
    const past = await recall(email);
    const color = past?.color || pick(colors);
    let style;
    do { style = pick(styles); } while (styles.length > 1 && style === past?.style);
    await remember(email, { color, style, visits: (past?.visits || 0) + 1 });

    Custom code follows the same switches as other custom JS: it only runs when custom JS is enabled for your account and not turned off on the site.

    Three examples

    Personalised line

    Output "line" (Text), mapped to a text layer.

    Numbered edition

    Output "edition" (Text). The counter is shared by every booth of the event and keeps going offline.

    Prize draw

    Output "prize" (Text). Every 25th guest of the event (all booths) wins, with fireworks on screen.

    Personalised line

    const name = String(answers.Q1 || 'Friend').split(' ')[0];
    await setField('line', name + ' ' + pick(['will dance until sunrise', 'is tonight\'s superstar']) + '!');

    Numbered edition

    const n = await sharedCounter('edition');
    await setField('edition', 'Edition ' + n + '/200');

    Prize draw

    const n = await sharedCounter('prize-draw');
    if (n % 25 === 0) { await setField('prize', 'WINNER!'); fireworks(); }
    else { await setField('prize', ''); }

    Ready-made experiences (special use cases)

    Choose Experience in the guided wizard to get one of these fully working. The wizard writes the custom code, the output fields for your design and the image sets from your answers, so you only fine-tune the code if you want to.

    Aura photo booth

    Reads the guest's smile, head tilt and group size on the device and reveals their aura colour with a matching background and overlay. Optional live glow on the camera and returning guests keep their colour (by email).

    AI Oracle reading

    An AI writes a short personal reading from the guest's answers in the tone and language you choose, with words to avoid and free fallback lines when offline.

    Fortune teller

    Crystal ball, a card and a season: each answer adds a line to the guest's reading. Works fully offline.

    Smile-o-Meter

    Scores the smile from 0 to 100, gives a badge from your score levels, adds bonus points per extra person, fires confetti and keeps the best smiles on a live leaderboard.

    "Which one are you?"

    Answers and the guest's photo point to a character, with a match percentage and a live count of each character.

    Multi-station passport

    Guests collect a stamp at every station and win a reward code when the passport is full. One survey is made per station and booths share the passport with guest memory.

    Instant win

    Every guest gets one chance at a prize. Stock and odds are shared by every booth of the event; winners get a code and QR.

    Team battle

    Every guest scores for their team on a live leaderboard; smiles earn bonus points and milestones set off fireworks.

    Show leaderboards on a TV with the event's leaderboard link or on a second screen with the Cast button. Replace the starter pictures any time in the action's image sets.

    More special use cases

    A few more ideas you can build with the helpers above:

    VIP routing

    Read the ticket type and use printOptions({ printer }) to send VIP designs to a separate printer, or printOptions({ copies: 2 }) for a second copy.

    One print per guest

    Use recall and remember with the guest's email, and printOptions({ skip: true, message }) when they have already printed today.

    QR coupon on the print

    Make a unique code with random or sharedCounter, turn it into a picture with qrCode, and map the output onto your design.

    Quiz score and badge

    Count correct answers, pick a badge picture with pickImage, and add the score to a live leaderboard with highScore.

    1