Case Study

Hyper-Personalization at Scale with Velocity Scripting

Creating deep, custom, data-driven personalization for customers at scale with Marketo Velocity Scripting.

Company
ActivTrak
Platform
Marketo
Personalization
User Account data
Method
Velocity Scripting

Delivering an ultra personalized email with 5 account specific metrics per subscriber, and specific guidance tailored to that data required more than just variants or dynamic content. The combinations of data across a database are almost endless and too varied to account for in any finite set of pre-built emails.

Velocity scripting is Marketo's templating language for advanced personalization. Unlike the visual dynamic content editor, Velocity runs as server-side logic at send time, allowing conditional statements, data parsing, string manipulation, and custom functions, all within the email template itself.

To solve that, I built a Velocity scripting solution that pulls each subscriber's actual account data at send time and generates dynamic responses from the Productivity Lab based on healthy metric bands. Check out the interactive demo below to see how it worked.

Edit Values
Values update the email in real time. Try different numbers to see the conditional messaging change.
Loading email template...

Each of the five metrics required its own Velocity token, a self-contained script that parses the input, evaluates it against thresholds, and returns a block of HTML with the appropriate messaging, color coding, and status label. Those tokens are dropped into the email template as placeholders, populated at send time by the Marketo engine.

The first challenge was data parsing. The metric values come in as time strings like "4h 12m" or "44m", not as numbers. Velocity doesn't have native time parsing, so a custom parsing function extracts hours and minutes and converts them to a comparable unit before evaluation.

Script Logic per Token
Parse
Time string → comparable unit
Splits "4h 12m" into hours and minutes, converts to total minutes or hours depending on the metric. Handles edge cases: missing hours, missing minutes, whitespace variations.
Evaluate
Value → threshold range
Compares parsed value against benchmark thresholds. Each metric has its own range definitions based on ActivTrak's benchmark data. Falls into one of five states: healthy, watch-high, watch-low, action-high, action-low.
Generate
Range → HTML content block
Returns a fully-formed HTML snippet with color-coded status label, personalized message referencing the recipient's actual value, and benchmark context. No post-processing required.
Fallback
Missing data → safe default
Smart list filters exclude records with missing metrics before send. If a value is malformed, the script falls back gracefully rather than rendering broken content.

The collaboration time token shows the full pattern:

## Parse time string into minutes
#set($timeString = $lead.collaborationTime2025)
#if($timeString.contains("h"))
  #set($parts = $timeString.split("h"))
  #set($hours = $convert.toInteger($parts[0].trim()))
  #set($minutes = 0)
  #if($parts.size() > 1 && $parts[1].trim() != "")
    #set($minutesPart = $parts[1].replace("m","").trim())
    #set($minutes = $convert.toInteger($minutesPart))
  #end
  #set($value = ($hours * 60) + $minutes)
#else
  #set($value = $convert.toInteger($timeString.replace("m","").trim()))
#end

## Evaluate and generate content
#if($value >= 30 && $value <= 60)
  <p><strong style="color: #2ED4B5;">Congrats!</strong>
  Your average of ${value}m closely matches the benchmark (44 minutes).</p>
#elseif($value > 60 && $value <= 90)
  <p><strong style="color: #FBD13E;">Keep an eye on this.</strong>
  Collaboration time is above benchmark.</p>
#else
  <p><strong style="color: #FF864B;">This may call for action.</strong>
  Collaboration time requires attention.</p>
#end

Full scripts for all five metrics are on GitHub.

MarketoVelocity ScriptingDynamic PersonalizationEmail TemplatesConditional LogicData Parsing