Skip to main content

What is the Text Block?

The Text block uses Liquid templating to format and combine data from previous workflow steps. Think of it as a powerful text formatter that lets you create custom outputs by mixing static text with dynamic data. Common use cases:
  • Format data for human-readable output
  • Combine multiple step outputs into one text
  • Create structured reports or summaries
  • Prepare content for Google Sheets or external APIs
  • Format lists and arrays as readable text
  • Transform JSON data into formatted text

How Does the Text Block Work?

  1. Write a template using Liquid syntax with placeholders
  2. Reference previous steps using {{step_X.output}} syntax
  3. Apply formatting using Liquid filters and tags
  4. Block executes and replaces placeholders with actual data
  5. Output is the formatted text ready for use

Configuration

Template (Required)

The template field where you write your Liquid template with placeholders for dynamic data. Basic examples: Simple output:
{{step_1.output}}
Access object properties:
Keyword: {{step_1.output.Keyword}}
Volume: {{step_1.output.Search_Volume}}
Loop through array:
{% for item in step_1.output %}
- {{item}}
{% endfor %}
Conditional formatting:
{% if step_1.output.volume > 10000 %}
High volume keyword
{% else %}
Low volume keyword
{% endif %}
Learn more: See Liquid Templating for complete syntax guide, filters, control flow, and examples.

Error Handling

Define what happens if the block fails to process the template. Options:
  1. Terminate Workflow: Stop execution immediately
  2. Continue Execution: Proceed to next step with empty output
Select based on whether subsequent steps require the formatted text.

Use Cases and Examples

Use Case 1: Format Keyword Research Data

Input from Keyword Overview block:
{
  "Keyword": "crm software",
  "Search Volume": "74000",
  "Keyword Difficulty Index": "76"
}
Text block template:
# Keyword Analysis Report

**Target Keyword:** {{step_2.output.Keyword | upcase}}

**Metrics:**
- Monthly Searches: {{step_2.output.Search_Volume}}
- Difficulty: {{step_2.output.Keyword_Difficulty_Index}}/100

{% if step_2.output.Keyword_Difficulty_Index > 70 %}
High difficulty - Consider long-tail variations
{% elsif step_2.output.Keyword_Difficulty_Index > 40 %}
Moderate difficulty - Good opportunity
{% else %}
Low difficulty - Quick win opportunity
{% endif %}
Output:
# Keyword Analysis Report

**Target Keyword:** CRM SOFTWARE

**Metrics:**
- Monthly Searches: 74000
- Difficulty: 76/100

High difficulty - Consider long-tail variations

Use Case 2: Create Numbered List from Array

Input from Related Keywords block:
[
  {"Keyword": "crm", "Search Volume": "165000"},
  {"Keyword": "hubspot", "Search Volume": "301000"},
  {"Keyword": "salesforce", "Search Volume": "450000"}
]
Text block template:
## Top Keywords by Search Volume

{% for kw in step_3.output %}
{{forloop.index}}. **{{kw.Keyword}}** - {{kw.Search_Volume}} monthly searches
{% endfor %}

Total keywords analyzed: {{step_3.output | size}}
Output:
## Top Keywords by Search Volume

1. **crm** - 165000 monthly searches
2. **hubspot** - 301000 monthly searches
3. **salesforce** - 450000 monthly searches

Total keywords analyzed: 3

Use Case 3: Filter and Format High-Volume Keywords

Input:
[
  {"Keyword": "crm", "Search Volume": "165000", "CPC": "16.63"},
  {"Keyword": "email marketing", "Search Volume": "5400", "CPC": "12.50"},
  {"Keyword": "marketing automation", "Search Volume": "8100", "CPC": "25.30"}
]
Text block template:
# High-Volume Keywords (10,000+ searches)

{% for keyword in step_1.output %}
  {% assign volume = keyword.Search_Volume | plus: 0 %}
  {% if volume > 10000 %}
- {{keyword.Keyword}}
  - Volume: {{keyword.Search_Volume | append: " searches/month"}}
  - CPC: ${{keyword.CPC}}
  - Estimated Value: ${% assign value = keyword.CPC | times: volume %}{{value}}
  {% endif %}
{% endfor %}
Output:
# High-Volume Keywords (10,000+ searches)

- crm
  - Volume: 165000 searches/month
  - CPC: $16.63
  - Estimated Value: $2743950

Use Case 4: Combine Multiple Step Outputs

Inputs:
  • Step 1: Keyword Overview
  • Step 2: Domain Overview
  • Step 3: LLM-generated content
Text block template:
# SEO Content Brief

## Target Keyword Analysis
Keyword: {{step_1.output.Keyword}}
Search Volume: {{step_1.output.Search_Volume}}
Difficulty: {{step_1.output.Keyword_Difficulty_Index}}

## Competitor Analysis
Domain: {{step_2.output.Domain}}
Organic Keywords: {{step_2.output.Organic_Keywords}}
Organic Traffic: {{step_2.output.Organic_Traffic}}

## Content Strategy
{{step_3.output}}

---
Generated: {{step_1.output.Keyword | capitalize}} content brief

Use Case 5: Create CSV Format

Input:
[
  {"Keyword": "crm", "Volume": "165000", "CPC": "16.63"},
  {"Keyword": "sales", "Volume": "74000", "CPC": "12.50"}
]
Text block template:
Keyword,Search Volume,CPC
{% for row in step_1.output -%}
{{row.Keyword}},{{row.Volume}},{{row.CPC}}
{% endfor %}
Output:
Keyword,Search Volume,CPC
crm,165000,16.63
sales,74000,12.50

Use Case 6: Format Loop Results

Input from Loop block:
[
  "Content brief for keyword 1...",
  "Content brief for keyword 2...",
  "Content brief for keyword 3..."
]
Text block template:
# Content Briefs Summary

{% for brief in step_5.output %}
## Brief {{forloop.index}}

{{brief}}

{% unless forloop.last %}
---
{% endunless %}
{% endfor %}

Total briefs generated: {{step_5.output | size}}

Use Case 7: Conditional Formatting Based on Metrics

Input:
{
  "Keyword": "crm software",
  "Search_Volume": "74000",
  "Keyword_Difficulty_Index": "76",
  "CPC": "14.24",
  "Competition": "0.27"
}
Text block template:
# Keyword: {{step_1.output.Keyword}}

{% assign difficulty = step_1.output.Keyword_Difficulty_Index | plus: 0 %}
{% assign cpc = step_1.output.CPC | plus: 0 %}
{% assign competition = step_1.output.Competition | plus: 0 %}

## Difficulty Assessment
{% if difficulty > 70 %}
Very Difficult ({{difficulty}}/100)
Recommendation: Consider long-tail variations or build authority first
{% elsif difficulty > 50 %}
Moderately Difficult ({{difficulty}}/100)
Recommendation: Achievable with good content and backlinks
{% else %}
Easy ({{difficulty}}/100)
Recommendation: Quick win opportunity
{% endif %}

## Commercial Value
{% if cpc > 20 %}
High Value Keyword (${{cpc}} CPC)
{% elsif cpc > 10 %}
Medium Value Keyword (${{cpc}} CPC)
{% else %}
Lower Value Keyword (${{cpc}} CPC)
{% endif %}

## Competition Level
{% if competition > 0.66 %}
High Competition ({{competition}})
{% elsif competition > 0.33 %}
Medium Competition ({{competition}})
{% else %}
Low Competition ({{competition}})
{% endif %}

Use Case 8: Extract and Format Specific Fields

Input:
[
  {"title": "Article 1", "url": "https://example.com/1", "snippet": "Description 1"},
  {"title": "Article 2", "url": "https://example.com/2", "snippet": "Description 2"},
  {"title": "Article 3", "url": "https://example.com/3", "snippet": "Description 3"}
]
Text block template:
# Research Sources

{% for source in step_1.output %}
### {{forloop.index}}. {{source.title}}

[{{source.url}}]({{source.url}})

{{source.snippet}}

{% endfor %}

Use Case 9: Create Markdown Table

Input:
[
  {"Keyword": "crm", "Volume": "165000", "Difficulty": "75"},
  {"Keyword": "sales", "Volume": "74000", "Difficulty": "68"}
]
Text block template:
| Keyword | Search Volume | Difficulty | Priority |
|---------|---------------|------------|----------|
{% for kw in step_1.output -%}
| {{kw.Keyword}} | {{kw.Volume}} | {{kw.Difficulty}} | {% if kw.Difficulty < 50 %}High{% elsif kw.Difficulty < 70 %}Medium{% else %}Low{% endif %} |
{% endfor %}
Output:
| Keyword | Search Volume | Difficulty | Priority |
|---------|---------------|------------|----------|
| crm | 165000 | 75 | Low |
| sales | 74000 | 68 | Medium |

Use Case 10: Summary Statistics

Input:
[
  {"Keyword": "crm", "Search_Volume": "165000"},
  {"Keyword": "sales", "Search_Volume": "74000"},
  {"Keyword": "marketing", "Search_Volume": "33100"}
]
Text block template:
{% assign keywords = step_1.output | map: "Keyword" %}
{% assign total_keywords = keywords | size %}
{% assign first_kw = step_1.output | first %}
{% assign last_kw = step_1.output | last %}

# Keyword Research Summary

**Total Keywords Analyzed:** {{total_keywords}}

**Top Keyword:** {{first_kw.Keyword}} ({{first_kw.Search_Volume}} searches)
**Last Keyword:** {{last_kw.Keyword}} ({{last_kw.Search_Volume}} searches)

**All Keywords:**
{{keywords | join: " | "}}

Use Case 11: Nested Data Access

Input:
{
  "organic": [
    {"title": "Result 1", "link": "https://example.com/1"},
    {"title": "Result 2", "link": "https://example.com/2"}
  ]
}
Text block template:
# Search Results

{% for result in step_1.output.organic %}
**{{forloop.index}}. {{result.title}}**
URL: {{result.link}}

{% endfor %}

Total results: {{step_1.output.organic | size}}

Best Practices

Template Design

  • Keep it readable: Use line breaks and indentation
  • Test incrementally: Build complex templates step by step
  • Comment your logic: Use {% comment %} for complex sections
  • Handle missing data: Use default values or conditionals

Data Formatting

  • Consistent formatting: Choose one style and stick to it
  • Meaningful labels: Use clear section headers
  • Visual hierarchy: Use headings, bullets, and spacing
  • Units and context: Include units (searches/month, $, %)

Performance

  • Avoid deep nesting: Keep loops and conditions simple
  • Limit loop iterations: Process large arrays carefully
  • Filter early: Apply filters before loops when possible
  • Reuse variables: Assign once, use multiple times

Common Patterns

  • Headers and footers: Add context at start and end
  • Separators: Use --- or {% unless forloop.last %} for clean formatting
  • Conditional formatting: Show/hide sections based on data
  • Data transformation: Convert formats for downstream blocks

Troubleshooting

Template Not Rendering

Problem: Output is empty or shows template code. Solution:
  • Check step references are correct (step_X)
  • Verify previous steps completed successfully
  • Test with simple template first: {{step_1.output}}

Filter Not Working

Problem: Filter produces unexpected results. Solution:
  • Check filter syntax: {{value | filter: "param"}}
  • Ensure data type matches filter (string/number/array)
  • Chain filters step by step to debug

Loop Not Iterating

Problem: For loop doesn’t produce output. Solution:
  • Verify input is an array: {{step_1.output | size}}
  • Check loop syntax: {% for item in step_1.output %}
  • Ensure array is not empty

Property Access Error

Problem: {{step_1.output.keyword}} shows blank. Solution:
  • Check exact property name (case-sensitive)
  • Verify object structure: {{step_1.output}}
  • Use array index if needed: {{step_1.output[0].keyword}}

Condition Not Working

Problem: If statement doesn’t behave as expected. Solution:
  • Check comparison operators: ==, >, <, >=, <=, !=
  • Convert strings to numbers: {% assign num = value | plus: 0 %}
  • Use and/or for multiple conditions

What’s Next

Now that you understand the Text block: