# Toggling/modifying default \`ghost\_head\` Structured Data

**URL:** <https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537>\
**Category:** Developer help\
**Created:** [October 20, 2025, 9:57am UTC](https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537 "2025-10-20T09:57:03Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Collxn\_Ash](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/collxn_ash/32/37564_2.png) [@Collxn\_Ash](https://forum.ghost.org/u/Collxn_Ash)\
**Post date:** [October 20, 2025, 9:57am UTC](https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537/1 "2025-10-20T09:57:03Z")

</div>

Hi everyone, this is partially a question but also some rubber ducking in hopes it’s useful for others.

# Question

As a theme developer, it appears there is no way to programmatically toggle or modify the structured data emitted from `ghost_head`… correct?

# Context

`ghost_head` emits some JSON-LD structured data already:

- `WebSite`
- `Article`(apparently for post posts _and_ pages)

The data contained within is set manually by the end user within Ghost Admin.

# Why you might want to toggle/modify the ghost\_head structured data

If you’re adding more structured data to your custom theme, it’s possible you’d like to have centralized control over _all_ structured data, including `WebSite` and `Article`, in the code base.

For example, I have the following setup in my custom theme:

- `data/schema.json`
- `partials/schema/<schema_object>.hbs` (auto-generated JSON-LD scripts)
- `scripts/build-schema.mjs`

Before build-time, I call the script which builds the partials based on the JSON data. The templates then pick up these partials (the JSON-LD scripts) at build time.

However, I can’t control `WebSite` or `Article` at the code level because that’s coming from `ghost_head`.

# Why you might _not_ want to do this

If you have an end user who wants to control this stuff directly, the setup I loosely describe above will not work, since structured data edits would require code-level access.

I’m not trying to ship a downloadable theme in this case, and the single user I’m building the theme for doesn’t want this level of control.

(This is surely a solvable problem, but out of scope for this post and for my current needs.)

# Workaround

The only workaround I’m aware of is to forego `ghost_head` entirely and write your own `head` instead.

That’s certainly a path one could take, but it’s too heavy-handed for my needs, so I’m sticking with `ghost_head` and living with the structured data that it provides “for free”.

# Relevant past forums questions

> [@How to edit the output of {{ghost\_head}}](https://forum.ghost.org/t/how-to-edit-the-output-of-ghost-head/5392):
>
> Hi Guys, Basically I want to take advantage of Google’s Freshness Factor To get a ranking Boost as explained in this post [1 Easy Google Freshness Tip When Updating Website Content](https://bit.ly/2WsPBzv) From my research, I found out that the tag {{ghost\_head}} in default.hbs of Casper theme is responsible for outputting structured data. What I want to do is edit the structured data so that the datePublished value is always equal to the dateModified value. Any ideas where I should be looking? I also want to fix th…

> [@How to add more Structured Data to posts and pages on top of Ghost's output](https://forum.ghost.org/t/how-to-add-more-structured-data-to-posts-and-pages-on-top-of-ghosts-output/38972):
>
> Hi there, Does anyone know how to add more structured data to what Ghost already produces as default. I know that Ghost, by default, adds Article schema for all posts. But how do we extend the structured data by including more schema properties, on top of what Ghost generates. @Cathy_Sarisky @denvergeeks do you have any suggestions?

> [@Edit/Add JSON-LD](https://forum.ghost.org/t/edit-add-json-ld/6008/4):
>
> Hey no problem relaxed The code that generates the structured data is located within Ghost core, [https://github.com/TryGhost/Ghost/blob/master/core/server/data/meta/schema.js](https://github.com/TryGhost/Ghost/blob/master/core/server/data/meta/schema.js) If you want to change the values without modifying the Ghost core, you should update the name and logo of your publication on the “General” settings screen in your Ghost Admin

---

<div class="post-metadata">

**Author:** ![Cathy\_Sarisky](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/cathy_sarisky/32/25750_2.png) [@Cathy\_Sarisky](https://forum.ghost.org/u/Cathy_Sarisky)\
**Post date:** [October 20, 2025, 11:29am UTC](https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537/2 "2025-10-20T11:29:32Z")

</div>

You can opt out of just the structured data, and you can use handlebars logic to choose which types of content opt out.

When I did the work, the docs weren’t open source, so I didn’t patch the docs, and I guess no one else did, either. But here’s my write up on those options:

> **[Making {{ghost\_head}} better](https://www.spectralwebservices.com/blog/adding-new-features-to-ghost-head/)**
>
> Know how I'm always griping about ghost\_head being a monolith? I did something about it!

---

<div class="post-metadata">

**Author:** ![Collxn\_Ash](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/collxn_ash/32/37564_2.png) [@Collxn\_Ash](https://forum.ghost.org/u/Collxn_Ash)\
**Post date:** [October 21, 2025, 1:37am UTC](https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537/3 "2025-10-21T01:37:56Z")

</div>

Woah, this is incredible. Thank you @Cathy_Sarisky!

---

<div class="post-metadata">

**Author:** ![Collxn\_Ash](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/collxn_ash/32/37564_2.png) [@Collxn\_Ash](https://forum.ghost.org/u/Collxn_Ash)\
**Post date:** [October 21, 2025, 2:35am UTC](https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537/4 "2025-10-21T02:35:37Z")

</div>

@Cathy_Sarisky as a follow-on to this:

Everything I described above works fine for static content: just build and ship.

But posts and pages are dynamic. New ones will be created between builds and data for existing ones could change. This data is user-generated and could contain characters that we don’t want in the JSON.

Is there an officially supported way to safely serialize dynamic content for use in JSON-LD? For example, a JSON stringify helper or the like?

---

<div class="post-metadata">

**Author:** ![Cathy\_Sarisky](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/cathy_sarisky/32/25750_2.png) [@Cathy\_Sarisky](https://forum.ghost.org/u/Cathy_Sarisky)\
**Post date:** [October 21, 2025, 2:47am UTC](https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537/5 "2025-10-21T02:47:19Z")

</div>

There’s not an official json stringify helper, but it is possible (painfully) to assemble jd+json using existing handlebars helpers.

---

<div class="post-metadata">

**Author:** ![Collxn\_Ash](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/collxn_ash/32/37564_2.png) [@Collxn\_Ash](https://forum.ghost.org/u/Collxn_Ash)\
**Post date:** [October 21, 2025, 3:13am UTC](https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537/6 "2025-10-21T03:13:40Z")

</div>

I see. On the one hand, it’s nice to have the option to exclude schema, but on the other, it seems like building custom schema for dynamic content isn’t readily doable.

I see that `ghost_head.js` gets the benefit of access to `JSON.stringify()` ([source code](https://github.com/TryGhost/Ghost/blob/7c32527159ce9ea2028b8a07b6aea7d95dc7a831/ghost/core/core/frontend/helpers/ghost_head.js#L273C1-L277C7)).

I’m getting the sense I’ll get diminishing returns on pursuing this further. So close! For now, I’ll keep the default schema from `ghost_head`.

Thank you for all the info!

* * *

> it is possible (painfully) to assemble jd+json using existing handlebars helpers

Just out of curiosity: did you do it the painful way? I considered it, but I’m worried about building something brittle 🙂

---

<div class="post-metadata">

**Author:** ![Collxn\_Ash](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/collxn_ash/32/37564_2.png) [@Collxn\_Ash](https://forum.ghost.org/u/Collxn_Ash)\
**Post date:** [October 21, 2025, 8:17am UTC](https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537/7 "2025-10-21T08:17:57Z")

</div>

I did a writeup on what I ended up doing here:

> **[Taking Control of Structured Data in Ghost](https://www.ashryan.io/taking-control-of-structured-data-in-ghost/)**
>
> Notes on setting up structured data a Ghost theme, including how to handle static and dynamic data.

Happy to take feedback and corrections if I’m off base on anything related to Ghost.

I did run the various pages through the [Schema.org validator](https://validator.schema.org/) and I’m getting back what I expected without any reported errors or warnings.

(Thanks again to @Cathy_Sarisky for sharing your expertise here!)

---

<div class="post-metadata">

**Author:** ![Cathy\_Sarisky](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/cathy_sarisky/32/25750_2.png) [@Cathy\_Sarisky](https://forum.ghost.org/u/Cathy_Sarisky)\
**Post date:** [October 21, 2025, 11:44am UTC](https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537/8 "2025-10-21T11:44:31Z")

</div>

> [@Collxn\_Ash](#):
>
> Just out of curiosity: did you do it the painful way? I considered it, but I’m worried about building something brittle 🙂

I did do it the painful way. Actually, before ghost\_head took an exclude, so I had to replace EVERYTHING. On Ghost 4.x, no less, with a smaller set of helpers. It was gnarly.

I wonder if we could get a stringify into the set of handlebars available to the theme? What would that look like?

---

<div class="post-metadata">

**Author:** ![Collxn\_Ash](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/collxn_ash/32/37564_2.png) [@Collxn\_Ash](https://forum.ghost.org/u/Collxn_Ash)\
**Post date:** [October 22, 2025, 4:39am UTC](https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537/9 "2025-10-22T04:39:28Z")

</div>

> I wonder if we could get a stringify into the set of handlebars available to the theme? What would that look like?

I’m tempted to look. At this early point in my Ghost dev journey, I remain aware that my field of view is pretty narrow: I just have the one site I’m building a theme for and I haven’t dug into the core at all.

Naively, I wonder if it could be as simple as following this pattern:

> <https://github.com/TryGhost/Ghost/blob/main/ghost/core/core/frontend/helpers/encode.js>

Since that’s frontend, the `JSON` object should come for free, along with the `.stringify()` and `.parse()` methods.

But I haven’t really thought this through. Not sure if it makes sense.

---

<div class="post-metadata">

**Author:** ![Cathy\_Sarisky](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/cathy_sarisky/32/25750_2.png) [@Cathy\_Sarisky](https://forum.ghost.org/u/Cathy_Sarisky)\
**Post date:** [October 22, 2025, 6:13am UTC](https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537/10 "2025-10-22T06:13:24Z")

</div>

Not sure if I’m totally following you. If we had a json helper, what arguments would you give it, from your hbs file?

---

<div class="post-metadata">

**Author:** ![Collxn\_Ash](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/collxn_ash/32/37564_2.png) [@Collxn\_Ash](https://forum.ghost.org/u/Collxn_Ash)\
**Post date:** [October 23, 2025, 12:58am UTC](https://forum.ghost.org/t/toggling-modifying-default-ghost-head-structured-data/60537/11 "2025-10-23T00:58:44Z")

</div>

I’d need more time to think it through. Like I said, I’m not sure if what I mentioned above even makes sense. 😊 I’m still learning about Ghost.
