What are Variables?
Variables are temporary storage containers that let you capture, calculate, and use data as visitors move through your Flows. Unlike permanent contact fields that sync to your email platform, Variables exist only for the current session—making them perfect for tracking preferences, scores, or dynamic content during a single interaction.
You can set Variables to store quiz answers, count page views, calculate personalized recommendations, or rotate through different offers. Once set, you can display Variable values in messages, use them in branching logic, or sync them to your ESP as permanent fields.
Setting Variables
Use Data Nodes to set Variables at any point in your Flow.
Drag a Data Node onto your canvas (the fuchsia-colored node)
Click the node to edit
Click Add Action
Select Variable from the action type dropdown
Enter a Name for your Variable (e.g., "user_preference", "quiz_score")
Enter a Value, can be static text or dynamic using Liquid tags like
{{ hubspot.customFields.lifetime_value }}(Optional) Set an Expiration time, choose duration and unit (minutes, hours, days, weeks)
Variable names are case-sensitive and should be unique. If you set the same Variable name twice, the last value overwrites the first.
When you save, the Data Node will display a description like: "Set variable user_preference to premium (expires in 7 days)".
Reading Variables in Messages
Display Variable values anywhere in your Message Nodes using Liquid syntax.
Drag a Message Node onto your canvas
Click to edit the message content
Insert
{{ variable_name }}where you want the value to appearThe preview will resolve the Variable to its actual value
Example: "Welcome back! You selected {{ user_preference }} as your plan." If the Variable is unset or expired, it will display as blank text.
Variables auto-suggest as you type in the message editor. Look for the dropdown suggestions when you type opening curly braces.
Using Variables in Branching Logic
Create conditional paths based on Variable values using Yes/No Nodes.
Drag a Yes/No Node onto your canvas
Click to edit the condition
Set Source to "Scores"
Set Type to "Variable"
Select your Variable name from the dropdown
Choose an Operator (is, is set, is not set, includes, between, etc.)
Enter a comparison value if needed
Connect Yes and No paths to appropriate next nodes
Common operators:
is set — checks if the Variable has any value (no comparison needed)
is — exact match to a specific value
includes — checks if the Variable contains a substring
between — numeric range comparison
If a Variable is unset or expired, conditions using it will evaluate to the "No" path unless you're specifically checking "is not set".
Variable Expiration
When you set a Variable, you can specify how long it should persist. After the expiration time passes, the Variable is automatically cleared.
Expiration is useful when you want temporary personalization without cluttering long-term data. For example, set a "quiz_result" Variable to expire in 7 days—enough time for follow-up messaging, but it won't persist forever.
If you don't set an expiration, Variables last for the visitor's current session but clear when they close their browser or start a new session.
To make Variable data permanent, sync it to an ESP field using another Data Node action (explained below).
Syncing Variables to Your ESP or CRM
Variables don't automatically sync to your email platform. To save Variable values as permanent contact data, add a Field action after setting the Variable.
After your Data Node that sets the Variable, add another Data Node
Click Add Action and select Field
Choose the ESP field you want to update (e.g., "preferences", "lead_score")
Set the value to
{{ variable_name }}Save and connect the nodes
This creates a two-step process: set the Variable in-session, then push it to your ESP for permanent storage. This only works for identified visitors (those who have provided their email).
For more details on field mapping and ESP integration, see Synchronizing contact data with your email platform or CRM.
Use Cases and Examples
Round-robin offer rotation
Show different offers to visitors on a rotating basis, ensuring balanced distribution across multiple options.
How it works: Track a counter Variable that increments with each page view, then use modulo logic to cycle through offers.
Implementation:
Create a Data Node at the start of your Flow
Use a Code Node to calculate the rotation index:
// Get current rotation index, default to 0 let index = parseInt(RM.getVariable('offer_index') || '0'); // List of offer options const offers = ['offer-a', 'offer-b', 'offer-c']; // Calculate which offer to show (round robin) const currentOffer = offers[index % offers.length]; // Increment for next visitor RM.setVariable('offer_index', (index + 1).toString()); RM.setVariable('current_offer', currentOffer);Use a Yes/No Node to branch based on
{{ current_offer }}valueShow different forms or messages for each offer path
This pattern requires the Code Node for counter logic. For details on Code Node JavaScript, see Code Node JavaScript API reference.
Tracking total page views
Count how many times a visitor has viewed a specific page or your entire site, then sync this data to your ESP for segmentation.
How it works: Increment a Variable each time the Flow triggers, then sync to a custom field.
Implementation:
Set your Flow to trigger on page load for the target page
Add a Code Node to increment the counter:
// Get current view count, default to 0 let viewCount = parseInt(RM.getVariable('page_views') || '0'); // Increment viewCount += 1; // Save updated count RM.setVariable('page_views', viewCount.toString());Add a Data Node with a Field action
Map
{{ page_views }}to your ESP's "page_views" custom fieldUse this data in your ESP to segment high-engagement visitors
This works great for identifying warm leads who repeatedly visit pricing pages or product pages.
Calculating dynamic data for personalization
Compute values based on quiz responses or user behavior, then display them in messages or popups.
Example: Calculate a personalized "readiness score" based on quiz answers, then show it in a results message.
Implementation:
After each quiz question, use Data Nodes to assign point values to Variables
Add a Code Node to sum the scores:
// Get individual question scores let q1 = parseInt(RM.getVariable('question_1_score') || '0'); let q2 = parseInt(RM.getVariable('question_2_score') || '0'); let q3 = parseInt(RM.getVariable('question_3_score') || '0'); // Calculate total let total = q1 + q2 + q3; // Determine readiness level let level = total < 30 ? 'Beginner' : total < 70 ? 'Intermediate' : 'Advanced'; // Save results RM.setVariable('total_score', total.toString()); RM.setVariable('readiness_level', level);In a Message Node, display: "Your readiness score is {{ total_score }}—you're at the {{ readiness_level }} stage!"
Optionally sync
readiness_levelto an ESP tag for future segmentation
Storing user preferences for in-session personalization
Let visitors choose their interests or preferences early in a Flow, then customize subsequent messages based on those choices.
How it works: Capture preference selections in Variables, then reference them throughout the Flow.
Implementation:
Create a multiple-choice question asking about preferences (e.g., "What topics interest you?")
Add a Data Node after the question
Set a Variable
user_interestto{{ question_answer }}In later Message Nodes, customize content: "Since you're interested in {{ user_interest }}, here are our top resources..."
Use Yes/No Nodes to branch: if
user_interestis "SEO", show SEO-specific offers
This keeps your Flow dynamic without committing preference data to permanent fields until the visitor completes the Flow and opts in.
Conditional messaging based on accumulated behavior
Track multiple behavioral signals in Variables, then show different messages based on combined conditions.
Example: If a visitor has viewed 3+ pages AND downloaded a lead magnet, show a premium offer popup.
Implementation:
Use page-view tracking (see above) to set
page_viewsOn lead magnet download, set a Variable
downloaded_lead_magnetto "true"Create a Yes/No Node with compound conditions checking both Variables
Yes path: show premium offer
No path: continue standard nurture sequence
Testing Variables
The Flow Builder preview mode includes a Test Variables panel that shows all active Variables and their current values as you step through your Flow.
Click Preview in the Flow Builder
Open the Test Variables panel (usually visible by default)
As you progress through the Flow, Variables appear as pills with their names and values
Check that Variables update correctly and expire as expected
Expiration timing in preview mode is simulated. For real-time testing, publish your Flow and test on your live site.
Common Issues and Tips
Variable shows blank in messages: The Variable is either unset, expired, or referenced before it's set. Check your node order and make sure the Data Node that sets the Variable comes before any Message Nodes that read it.
Conditions always go to "No" path: Variable is likely expired or unset. Use "is set" conditions first to check Variable existence before testing values.
ESP sync not working: Variables only sync to ESP fields when the visitor is identified (has provided their email). Anonymous visitors can use Variables in-session but can't sync to external platforms.
Variables persist across visits: Variables are session-scoped and clear when the session ends. To persist data across visits, sync to ESP fields and pull from those fields on future visits.
Name conflicts: If you set the same Variable name twice in one Flow, the last value overwrites the first. Use unique names or intentionally overwrite when updating values.
Advanced: Programmatic Variable Access
For complex logic, calculations, or integrations, you can set and read Variables using JavaScript in Code Nodes.
Set a Variable:
// Basic set
RM.setVariable('variable_name', 'value');
// With expiration (7 days)
RM.setVariable('variable_name', 'value', {
expiresType: 'duration',
expiresDuration: 7,
expiresUnit: 'days'
});Read a Variable:
let value = RM.getVariable('variable_name');
// Returns the value as a string, or null if unset/expiredFor complete API documentation, see Code Node JavaScript API reference.