Get Tags for a specific page (including posts)

Hi,

I am trying to fetch all the tags on a page (also for posts) to include it into the meta tag. How can I do this? (I am doing this within the <head> html tag)

Ghost v5.69.0.

So, the assumption for the following to work is that you’re within the #post context – otherwise you won’t be able to get the tags for that specific post. In order to achieve that, you will need to start and end your post.hbs and page.hbs with the context like this:

{{#post}}
<html lang="{{@site.locale}}">
    <head>
        ...
    </head>
    <body>
        ...
    </body>
</html>
{{/post}}

Now, you can access the tags attached to a post or page anywhere – including the <head> tag.

Here is the snippet that will generate a comma-separated list of tags in a meta tag labelled “tags”:

<meta name="tags" content="{{#foreach tags}}{{#if @last}}{{name}}{{else}}{{name}}, {{/if}}{{/foreach}}" />

Just a bit of handlebar-mix-match :smiley:

So, what does it do?

  1. First, we’re opening a foreach-loop for all tags attached to the page or post.
  2. Then, we do a bit of formatting. Since we want a comma separated list, the very last tag in our list should not get a ", " appended. So, we start of by asking whether the current tag in our foreach loop is the last of the list. For this, we’re using the @last helper and just return the {{name}}. If, however, the current tag is NOT the last one in the list, we return {{name}}, a comma, and a space – so that our list continues, and continues.
  3. And well, then we’re closing all these helper tags.

Another way of writing this (the structure of the code might be clearer here, but the end result will also have line breaks – so, I personally prefer the first one):

<meta name="tags" content="
    {{#foreach tags}}
        {{#if @last}}
            {{name}}
        {{else}}
            {{name}}, 
        {{/if}}
    {{/foreach}}
" />

The result will look like this:

<meta name="tags" content="Tag 1, Tag 2, Tag 3, Tag 4" />

Hope this does what you need :slight_smile:

2 Likes

Hi Jannis,

Thanks for that detailed answer! I had also come up with an alternate solution in the meantime :

<meta name="tags" content="{{#is "page"}}{{#page}}{{tags autolink="false" separator=", "}}{{/page}}
      {{else}}{{#post}}{{tags autolink="false" separator=", "}}{{/post}}{{/is}}" />

I think the separator is a good attribute to use for including the commas. How different are the solutions in terms of performance or best practices?

2 Likes

Ah nice! I didn’t know the separator option.

I guess the most efficient would be a combination then, given that the page and post context are pretty much the same and you don’t need to differentiate between them for your use case.

Here’s one more suggestion. Forget what I said before, because this is so much more elegant :joy:

<meta name="tags" content="{{#post}}{{tags autolink="false"}}{{/post}}" />

:person_shrugging:

Can’t believe it’s that easy. I went down the rabbit hole and chased down the implementation of the {{tags}} helper in the Ghost core. Turns out, the separator defaults to ", " – and that makes this whole thing super simple :smiley:

1 Like

Clean! I didn’t know that tags use comma as the default separator.

Even though there is not much difference between post and page context, if I don’t add one of these context tags (for eg: #page) then those tags are not included.

So here’s my final code snippet:

<meta name="tags" content="{{#is "page"}}{{#page}}{{tags autolink="false"}}{{/page}}{{else}}{{#post}}{{tags autolink="false"}}{{/post}}{{/is}}" />

:smiley:

1 Like