This feature is currently in beta testing. The API and functionality may change in future releases. We welcome feedback and suggestions as we refine this feature.
Overview
The seoMeta field type allows you to define SEO meta tags at the form/page level. These tags are extracted during Server-Side Rendering (SSR) and injected into the HTML <head> section, enabling:
Search Engine Optimization - Better indexing by Google, Bing, etc.
Social Media Previews - Rich previews when links are shared on Slack, Facebook, LinkedIn, Twitter, Discord, etc.
Dynamic Meta Tags - Use _calc expressions to populate tags from database data
Field Structure
Basic Schema
{"type":"seoMeta","metaTags":{"title":"Page Title - Your Brand","description":"Page description for search results","og:title":"Social Media Title","og:image":"https://yourdomain.com/image.jpg"}}
Properties
Property
Type
Required
Description
type
String
Yes
Must be "seoMeta"
metaTags
Object
Yes
Meta tag definitions
Behavior
In Editor (GUI)
Visible - Field appears in the form designer in the tree view
Editable - Designers can modify meta tags
No Rendering - Does not render in the actual form
In Production (Runtime)
Hidden - Field does not appear to users
SSR - Meta tags are extracted during SSR for bots/crawlers
Client-Side - Meta tags are also injected into document.head at runtime for regular users, enabling correct browser tab titles, social sharing from the SPA, and <html lang> attributes
Meta Tags Object
The metaTags object supports two types of values:
1. Static Values
2. Dynamic Values with _calc
Important: The _calc suffix is removed when rendering:
title_calc → becomes title in HTML
og:image_calc → becomes og:image in HTML
Supported Meta Tag Types
Special Keys
These keys have unique behavior and do not render as <meta> tags:
Key
Behavior
title
Sets <title> tag (browser tab / search result title)
language
Sets <html lang="..."> attribute. Defaults to "en" if omitted
_comment*
Ignored — for developer notes and organization
Standard Meta Tags
Use name="" attribute:
Renders as:
Open Graph (Facebook, LinkedIn, Slack)
Use property="" attribute:
Renders as:
Twitter Card
Use name="" attribute:
Renders as:
Article Meta (Blog Posts)
Use property="" attribute:
Product Meta (E-commerce)
Use property="" attribute:
Dynamic Expressions with _calc
Add _calc to any key to evaluate it as a JavaScript expression. The expression has access to the model object from the form's data model.
If both a static key and its _calc counterpart exist, _calc takes precedence.
Complete Examples
Static Page
Dynamic Page (using _calc)
Any key with a _calc suffix is evaluated as a JavaScript expression with access to model. The _calc version takes priority over the static key.
Requirements
Server-Side Rendering (SSR) Enabled per page
The seoMeta field only works with SSR enabled. Meta tags are extracted and rendered when:
A bot/crawler accesses the page (Googlebot, Facebookbot, etc.)
SSR is enabled for the form's layout in site settings
The form is successfully loaded with data
Form Data (onFormRequest)
For dynamic_calc expressions:
The form's onFormRequest hook must be enabled
The hook must populate the model object with data
SSR will fetch this data automatically
For static values:
No onFormRequest needed
Tags are rendered as-is
Validation & Best Practices
Character Limits
Tag
Recommended Length
title
50-60 characters
description
150-160 characters
og:title
60-90 characters
og:description
55-65 characters
twitter:title
70 characters
Image Requirements
Platform
Size
Aspect Ratio
Open Graph (Facebook, LinkedIn, Slack)
1200x630px
1.91:1
Twitter Large Image
1200x675px
16:9
Twitter Summary
120x120px (min)
1:1
Best Practices
✅ Always include fallbacks in _calc expressions
✅ Use absolute URLs for images
✅ Test previews on actual platforms (Slack, Facebook, etc.)
✅ Keep descriptions concise and compelling
✅ Use high-quality images (1200x630px minimum)
❌ Don't use relative URLs for og:image
❌ Don't exceed character limits (truncated by platforms)
Clear the platform's cache using their debugging tools
Facebook/LinkedIn/Twitter cache previews for 7 days
Use their inspector tools to force a refresh
Security
XSS Prevention
All meta tag values are automatically HTML-escaped to prevent XSS attacks:
Expression Safety
_calc expressions are evaluated with:
Limited scope (only model object available)
Error catching (failures are logged, not exposed)
No access to require(), process, or other Node.js APIs
Auto-Generated Tags
The following are injected automatically if not explicitly defined in metaTags:
Tag
Value
<link rel="canonical">
Current page URL
og:url
Current page URL
Page Language
Set the page language with the language key:
Renders as:
For dynamic language based on model data:
If omitted, defaults to "en".
Dynamic robots.txt and sitemap.xml
BetterForms automatically generates robots.txt and sitemap.xml for each tenant. Pages with ssr.enabled: true are allowed/listed; everything else is disallowed. No configuration required beyond enabling SSR per layout.