Blog System Documentation

This document provides a comprehensive guide to the blog system in Heatwave, covering content creation, SEO features, quality checks, and available plugins.

Table of Contents

  1. Overview
  2. Date Semantics
  3. Content Structure
  4. SEO & Structured Data
  5. Liquid Tags (Plugins)
  6. Quality Checks
  7. Related Content
  8. Comments System
  9. Revision History
  10. Feeds & Distribution
  11. CRM Administration

Overview

Blog posts (Post model) are a specialized type of Article that support:

  • Rich content with Liquid templating
  • Structured data extraction (FAQ, HowTo schemas)
  • Author attribution with bio pages
  • Comments and engagement tracking
  • SEO optimization tools
  • Revision history and content versioning

Post States

State Description
draft Work in progress, not visible to public
published Live on the website
scheduled Will auto-publish at publish_on date
archived Removed from public view

Date Semantics

The blog system uses three distinct date fields with specific meanings:

Field Purpose Public Display
published_at Original publication date Always shown in feeds/schema
revised_at Substantial content revision Shown as "last updated" when present
updated_at Internal tracking (any edit) Never shown publicly

Display Rules

  1. Blog post page:

    • If revised: "last updated [revised_at]"
    • If not revised: "published on [published_at]"
    • Note: Original publication date is preserved in JSON-LD/Atom for SEO but not shown visually
  2. Blog listings: Show revised_at if present, otherwise published_at

  3. Atom feed:

    • <published>: Always published_at
    • <updated>: revised_at if present, otherwise published_at
  4. JSON-LD BlogPosting:

    • datePublished: Always published_at
    • dateModified: revised_at if present, otherwise published_at
  5. Open Graph meta tags:

    • article:published_time: Always present
    • article:modified_time: Only present when revised_at is set

Setting Revision Date

In the CRM editor:

  • Manual: Set the "Revised at" date picker
  • Automatic: Check "Automatically update revised at" when saving (updates to current time)

Content Structure

Core Fields

Field Description Character Limit
subject Main title (H1 on page) 70 characters
title Page title (browser tab) 65 characters
description Summary/excerpt No limit (keep concise)
solution Main content body (HTML/Liquid) No limit
meta_description SEO description override 160 characters recommended
meta_keywords SEO keywords override Optional

Breadcrumbs

Breadcrumbs provide context for where the blog post fits in the site hierarchy.

Format options:

  • Simple path: /floor-heating
  • With custom title: Radiant Floor Heating@/floor-heating

Rules:

  • Must start with /
  • Auto-sorted by specificity (general → specific)
  • First public tag used if no breadcrumb defined

Tags

Tags categorize blog posts. Public tags appear in the URL structure.

Public tags (appear in navigation):

company-news, countertop-heaters, design-trends, example-projects, 
general-information, heat-tape-for-pipes, indoor-heating, installation, 
led-mirrors, mirror-defoggers, outdoor-heating, press-industry-report, 
press-release, product-information, radiant-floor-heating, radiant-panels, 
remodeling, roof-and-gutter-deicing, troubleshooting, share-your-story, 
shower-kits, snow-melting, towel-warmers, trade-professionals

SEO & Structured Data

Automatic Schemas

The system automatically generates:

  1. BlogPosting (via PostPresenter)

    • Title, description, author (Person with profile URL when available, else display name, else publisher org)
    • Publisher (Organization), inLanguage
    • datePublished and dateModified
    • wordCount (integer, schema.org camelCase), article body, featured image
  2. Breadcrumb (via formatted_breadcrumb helper)

    • One JSON-LD BreadcrumbList per page. Blog show renders breadcrumb only inside _post.html.erb (a duplicate hidden breadcrumb was removed — it had caused two identical BreadcrumbList blocks).

AI-Extracted Schemas

The BlogSchemaExtractor service uses AI (GPT-4) to extract:

Schema Type When Extracted
FAQPage Q&A content (unless embedded FAQ exists)
HowTo Step-by-step instructions, tutorials

Note: Article/BlogPosting schemas are NOT extracted (already handled).

Manual Schema Markup

In the CRM "Advanced" tab, you can add custom JSON-LD:

[
  { "@type": "FAQPage", "mainEntity": [...] },
  { "@type": "HowTo", "name": "How to Install...", "step": [...] }
]

Meta Tags Generated

<meta property="article:published_time" content="...">
<meta property="article:modified_time" content="..."> <!-- Only if revised -->
<meta property="article:author" content="...">
<meta property="article:section" content="...">
<meta property="article:tag" content="...">
<meta property="og:updated_time" content="..."> <!-- Only if revised -->

Liquid Tags (Plugins)

Available Liquid tags for blog content:

1. FAQ Tag

Embeds FAQ with inline JSON-LD schema.

{% faq 1234 %}
{% faq 1234,5678,9012 %}

2. Video Tag

Embeds a video player.

{% video 123 %}

3. Cloudflare Video

Embeds Cloudflare Stream video.

{% cloudflare_video abc123def %}

4. Image Tag

Responsive image with proper sizing.

{% image 456 width:800 alt:"Description" %}

5. Floor Heating Calculator

Interactive calculator widget.

{% floor_heating_calculator %}

6. Snow Melting Calculator

Interactive snow melt calculator.

{% snow_melting_calculator %}

7. Partial

Include shared content partials.

{% partial "shared/cta_block" %}

Quality Checks

Page Title Validation

  • Maximum 65 characters
  • Displayed with check/ban icon in CRM

Content Processing Options

Option Description
Sanitize URLs Fixes broken links, adds https scheme
Sanitize HTML Cleans inline styles, adds Bootstrap classes
Auto-update revised_at Updates revision date on save

Table of Contents

Enable has_toc to auto-generate navigation from headings:

  • Default selector: h2
  • Custom selector via toc_selector field

SEO Panel

The CRM shows an SEO overview panel with:

  • Site visits (30 days)
  • Ranking keywords count
  • Health score (AI-generated)
  • Quick links to locale-specific SiteMap details

Related Content

Manual Related Posts

Specify up to 4 related posts in the CRM editor.

Automatic Suggestions

The system uses semantic embeddings to find similar content:

  • Based on title, body, and product associations
  • Product context from breadcrumbs

Comments System

Blog posts support moderated comments:

  • Comments stored in post_comments table
  • Accessible via post.post_comments
  • Count displayed in CRM
  • Moderation interface at /posts/:id/post_comments

Revision History

Published posts support content revisions:

  1. Automatic versioning on significant edits
  2. Preview any historical revision
  3. Restore to previous version (creates new revision)
  4. Change notes for audit trail

Access via CRM post show page "Revision History" panel.


Feeds & Distribution

Atom Feed

Available at /posts.atom

  • Paginated with next/prev links
  • Entry includes full content
  • Proper published and updated timestamps

Referral Tracking

Each post auto-generates a Source for referral tracking:

  • Short URL via Bitly
  • Short URL with referral code
  • Source analytics integration

Edge Cache

Posts integrate with Cloudflare edge caching:

  • Auto-purge on publish/update
  • Tag-based bulk purging available
  • Purges related pages (index, tag pages)

CRM Administration

Post Editor Tabs

Tab Contents
Summary Title, author, dates, preview image
Content Rich text editor (TinyMCE)
Tagging Breadcrumbs, tags, meta fields
Related Up to 4 related post links
Advanced Content processing, TOC, schema markup, inline JS
Product Lines Associated products for context

Quick Actions

  • Preview: View unpublished posts (token-based, 1-hour expiry)
  • Publish/Unpublish: Change state
  • Duplicate: Create copy as draft
  • Extract Schema: Run AI schema extraction
  • Purge Cache: Clear CDN cache

Bulk Operations

  • Tag-based cache purge: Post.purge_all_posts_by_tag
  • Schema extraction worker: BlogSchemaExtractionWorker
  • Auto extraction: AutoBlogSchemaExtractionWorker

Best Practices

Content Quality

  1. Title: Keep under 65 characters for full display in search results
  2. Summary: Compelling excerpt that works as meta description
  3. Images: Always include a preview image for social sharing
  4. Breadcrumbs: Set appropriate context for SEO

SEO Optimization

  1. Revision dates: Use for substantial updates, not typo fixes
  2. Schema markup: Let AI extract, manually add only if needed
  3. Related posts: Link to relevant content to reduce bounce
  4. Tags: Use public tags for proper categorization

Content Freshness

  1. Review and update evergreen content periodically
  2. Set revised_at when making substantial updates
  3. This signals freshness to search engines and users

Technical Reference

Model: Post < Article

Key associations:

belongs_to :preview_image, class_name: 'Image', optional: true
belongs_to :source, optional: true
belongs_to :original_author, class_name: 'Employee', optional: true
has_many :post_comments, dependent: :destroy
has_many :site_maps, as: :resource

Key methods:

post.effective_published_date  # published_at || created_at
post.effective_revised_date    # revised_at || published_at
post.primary_tag               # First tag
post.main_public_tag           # First public tag
post.content_for_embedding     # Text for semantic search

Related Services

Service Purpose
BlogSchemaExtractor AI-powered schema extraction
PostPresenter View presentation logic, JSON-LD generation
BlogPreviewTokenService Secure preview URLs
Sitemap::SitemapGenerator XML sitemap integration

Last updated: January 2026