Using dynamic parameters with the #has helper


I’m migrating another site to the Ghost platform and I’ve come across an unusual use case I’m trying to work out a solution for.

Our old platform allowed for sub-pages to be included in different parts of a page. For example we have a page which has optional “top content” which can be rendered above the page itself in a different part of the layout. These are per page, but not all pages. Reading through the documentation, it looks like Ghost’s internal tag may be of help for this situation.

Tags which are prefixed by a # character, otherwise known as hashtags, are internal tags within Ghost - which is to say that they aren’t rendered publicly. This can be particularly useful when you want to drive particular functionality based on a tag, but you don’t necessarily want to output the tag for readers to see.

My idea was to create the page and assign it an internal tag, then in my template I want to query a secondary page (or post) based on a predictably patterned internal tag. Say my main page’s slug is my-page-slug. I could also tag the page with #top-content. The existence of this tag would allow the template to know whether it needs to query a sub page, which itself might be tagged with an internal tag like #top-content-my-page-slug.

Of course I could get by with only using an internal tag for the sub post, but it seems it would be faster to just not run the query when not needed. Maybe this is negligible? We only have a few posts with “top content”, so it would cut down a lot of queries.

My problem I can’t quite figure out is how to get a particular page’s internal tags, as they are not populated in a a page’s tag context. Reading through the documentation for Ghost’s function helpers, I see that the {{#has}} helper can be used to determine if a post has a specific internal tag. For example this is valid in the post context of my template:

{{#has tag="#top-content-my-page-slug"}}
    do something

However I would want it to function dynamically where my-page-slug could be populated by the page’s post {{slug}} attribute.

Is there a way to achieve this with the {{#has}} function helper? I feel like this could very well be just a handlebars question. But I figured I would post my problem in it’s entirety in case there is a much easier way to achieve what I’m going for here.

Another thing to note, I would not want my sub pages to be directly accessible, nor show up in any sitemaps. I was thinking maybe I could filter these out in my routes file somehow, but our tag taxonomy is pretty simple (tag: /{slug}/) and I’m not sure if the tag taxonomy provides filtering.

I am developing against the ghost docker image ghost:3.33-alpine.

Thank you for your help.

Best regards,
Nathan Cobb

I found a solution to the problem by using something like this in my page template:

{{#has tag="#top-content"}}
    {{#get "posts" filter="tag:hash-top-content-{{slug}}" include="tags"}}
        {{#foreach posts}}
            post content here

However I now have the issue of my posts being directly accessible via url like this: http://localhost:2368/top-content-welcome/.

You can use dynamic routing to filter out partial pages:


    permalink: /{slug}/
    filter: tag:-hash-partial
    template: index

  tag: /tag/{slug}/
  author: /author/{slug}/

Great! Thank you for the quick reply. I need to change a few things up for this to work, but think I have all I need to get this working now.