Forum Discussion
Complex Canvas
Hi emily_wri
You can handle this effectively using Canvas Context Variables. Updating a user attribute from inside a Canvas can work, but there is an important limitation:
A custom attribute is information saved on the user’s profile. It can change every time the user starts the Canvas again and the wait periods or any dependencies on the custom attribute will be messes up.
A context variable is information saved only for the user’s current run of the Canvas. If the user enters again later, they get a brand-new set of context variables, and the old ones stay untouched. (only if you do not update the variable again in a different context step)
Imagine a coffee shop app.
A custom attribute is like a note on your customer account:
“Favourite drink: Latte.”
If the app updates this based on your last order, it might change the next time you come back and start a new order.
A context variable is like your current order number:
“Order #1042.”
This number stays the same while you’re placing that order.
If you leave and come back tomorrow to place a new order, you get a new order number, and yesterday’s number doesn’t change. It was only for that one visit.
So:
- Custom attribute = profile info that can change when you re-enter.
- Context variable = session info; each time you enter, you get your own fresh set, and past ones are not affected.
Ignore all of the above if you have disabled re-entry..haha. But I would still chose Context variables.
For this reason, once the Canvas is triggered, the very first step should be a Context Step. This ensures you capture the user’s entry information before anything else happens.
Below are the two context variables that work well for a month-long challenge.
1. Capture the user’s entry date with a Context Step
Immediately after the Canvas trigger, add a Context Step.
Create the first variable:
Context Variable Name: entered_date
Data Type: time
Value :
{% comment %}
--User entered the challenge -- The time is in UTC, change it to your need
{% endcomment %}
{{ "now" | date: "%Y-%m-%d %H:%M" }}This records the exact moment the user joined the challenge. Unlike a custom attribute, it will not update or change if the user triggers the entry logic a second time. You can reference this value in decision splits, audience paths, exit criteria, and message templates
This allows you to structure logic such as sending different content depending on the date they entered.
2. Calculate how many days remain until the campaign end date
If your challenge ends on a fixed date (for example, December 21), you can calculate the days remaining as soon as the user enters.
In the same Context Step, create a second variable:
Context Variable Name: days_till_campaign_end_date
Data Type: Number
Value:
{% assign date_entered = "now" | date: "%Y-%m-%d %H:%M" %}
{% comment %}
-- Assign/Manipulate the campaign end date
{% endcomment %}
{% assign end_date = "2025-12-21 00:00" %}
{% assign entered_seconds = date_entered | date: "%s" %}
{% assign end_seconds = end_date | date: "%s" %}
{% assign diff_seconds = end_seconds | minus: entered_seconds %}
{% assign diff_days = diff_seconds | divided_by: 86400 %}
{{ diff_days }}This variable can be used for dynamic delays, for branching users into different paths based on how late they joined, or inside templates to adjust or abort certain messages. Because this calculation is stored in the Canvas context, it stays consistent no matter what the user does after entering.
By making the Context Step the first step, you ensure that entry-specific data is captured immediately and remains reliable throughout the journey. Context Steps and dynamic delays provide clear, predictable ways to manage complex timing rules, challenge windows, late entrants, and final cutoff dates.
I have attached few screenshots in the next comment for you to understand the above better.
If you can provide more info on the sending rules and wait periods etc., I can help refine the setup further. Do not hesitate!
Hope this helps!
Related Content
- 9 months ago
- 7 months ago