Javascript · 5 min read · Updated

Dynamic JSON-LD Schema on Webflow CMS Template Pages (Without Invalid JSON)

Generate BlogPosting and FAQ structured data from Webflow CMS fields, and avoid the escaping problems that silently invalidate your schema.

Webflow CMS JSON ld schema

Structured data helps search engines understand your pages and can make them eligible for rich results. On a Webflow site, most pages worth marking up, such as blog posts, products, locations, and team members, are CMS template pages. That means one template can produce valid schema for hundreds of pages. It can also produce invalid schema on hundreds of pages if you get it wrong.

Where to put it

Open the CMS template page (for example, Blog Posts Template), then go to Page settings → Custom code → Inside <head> the tag. In this field, you can insert CMS fields with the + Add field button. They appear as {{wf {"path":"name",...} }} placeholders, which the editor shows as purple field pills.

A basic BlogPosting schema

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "{{Name}}",
  "description": "{{Meta Description}}",
  "image": "{{Main Image}}",
  "datePublished": "{{Published On}}",
  "dateModified": "{{Updated On}}",
  "author": {
    "@type": "Person",
    "name": "{{Author: Name}}"
  },
  "publisher": {
    "@type": "Organization",
    "name": "Your Company",
    "logo": { "@type": "ImageObject", "url": "https://www.example.com/logo.png" }
  },
  "mainEntityOfPage": "https://www.example.com/blog/{{Slug}}"
}
</script>

({{Name}} here stands for the field pill you insert. Don’t type curly braces by hand.)

Date formats

When you insert a date field, Webflow asks for a format. Schema.org expects ISO 8601, so pick the ISO-style option or a custom format that produces 2026-10-17. “October 17, 2026” may be accepted by some parsers, but it isn’t the format Google documents.

The escaping problem

As with Embeds, Webflow inserts the raw field value into custom code. If a post title contains a double quote:

How to Build a "Mega Menu" in Webflow

your schema becomes:

"headline": "How to Build a "Mega Menu" in Webflow",

That’s invalid JSON. Google drops the whole block without telling you, and you’ll only notice in Search Console’s enhancement reports, if at all. Backslashes and line breaks in plain-text fields (common in multi-line descriptions) cause the same problem.

Fix 1: Control your content

  • Use typographic quotes (“ ”) rather than straight " quotes in titles and summaries. Curly quotes are valid inside a JSON string.
  • Use single-line plain text fields for anything that goes into schema.
  • Add a note to the field’s help text in the collection settings, e.g., “Used in SEO schema. Avoid straight double quotes.”

This is the simplest fix and works on sites where only a few people edit content.

Fix 2: Build the schema in JavaScript from attributes

To make it robust, let the browser do the escaping. Put the CMS values in attributes, which Webflow escapes correctly, and assemble the JSON with JSON.stringify, which escapes for JSON.

In the template, add a hidden div (or use any element) with custom attributes bound to fields:

id                = schema-source
data-headline     → {Name}
data-description  → {Meta Description}
data-image        → {Main Image}
data-published    → {Published On}   (ISO format)
data-author       → {Author: Name}
data-slug         → {Slug}

Then in Before </body> tag on the template page:

<script>
  (function () {
    var s = document.getElementById('schema-source');
    if (!s) return;
    var d = s.dataset;
    var schema = {
      '@context': 'https://schema.org',
      '@type': 'BlogPosting',
      headline: d.headline,
      description: d.description,
      image: d.image,
      datePublished: d.published,
      author: { '@type': 'Person', name: d.author },
      mainEntityOfPage: location.origin + '/blog/' + d.slug
    };
    var tag = document.createElement('script');
    tag.type = 'application/ld+json';
    tag.textContent = JSON.stringify(schema);
    document.head.appendChild(tag);
  })();
</script>

Trade-off: Google renders JavaScript and does pick up JSON-LD injected this way, but it happens in the rendering stage, which can be delayed. Other crawlers and some SEO tools only read the raw HTML. If your content is clean, Fix 1 (static JSON in the head) is more widely supported. If you can’t control what editors type, Fix 2 is safer.

FAQ schema from a multi-reference or nested list

Say each service page has a multi-reference field linking to FAQ items. Add a Collection List of FAQs on the template, bind the question and answer to elements, and give them attributes:

<div class="faq-item" data-faq-q="{Question}">
  <div class="faq-answer">{Answer (rich text)}</div>
</div>
var faqs = [...document.querySelectorAll('.faq-item')].map(function (el) {
  return {
    '@type': 'Question',
    name: el.dataset.faqQ,
    acceptedAnswer: {
      '@type': 'Answer',
      text: el.querySelector('.faq-answer').innerText.trim()
    }
  };
});

if (faqs.length) {
  var tag = document.createElement('script');
  tag.type = 'application/ld+json';
  tag.textContent = JSON.stringify({
    '@context': 'https://schema.org',
    '@type': 'FAQPage',
    mainEntity: faqs
  });
  document.head.appendChild(tag);
}

Google now limits FAQ rich results to a small set of authoritative sites, so don’t count on the visual result. The markup still helps machines understand the page.

Conditional fields

If a field is empty, Webflow inserts an empty string, so you get "image": "", which validators flag. With the JavaScript approach, remove empty values before stringifying:

function clean(obj) {
  Object.keys(obj).forEach(function (k) {
    if (obj[k] && typeof obj[k] === 'object') clean(obj[k]);
    if (obj[k] === '' || obj[k] == null) delete obj[k];
  });
  return obj;
}
tag.textContent = JSON.stringify(clean(schema));

Validate on real pages

  1. Publish to staging.
  2. Pick the CMS items with the messiest content: long titles, quotes, empty images.
  3. Test them in Google’s Rich Results Test and the Schema.org validator.
  4. After going live, check Search Console → Enhancements over the next few weeks.

Templates fail on the unusual items, not the clean ones you check first, so test the messy items before you publish.

Webflow custom code series: 1. Host JavaScript on Webflow’s CDN · 2. MIME types and the asset CDN · 3. Where custom code runs · 4. CMS data in JavaScript · 5. JSON-LD on CMS pages · 6. Local dev workflow · 7. Forms to your own API · 8. Custom code via the Data API · 9. Third-party scripts and Core Web Vitals. Preparing for the exam too? See the Webflow Visual Developer Certification guide.

Rupak Nepali
Written byRupak Nepali

Author of four Opencart book.
The recent are Opencart 4 developer book and Opencart 4 user manual

Leave a Reply

Your email address will not be published. Required fields are marked *