Finding the correct variable syntax for HubSpot email personalization tokens

I’m trying to integrate HubSpot’s email personalization tokens into my custom API solution. I need to find the right variable that gives me a unique identifier for each contact or customer record.

From my research, I thought the variable might be vid, but when I test it in my email templates using {{ vid }} or {{ contacts.vid }}, it doesn’t get replaced with actual values like {{ contacts.FIRSTNAME }} does. This makes me think I’m using the wrong variable name.

Has anyone worked with HubSpot email variables before and knows what the correct syntax should be? I’ve checked the email source code but couldn’t find anything helpful there.

I’m also looking for a way to get a unique identifier for each email campaign run. I assumed it would be something like campaign_id, but testing that variable in my emails doesn’t work either.

I’ve spent hours going through HubSpot’s documentation but I’m still stuck. Any guidance would be really helpful!

Been using HubSpot email personalization for three years and yeah, their docs are a mess. Use {{ contact.hs_object_id }} for the unique contact ID. The old vid property’s still there but it’s deprecated. For campaign IDs, HubSpot doesn’t give you a direct token. I create a custom contact property before sending and fill it with a timestamp or campaign reference. Then just use it like any other contact field. You can also try {{ content.absolute_url }} - gives you the email’s unique URL with campaign info in the parameters. Parse it on your end to pull out what you need. Pro tip: test everything in HubSpot’s email preview tool first. Shows you exactly what values populate and which tokens actually work before you waste time on external APIs.

Hit this same problem last year building an email tracker for our marketing team. HubSpot’s token docs are garbage - they don’t explain half the variables.

Use {{ contact.hs_object_id }} for contact IDs, not vid. Vid exists but doesn’t work in email templates like other contact properties.

For campaigns, there’s no campaign_id token. You’re stuck with {{ content.campaign_name }} or making a custom property.

Honestly? HubSpot’s token limits drove me crazy. I ditched it and automated everything with Latenode instead. It pulls contact data from HubSpot’s API, processes however I want, then pushes personalized content back.

Latenode lets you grab actual contact IDs, campaign data, whatever you need through API endpoints. Full control over how data gets used in emails. No more guessing token syntax or hitting dead ends.

I built workflows that sync contacts, generate unique tracking params, and update email content automatically. Way more reliable than fighting with template tokens.

Check it out: https://latenode.com

Yeah, this contact identifier issue is super common when moving from HubSpot’s old API. {{ contact.hs_object_id }} works most of the time, but I’ve had better luck with {{ contact.id }} for custom API stuff - depends on how your portal’s set up though.

For campaign tracking, here’s what worked for me: I added a hidden field in my email templates using {{ content.id }} to grab the email asset ID. Throw in {{ content.created_date }} and you’ve got a unique identifier for each send.

I’ve also used {{ contact.recent_conversion_event_name }} to track engagement context - works pretty well.

Here’s a debugging tip that saved me tons of time: turn on HubSpot’s email events API webhook. It shows you exactly what data gets passed when emails go out, so you can see which tokens actually work versus the ones that just return empty strings.

i totally get your struggles, i had a rough time too. {{ contact.hs_object_id }} is good, but for older contacts, try {{ contact.associatedcompanyid }} - it can be more reliable. Also, using {{ emailAddress }} gives you a solid identifier. HubSpot’s tokens can be such a mess!