Setting page.title from another variable

When using collections, it is often unintuitive to use a ‘title’ field for data that one would not describe as such. Thus, I would like to be able to set a different variable that Jekyll should use for page.title in the site configuration. Is there a way to do this?

Even better would be a method of combining two variables into page.title: this would make it possible, for example, to include the name of a post’s author in its <title>.

One way to go about this: Use a layout where the <h1>{{page.title}}</h1> part is left out, and compose a h1-line “locally” in whichever way you wish.

You are using the term “data”. I assume you are referring to “YAML front matter.”

Let’s say you have a post that looks like this:

---
layout: post
title:  "Welcome to Jekyll!"
date:   2022-04-21 21:24:38 +0000
categories: jekyll update
author: "Bill Raymond"
---

My first post!

Right now, the title will probably look something like this:


Welcome to Jekyll!

My first post


However, you want every post to display the title and the author like this:


Welcome to Jekyll! - Bill Raymond

My first post


I recommend you modify the post layout you are using. For example, here is the code from the minima theme’s /_layouts/post.html:

---
layout: default
---
<article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">

  <header class="post-header">
    <h1 class="post-title p-name" itemprop="name headline">{{ page.title | escape }}</h1>
    <p class="post-meta">
      <time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
        {%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
        {{ page.date | date: date_format }}
      </time>
      {%- if page.author -%}
        • <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span class="p-author h-card" itemprop="name">{{ page.author }}</span></span>
      {%- endif -%}</p>
  </header>

  <div class="post-content e-content" itemprop="articleBody">
    {{ content }}
  </div>

  {%- if site.disqus.shortname -%}
    {%- include disqus_comments.html -%}
  {%- endif -%}

  <a class="u-url" href="{{ page.url | relative_url }}" hidden></a>
</article>

Note this line that displays the page title:

<h1 class="post-title p-name" itemprop="name headline">{{ page.title | escape }}</h1>

You can create a variable with the new title, adding the author. Add a new line above to create the variable newTitle and then modify the h1 tag so it displays newTitle like this:

    {%- assign newTitle = page.title | append: ' - ' | append: page.author | escape -%}
    <h1 class="post-title p-name" itemprop="name headline">{{ newTitle | escape }}</h1>

Now the output will include the title and author, like this:


Welcome to Jekyll! - Bill Raymond

My first post


Thank you for taking the time to respond in such detail! I didn’t know about append and that will be useful.

It’s easy to change the title as displayed in the page layout, but I also want to change the value that Jekyll SEO uses for page.title. Hence why I was hoping to be able to change it in the configuration of defaults.

(I used the term ‘data’ because I am making pages from YAML files in collections, but of course that is merely front matter. In this situation I also want to use a name for an author page but don’t want to have to store the name as title.)

Okay, I think I better understand your requirement. What Jekyll SEO [mostly] does is add HTML <meta> tags to your pages. According to the Advanced usage documentation, you can overwrite those defaults.

I do not use Jekyll SEO since I create my own tags, but according to the documentation, the following approach should work.

Using the Jekyll Minima theme as an example, nearly every page uses the default layout. That layout in turn includes the head.html file. It is in that file where you will find the Jekyll SEO tag in use. Looks for the line that reads {%- seo -%}. Note also that the <title> tag always lives in the <head> tag of your HTML document.

According to the Jekyll SEO documentation link I shared, this modification to the /_includes/head.html file would give you what you need:

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  {%- seo title=false -%}
  {%- seo -%}
  {%- assign newTitle = page.title | append: ' - ' | append: page.author | escape -%}
  <title>{{-newTitle-}}</title>
  <link rel="stylesheet" href="{{ "/assets/main.css" | relative_url }}">
  {%- feed_meta -%}
  {%- if jekyll.environment == 'production' and site.google_analytics -%}
    {%- include google-analytics.html -%}
  {%- endif -%}
</head>

Notice that I include {%- seo title=false -%} just before {%- seo -%}. According to the docs, that should prevent the <title> tag from displaying.

Right after the {%- seo -%} line, I create a variable called newTitle, which happens to be the title of the page concatenated with the author.

Finally, right after that line, I use the variable by adding <title>{{-newTitle-}}</title>

Since I was not able to test this code beforehand, go ahead and give it a try. Assuming no errors, open the web page in the browser, right-click and choose the option to view the source code. You should only see one <title> tag within the <head> tag and it should be the title you created with the Liquid variable.

You said you use collections, so if you want a different <title> tag per collection, then you will have to figure out how you want to handle that (more layouts, more include files, if logic, etc.)

Hand-coding your SEO tags is not that complicated and can be done without a plugin. If you want to replace it with your own Liquid code, go to the readme.md file at the Jekyll SEO GitHub page to learn how it works: