githubEdit

SEO Meta Tags

⚠️ PRELIMINARY FEATURE - BETA

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:

  1. A bot/crawler accesses the page (Googlebot, Facebookbot, etc.)

  2. SSR is enabled for the form's layout in site settings

  3. 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

  1. Always include fallbacks in _calc expressions

  2. Use absolute URLs for images

  3. Test previews on actual platforms (Slack, Facebook, etc.)

  4. Keep descriptions concise and compelling

  5. Use high-quality images (1200x630px minimum)

  6. Don't use relative URLs for og:image

  7. Don't exceed character limits (truncated by platforms)


Testing

Test as Bot

Use curl with a bot user-agent:

Look for meta tags in the <head> section.

Test Social Previews

  • Facebook Debugger: https://developers.facebook.com/tools/debug/

  • Twitter Card Validator: https://cards-dev.twitter.com/validator

  • LinkedIn Inspector: https://www.linkedin.com/post-inspector/

  • Slack: Just paste the link in any channel


Troubleshooting

Meta Tags Not Appearing

Check:

  1. Is SSR enabled for this layout?

  2. Is the form loading successfully?

  3. Are you testing with a bot user-agent?

  4. Does the seoMeta field exist in the form schema?

Dynamic Values Not Working

Check:

  1. Is onFormRequest enabled for the form?

  2. Is the model object populated with data?

  3. Are _calc expressions syntactically correct?

  4. Check server logs for evaluation errors

Social Previews Not Updating

Solution:

  • 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.


Feedback

This is a preliminary feature. Please share feedback or suggestions in the Slack channel #suggestions.


Last Updated: February 2026

Last updated

Was this helpful?