Back to Blog
Email Marketing

Klaviyo Dynamic Content: A Practical Guide for Ecommerce Marketers

Discover how Klaviyo dynamic content enhances email marketing by personalizing messages based on subscriber behavior to boost engagement.

15 min read
Klaviyo Dynamic Content: A Practical Guide for Ecommerce Marketers

Klaviyo Dynamic Content: A Practical Guide for Ecommerce Marketers

Klaviyo dynamic content is any part of an email that automatically changes based on a recipient’s behavior or profile data — so two subscribers opening the same campaign can see completely different products, offers, or sections. The three core mechanisms are show/hide logic (template blocks that appear or disappear based on profile conditions), dynamic table blocks (flow-specific rows that repeat for each item in an event array like line_items), and personalization tags (variables that pull profile or event data directly into text). You’ll use these across:

  • Abandoned cart flows (showing the exact products left behind)
  • Order confirmation and shipping emails (listing purchased items with images and prices)
  • Campaign hero sections (swapping content for VIP vs. standard subscribers)

Key Takeaways

Klaviyo dynamic content works best when you match the right feature to the right data source: dynamic table blocks for event arrays in flows, show/hide logic for profile-driven campaigns, and product feeds for catalog-based recommendations.

Point Details
Match feature to data source Dynamic table blocks need event arrays; show/hide blocks use profile properties; product feeds use your catalog.
Flows unlock event data Dynamic table blocks only work in metric-triggered flows — campaigns cannot access event arrays.
Test with real event data Use the preview modal to copy exact variable paths and always verify fallback content before sending.
Track revenue per recipient Open and click rates are leading indicators; revenue per recipient shows whether dynamic content is actually converting.
Take-action for implementation Take-action sets up flow dynamic tables, property governance, and testing cadences for ecommerce brands on Klaviyo.

Table of Contents

Why Klaviyo dynamic content matters for your email program

Sending the same email to every subscriber is the fastest route to a shrinking list. Klaviyo frames dynamic content as the antidote to messaging fatigue — relevance at scale keeps subscribers engaged instead of reaching for the unsubscribe link.

The practical benefits:

  • Higher open and click rates — personalized subject lines and content blocks give recipients a reason to engage rather than delete
  • Lower unsubscribe rates — subscribers who see content that matches their behavior or preferences are less likely to opt out
  • Fewer campaign variants to maintain — one template with show/hide logic replaces three or four separate campaigns built for different segments
  • Better revenue per recipient — showing the right product at the right moment in a flow converts at a higher rate than a generic recommendation

The metrics worth tracking once you go live: open rate, click-through rate, conversion rate, and revenue per recipient. Revenue per recipient is the one most teams ignore early on, and it’s the clearest signal of whether your personalization is actually moving the needle.


The main types of dynamic content in Klaviyo

Klaviyo supports four distinct dynamic content features, each suited to a different data source and use case:

  • Personalization tags — the simplest form. These are variables like {{ person.first_name }} (profile data) or {{ event.extra.order_total }} (event data) dropped directly into text or subject lines. Profile variables pull from stored contact properties; event variables pull from the specific action that triggered the flow.

  • Show/hide logic blocks — template-level conditional display. A block is shown or hidden based on profile property conditions you set in a point-and-click builder. Good for swapping hero images, offers, or copy based on loyalty tier, gender, or custom preferences.

  • Dynamic table blocks — the workhorse for transactional flows. These repeat a row of content for each item in an event array, so an abandoned cart with four products automatically generates four product rows. They only work inside metric-triggered flows.

  • Product feed blocks — catalog-driven product recommendations surfaced in campaigns or flows. Unlike dynamic table blocks, product feed blocks pull from your catalog rather than a specific trigger event, making them better suited for curated recommendations than for transaction-specific lists.

The profile vs. event distinction matters more than most teams realize. Profile variables are available everywhere — campaigns and flows alike. Event variables only exist in metric-triggered flows, because they reference the specific action (a checkout, a purchase) that fired the flow.


How to build a dynamic table block in a flow email

This walkthrough uses an abandoned cart flow as the example, which is the most common starting point for dynamic table blocks.

  1. Set the right flow trigger. Dynamic table blocks require a metric-triggered flow. For abandoned cart, use the Started Checkout metric. For order confirmation, use Placed Order. Without a metric trigger, the event array that feeds the table doesn’t exist.

  2. Add an email to the flow and open the template editor. Drag an email block into the flow canvas, then open the template. If you’re starting from scratch, Klaviyo’s flow library includes prebuilt abandoned cart and order confirmation templates with dynamic blocks already configured — a faster starting point than building from zero.

  3. Drag a table block into the email. In the content panel, find the table block and drag it into the email body. By default it’s a static table.

  4. Convert it to Dynamic. Click the table block, then toggle it from Static to Dynamic in the block settings panel. This unlocks the Row collection and Row alias fields.

  5. Set the Row collection. This is the event array you want to loop through. For a Started Checkout trigger, the path is typically event.extra.line_items. Paste that path into the Row collection field.

  6. Set the Row alias. The alias is a short label you’ll use inside the row to reference each item. Set it to something like item. Once the alias is set, a variable like {{ event.extra.line_items.0.title }} becomes simply {{ item.title }} inside the row — cleaner and less error-prone.

  7. Configure the columns. Add columns for product image, title, price, and a link back to the product page. Each column maps to a property on the alias object: {{ item.image }}, {{ item.title }}, {{ item.price }}, {{ item.product_url }}.

  8. Set fallback content. If the event fires but the array is empty or sparse, you need a fallback row. Enable the fallback option in the block settings and add a generic “Continue shopping” row or a curated product recommendation. Without a fallback, an empty array renders a blank space in the email.

  9. Preview and test. Open the preview modal, select a profile that has a real Started Checkout event, and verify that the rows populate correctly. The preview modal also exposes the exact account-specific variable paths for your store — copy them directly rather than guessing the structure.

Pro Tip: Never type variable paths from memory. Use the preview modal to copy the exact path for your account’s event data. A single underscore vs. hyphen difference in a variable name renders the entire row blank with no error message.


How show/hide logic and Django conditionals work in Klaviyo

Show/hide logic lives at the template block level. Select any content block in the editor, open Show/hide logic, and you’ll find a point-and-click builder where you set conditions based on profile properties.

What the builder handles well:

  • Text comparisons (loyalty_tier equals "VIP")
  • Numeric comparisons (total_orders greater than 5)
  • List membership checks (favorite_category contains "footwear")
  • AND/OR combinations across multiple conditions

What it cannot handle natively:

  • Event arrays (you can’t check whether a cart contains a specific product category through the builder)
  • Complex date math (e.g., showing a block only if a purchase was more than 90 days ago)
  • Some boolean patterns and data types the builder doesn’t recognize

When the builder hits its limits, you drop into the block’s Source field and write Django-style conditionals directly. A basic example:

{% if person|lookup:'loyalty_tier' == 'VIP' %}
  [VIP content block]
{% else %}
  [Standard content block]
{% endif %}

One practical workaround for segment-based conditions: the builder doesn’t accept segment membership as a condition directly. Instead, write a small profile property (like is_vip: true) via a flow that runs when someone enters a VIP segment, then reference that property in the show/hide builder. It’s an extra setup step, but it keeps your template logic clean.

Pro Tip: After saving a block with custom Django code, always check the Source field again. The visual editor can sometimes reformat or strip custom code when you switch between views. Validate the code is intact before sending a test.


When to use dynamic blocks vs. static blocks

Most ecommerce emails don’t need heavy in-email logic. The question is whether the content difference between subscribers is large enough to justify the setup time.

Use dynamic table blocks (flow) for:

  • Abandoned cart emails — product rows for each item left behind
  • Order confirmation emails — purchased items with images, quantities, and prices
  • Shipping and fulfillment notifications — items in the shipment
  • Cancellation notices — items from the cancelled order

Use show/hide blocks (campaign or flow) for:

  • VIP vs. standard subscriber offers in a broadcast campaign
  • Regional promotions where most of the email is identical
  • Gender- or preference-based hero image swaps
  • Loyalty tier messaging in a post-purchase flow
Feature Best for Data source Works in campaigns?
Dynamic table block Transaction-specific product lists Event array (e.g., line_items) No — flow only
Product feed block Curated or catalog recommendations Product catalog Yes
Show/hide block Conditional section display Profile properties Yes

When the logic gets complex enough that you’re stacking five or six show/hide conditions, consider whether a conditional split in the flow or a separate campaign segment would be cleaner. In-email logic is powerful, but a flow branch is easier to debug and measure independently.


Testing checklist and common pitfalls

Broken dynamic content fails silently. A subscriber sees a blank product row or the wrong offer, and you only find out when revenue per recipient drops.

Testing checklist:

  1. Open the preview modal and select a profile with a real trigger event — not a profile with no event history.
  2. Verify every dynamic row populates with real data (image, title, price, link).
  3. Test the fallback: preview with a profile whose event array is empty or missing, and confirm the fallback row appears.
  4. Send a test email to a seeded inbox with representative event data and check rendering across Gmail, Apple Mail, and Outlook.
  5. Click every link in the test email — product URLs built from event variables sometimes include encoding errors that only appear in a live send.
  6. Check currency formatting if your store sells in multiple currencies. Event variables pull the value stored in the event, which may not match the subscriber’s locale.

Common pitfalls:

  • Guessing variable names. The preview modal shows exact variable paths for your account. Use them.
  • Treating segment membership as a profile property. The show/hide builder can’t check segment membership directly. Write a property via a flow instead.
  • Skipping fallback content. If the event fires but the array is sparse, no fallback means a blank block in the email.
  • Wrong aliasing. If you set the Row alias to item but reference {{ product.title }} in the column, the row renders empty.
  • Enabling dynamic table blocks in campaign emails. They don’t work there — use a product feed block instead.

Agency-grade best practices from Take-action

Scaling dynamic content without a governance plan creates a different problem: templates that nobody can maintain six months later.

Operational checklist:

  • Document every profile property your templates reference, including the exact key name and expected data type. A shared naming convention prevents the loyalty_tier vs. loyaltyTier mismatch that breaks show/hide logic.
  • Run a testing cadence before every major send: preview modal check, test send to seeded profiles, fallback verification.
  • Keep a static-control version of any email where you’re testing dynamic blocks. Measuring lift against a static send is the only reliable way to quantify what dynamic content is actually contributing.
  • Build a rollback plan. Know which template version to revert to if a dynamic block fails in production.

Metrics to track:

  • Open rate and click-through rate (baseline engagement signal)
  • Conversion rate per flow (did the dynamic product row drive a purchase?)
  • Revenue per recipient (the clearest ROI signal for dynamic content)
  • Incremental revenue from dynamic blocks vs. static control sends

On scaling: start with one flow (abandoned cart is the right first choice), get the dynamic table working reliably, measure lift, then expand to order confirmation and post-purchase. Centralizing logic in a master template works well for show/hide blocks; event-driven dynamic tables belong in the flow itself.

Klaviyo’s AI features, including channel affinity and personalized send times, extend personalization beyond content to timing and channel. Once your dynamic content is stable, layering in AI-driven send time optimization compounds the gains. For advanced segmentation that feeds richer profile properties into your show/hide logic, RFM-based segments built for Klaviyo flows give you a cleaner data foundation than manually maintained lists.

Pro Tip: *A/B test the dynamic block against a static version of the same email before rolling out to your full list.


Dynamic content in campaigns vs. flows: key differences

The functional difference comes down to what data is available at send time.

Campaigns (broadcast sends):

  • Profile data is available at send time — show/hide logic and personalization tags work well
  • Product feed blocks surface catalog recommendations based on rules you set (bestsellers, new arrivals, category-specific)
  • No access to event arrays, because campaigns aren’t triggered by a specific customer action
  • Best for wide broadcasts where the content difference between subscribers is block-level (swap a hero image, show a VIP offer)

Flows (event-triggered automations):

  • Both profile data and event data are available
  • Dynamic table blocks repeat rows for each item in the trigger event’s array — this is what makes abandoned cart and order confirmation emails work
  • Event variables are only valid for the duration of the flow triggered by that event
  • Best for transaction-specific emails where the content is unique to each customer’s action
Scenario Right feature Right context
Show 3 recommended products in a newsletter Product feed block Campaign
List every item in an abandoned cart Dynamic table block Metric-triggered flow
Swap hero image for VIP subscribers Show/hide block Campaign or flow
Display purchased items in order confirmation Dynamic table block Metric-triggered flow

For Klaviyo flow setup and trigger selection, the trigger metric determines which event data is available — choosing the wrong trigger is the most common reason a dynamic table block renders empty.


Ready to get dynamic content working in your Klaviyo account?

Most ecommerce brands know they should be using dynamic content in their flows. The gap is usually in the setup: wrong triggers, missing fallback content, or profile properties that don’t exist yet. Take-action builds and manages the full stack — flow architecture, dynamic table configuration, property governance, and a testing cadence that catches errors before they reach subscribers.

Take-action

If you want your abandoned cart, order confirmation, and post-purchase flows running with reliable dynamic blocks, Take-action’s email marketing services cover the setup, testing, and ongoing measurement. For personalization strategies and Klaviyo email tactics that go beyond the basics, the Take-action blog is a practical next read. Book a free scoping call to see where your current flows have gaps.


How Take-action approaches dynamic content projects

Every dynamic content project at Take-action starts with a discovery phase: auditing which profile properties actually exist in the account, which events are firing reliably, and where the naming conventions have drifted. That audit almost always surfaces the same issue — brands have the data they need, but it’s stored under inconsistent key names that break template logic.

From there, the workflow is a single pilot flow (abandoned cart in most cases), built with a dynamic table block, fallback content, and a static control variant running in parallel. After two to four weeks of data, the lift is measurable and the template is proven before scaling to order confirmation, shipping, and post-purchase flows. Property governance and a naming standard are documented before any template goes live, so the next person to edit the template isn’t guessing at variable paths.

Sources

  • What is Dynamic Content? - Klaviyo

Share this article

Ready to transform your email marketing?

Let's discuss how we can help you achieve similar results for your brand with strategic email campaigns.