Toggling/modifying default `ghost_head` Structured Data

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

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:

2 Likes

Woah, this is incredible. Thank you @Cathy_Sarisky!

1 Like

@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?

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

1 Like

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

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 :slight_smile:

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

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 and I’m getting back what I expected without any reported errors or warnings.

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

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?

1 Like

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:

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.

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

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