Structure Data: Using variables as part of the data

I couldn’t find anything on this but how do I use variables in Structure Data on the page’s MetaData.

I want to use my page’s title which comes from the API endpoint’s data.

GPT is suggesting I use something like this:

{{
    JSON.stringify({
      "@context": "https://schema.org",
      "@type": "JobPosting",
      "title": JobsById.data.job_title,
      "description": JobsById.data.description,
      "employmentType": JobsById.data.job_type || "FULL_TIME",
      "datePosted": JobsById.data.date_posted || new Date().toISOString(),
      "validThrough": JobsById.data.valid_through || "2025-12-31",
      "hiringOrganization": {
        "@type": "Organization",
        "name": JobsById.data.company_name,
        "sameAs": JobsById.data.company_url || "https://your-default-url.com"
      },
      "jobLocation": {
        "@type": "Place",
        "address": {
          "@type": "PostalAddress",
          "addressLocality": JobsById.data.location || "London",
          "addressCountry": JobsById.data.country || "UK"
        }
      },
      "baseSalary": {
        "@type": "MonetaryAmount",
        "currency": "USD",
        "value": {
          "@type": "QuantitativeValue",
          "value": JobsById.data.salary || 0,
          "unitText": "YEAR"
        }
      }
    })
  }}

But when published, this doesn’t work.

T.

Hi Toby, If I understand correctly, what you’re trying to do is have each page show specific data depending on the item, right?

Option 1: Use a WeWebPageCollection

One way to do this is by creating a WeWebPageCollection, which automatically generates a page for each record in your database. This is great for static content and SEO, because each page is indexed and pre-rendered.

However, this means the collection has to be set to static, so if you update a record or add a new one, you’ll need to:

  • Refetch the collection, and
  • Republish the project every time.

That can be a bit of a problem if your app is meant to be dynamic and updated frequently.


Option 2: Use Dynamic Pages with Inputs

Another option is to create a single dynamic page that takes an ID as input.
Then, in the onPageLoad workflow, you can fetch the data from your backend using that ID Page Parameter and have it stored in a collection like currentItem.

That way, the page content is always fresh and dynamic.
The downside? It’s not ideal for SEO, since the content isn’t pre-rendered for crawlers.


Option 3: Use Page Variables

Finally, if you’re navigating from one page to another and already have the data, you could just store the values in a variable (instead of re-fetching them), and bind from there.
This is kind of like using a collection, but handled more manually.

I hope that was useful.

Best,
Bruno

1 Like

I have the job pages set to static so this is fine.

However, what you can’t do is inject some data (job title for ex) into the structured data JSON.
T.

Hi, you can simply build your object as you would normally and then use the JSON.stringify() method to turn it into a string and embed it in your app.

Sure but this isn’t in the pages meta data

What you want to achieve is not achievable by the code you posted, it’s a whole different concept of structured data, which show in SERP. :slight_smile:

Ignoring the code for a minute – Just having dynamic variables into the structured data section of the meta data of the page is pretty standard. I can do this in webflow, so my question is – is it possible in WeWeb which doesn’t seem to be the case.

So I’ve actually been able to achieve this through a lot of trial and error.

The trick is to create a “coded component” that injects the JSON-LD, as it isn’t possible any other way.

Here is a Ai summary of my working component that achieves this which you can use to prompt with WeWeb Ai to build your own component as needed with schema you desire. You then just make it non visible on the page so it can inject in the background.

Vue component that injects JSON-LD structured data for products into the page's <head>.
What it does:

Creates Schema.org Product markup for SEO
Doesn't render anything visible (hidden component)
Dynamically injects/updates a <script type="application/ld+json"> tag

Required props:

name - Product name
description - Product description
image - Product image URL
price - Product price
priceCurrency - Currency code (e.g., "USD")

Optional props:

availability - Stock status (defaults to "InStock")
url - Product URL

Key features:

Auto-updates the JSON-LD when props change
Cleans up the script tag when component unmounts
Only injects schema if all required fields are present
Uses WeWeb's wwLib.getFrontDocument() for document access

Here is the product and screenshot from Google console showing the schema live and working :slight_smile:

I’m not entirely sure if I’m honest why this works, as other methods I tried didn’t work (custom html, custom scripts). It’s all to do with the lifecycle of the app of content sequentially loads. Something along these lines:

The component works by using Vue's lifecycle hooks to inject a <script type="application/ld+json"> tag directly into the document head via wwLib.getFrontDocument(), which Google's crawler detects during its JavaScript rendering phase despite being added post-initial-load.

SSR is what we truly need however, which is getting focus by WW in Q4 2025 as it’s on the roadmap.

Hey What Gift, just stumbled the same wall as you.

I understand this may not be the ideal option since it’s not a native integration, but what do you think about the option I mentioned in the following post? →

- Post - WeWeb SSR, SEO, and Static Collection Behaviour - WeWeb Community

I suspect this works as this gets injected in the header correctly, where as the HTML component is injected in the body which isn’t correct.

I’ll go down this route, just seems a massively dumb oversight not to include a functional structured data feature in the page’s metadata parameters.

It’s such an easy fix.

T.

I don’t think it’s because you can’t inject into the header, which you can do with the custom HTML script, it’s the lifecycle part and access to dynamic data at runtime for crawlers that’s the issue.