Klaviyo is brilliant at personalizing text - {{ first_name }} in a subject line, dynamic product blocks, behavioral triggers. But the images in most Klaviyo emails stay the same for everyone. The hero banner, the header, the offer graphic: identical whether you're subscriber number 1 or number 100,000.
That's a missed opportunity. An email where the recipient sees their own name, their company, or the exact product they were looking at inside the image stops the scroll in a way that "Hi {{ first_name }}" in the body never will. And you can set it up in Klaviyo without writing a line of code or waiting on a developer.
Here's how.
Why personalize the image, not just the text
Klaviyo's built-in personalization handles text merge tags well. The gap is visual. Subscribers have been reading "Hi [First Name]" for fifteen years - it no longer registers as personal. A graphic that displays their name, or a product card showing the specific item they abandoned, is processed differently: it looks bespoke, so it earns attention and clicks.
The obstacle has always been production. You obviously can't open Photoshop or Canva and hand-make a separate image for every subscriber on a 50,000-person list. So the image stays generic.
The fix is a tool that generates the image dynamically from a URL - so one image "slot" in your Klaviyo template becomes a different picture for every recipient, filled in automatically from the data Klaviyo already holds about them.
How dynamic images work in Klaviyo
The mechanism is simpler than it sounds, and it relies on something Klaviyo already does perfectly: merge tags in URLs.
When you add an image to a Klaviyo email, that image is just a URL - https://something.com/image.png. Klaviyo doesn't care what's in the URL; it renders whatever the URL returns. And crucially, Klaviyo will substitute merge tags inside a URL, exactly as it does in body text.
So instead of a fixed image URL, you use one that contains a placeholder:
https://app.okzest.com/YOUR-DESIGN?name={{ first_name }}
When Klaviyo sends the email, it swaps {{ first_name }} for each subscriber's actual first name. The image service receives the name and renders a picture with that name drawn into the design. Subscriber "Sarah" gets an image that says Sarah; "James" gets one that says James - from a single line in your template.
Because the image renders when the email is opened (not when it's sent), it can also reflect live data - current pricing, latest leaderboard position, remaining stock - at the moment the recipient actually looks at it.
Step-by-step: personalized images in Klaviyo with OKZest
This walkthrough uses OKZest, which is built for exactly this. The whole thing takes about ten minutes the first time.
Step 1 - Design your image template
In OKZest, create a design at the size you need (a 1200 x 600 email header is a good starting point). Add your background, brand colors, and logo in the no-code editor - no design software required.
Then add a dynamic text layer where you want the personalization to appear, and give it a merge field name like name. This is the placeholder that will change per recipient. You can add several - name, company, product, price, whatever your Klaviyo data supports.
Step 2 - Get your image URL
OKZest gives you a single image URL for the design, with your merge fields as parameters:
https://media.okzest.com/img?c=your-design-id&name=SAMPLE
Test it by changing SAMPLE to a few different names in your browser - you'll see the image regenerate each time. That confirms it's working before it ever touches Klaviyo.
Step 3 - Insert Klaviyo's merge tags into the URL
Now replace the sample value with Klaviyo's merge tag. Match your OKZest parameter to the matching Klaviyo profile property:
https://media.okzest.com/img?c=your-design-id&name={{ first_name|default:'there' }}
The |default:'there' part is a Klaviyo fallback - if a subscriber has no first name on file, the image reads "there" instead of showing a blank. Always set a fallback so an empty field never produces a broken-looking image.
For multiple fields, chain them:
https://media.okzest.com/img?c=your-design-id&name={{ first_name|default:'there' }}&company={{ organization|default:'your team' }}
Step 4 - Add the image to your Klaviyo email
In the Klaviyo email editor, drag in an Image block (or a Text block if you need to hand-place the HTML). Instead of uploading a file, set the image source to your OKZest URL with the merge tags.
If you're using a table-based or HTML template, the image is a standard tag:
<img src="https://media.okzest.com/img?c=your-design-id&name={{ first_name|default:'there' }}" alt="A message for {{ first_name|default:'you' }}" width="600" />
Set a descriptive alt attribute (personalize it too) so the email still communicates if images are blocked, and set an explicit width so it renders predictably across clients.
Step 5 - Preview with real profiles and send
Use Klaviyo's Preview and test feature and select a few real profiles from your list. You'll see the image render with each person's actual data - the fastest way to catch a mismatched field name or missing fallback. Send yourself a test, confirm it looks right in Gmail and on mobile, then schedule as normal.
That's it. One image block now produces a unique visual for every subscriber, pulled from the Klaviyo data you already have.
Where this works best in Klaviyo
The flows where personalized images move the needle most:
Welcome series. A hero image that greets each new subscriber by name sets the tone that this brand pays attention.
Abandoned cart. Show the actual product left behind - image, name, price - rendered into a branded card. Far more persuasive than a generic "you left something behind."
Win-back campaigns. "We miss you, [Name]" hits differently as a designed graphic than as body text, especially with the subscriber's own data woven in.
Post-purchase and transactional. Branded, personalized order confirmations and shipping updates raise the perceived quality of the whole experience.
Loyalty and milestones. Points balances, tier status, anniversary cards - all live data OKZest can render into an image at open time.
Common questions
Do I need a developer? No. Everything above happens in the OKZest editor and the Klaviyo email builder. The only "code" is pasting a URL.
Will personalized images hurt deliverability? No - they're standard image URLs, and Klaviyo treats them like any other image. Follow normal best practice (reasonable text-to-image ratio, authenticated sending domain) and there's no deliverability penalty. OKZest also supports serving images from your own domain if you prefer.
Does it slow down sending? No. Because images render at open time rather than being pre-generated, there's no batch-processing delay before your campaign can go out - the send is ready as soon as the email is.
What if a subscriber's data field is empty?
Use Klaviyo's |default:'...' filter in the merge tag (shown above) so an empty field falls back to friendly text instead of a blank.
Or, use the fallback merge tag value in OKZest.
Which other ESPs does this work with? Any platform that lets you use a custom image URL with merge tags - Mailchimp, HubSpot, Campaign Monitor, SendGrid, and more. The concept is identical; only the merge-tag syntax changes.
Try it with your own Klaviyo account
Personalizing the image - not just the subject line - is one of the highest-leverage changes you can make to a Klaviyo flow, and it costs you one image block and about ten minutes of setup.
Create a free OKZest account, no credit card required. Build one template, drop the URL into your next Klaviyo welcome or abandoned-cart email, and compare the click-through rate against your last generic send.
For more on the strategy behind it, see personalized images in email, or if you run campaigns for multiple brands, the marketing agencies guide.