11 Jekyll SEO Checks Beyond Installing the SEO Plugin

Check Jekyll metadata, canonicals, collection output, sitemaps and deployed pages with version-aware examples and a practical 11-point release worksheet.

Editorial policy

Installing jekyll-seo-tag can generate useful metadata, but it cannot confirm that the right pages were built, that project paths work, or that your host serves the intended response. A Jekyll SEO check needs to follow a page from configuration and front matter to the generated files and the public URL.

These 11 checks cover that release workflow, including a version difference that matters when a theme and the plugin both generate canonical tags. Start with one representative post, one collection page and any paginated archive, then repeat the checks across their templates. The configuration examples are illustrative and based on official documentation and plugin source checked on October 31, 2026; they are not results from testing a particular website.

1. Match the audit to the actual production build

Read the deployment command, Gemfile.lock and build log before applying plugin advice. A custom GitHub Actions workflow can use a different bundle from a site built with the GitHub Pages dependency set. The versions in your local editor do not establish what production used.

The published GitHub Pages dependency table listed Jekyll 3.10.0 and jekyll-seo-tag 2.8.0 when checked on October 31, 2026; the table itself was marked updated August 13, 2025. The latest RubyGems releases were Jekyll 4.4.1 and SEO Tag 2.9.1. That difference is a reason to inspect the build, not an instruction to upgrade it.

Run these in the Jekyll project using its existing bundle:

POWERSHELL
bundle exec jekyll --version
bundle info jekyll-seo-tag

Record the commit, locked plugin version, configuration files and command used by the deployment job. If local output and public HTML disagree, compare those inputs first. A successful local preview is weak evidence when the publisher used another theme version, configuration override or build mode.

2. Verify the public origin and project path

Set url to the public origin and baseurl to the site's path beneath that origin. For an illustrative project published at https://example.com/docs/, the configuration is:

YAML
url: "https://example.com"
baseurl: "/docs"

A site at the domain root uses baseurl: "". Do not put /docs in both values. Jekyll's absolute_url and relative_url filters use these settings, so one mistake can affect canonical tags, image URLs and internal links together.

Build the production artifact with the same configuration inputs as deployment. For example, in PowerShell:

POWERSHELL
$env:JEKYLL_ENV = "production"
bundle exec jekyll build

If your project already uses a production override file, pass the existing files in deployment order, such as --config _config.yml,_config.production.yml. Later configuration files override earlier ones.

Inspect the resulting page under _site unless your project changes the destination. Its canonical and social URLs should use the public origin and include the project path exactly once. Do not upload a jekyll serve preview artifact: the development server can use a localhost URL. Setting JEKYLL_ENV=production controls environment-dependent behavior; it does not correct a wrong url value.

3. Keep one owner for each metadata tag

Inspect the theme's layout and head includes before adding {% seo %}. Some themes already execute it in a shared template. Adding another invocation to each post can create duplicate tags; listing the plugin in _config.yml does not show where a theme renders it.

Use the generated HTML to assign ownership:

Output What to inspect Passing result
<title> Theme markup and SEO Tag output One intentional title
Description Manual meta element and plugin output One page-specific description
Canonical Theme include and plugin output One consistent canonical URL
JSON-LD Theme, plugin and custom scripts Coherent entities without contradictory duplicates

There is an important version boundary. Both SEO Tag 2.8.0 and 2.9.1 support {% seo title=false %}. The 2.9.1 template supports canonical suppression with {% seo canonical=false %}; the 2.8.0 template does not contain that control. Do not use the newer option as a universal fix for an older Pages bundle.

Choose the owner your installed theme and plugin actually support. If custom markup owns the canonical, verify that the plugin's canonical really disappears in the built output. A template edit that merely looks plausible is insufficient. Keep the shared invocation inside the document head and ensure it executes as Liquid rather than appearing as literal text.

4. Replace unhelpful front matter fallbacks

Open a post and a non-post page that share a layout. Do they describe different tasks in search metadata, or do both inherit the site's generic description? A valid fallback can still be unhelpful to someone choosing a result.

For example, a page about a particular integration could start with:

YAML
---
layout: page
title: "Connect a Custom Domain to Your Documentation"
description: "Configure the domain, verify DNS and check the public documentation URL after the change."
---

Use the project's real layout and topic. Keep the YAML front matter at the start of the file, correctly delimited and valid; an invented field name does not become metadata unless a template or plugin reads it.

In SEO Tag 2.9.1, the description implementation uses the page description or excerpt, then falls back to the site description. It also applies a configurable word limit. That limit is plugin behavior, not a Google snippet-length rule.

Inspect the rendered title and description after theme formatting, including any appended site name. Write a concise, accurate description of this page rather than filling a character target with repeated keywords. Search engines can present different title links or snippets, so the check passes when your intended metadata is correctly rendered, not when a particular search appearance is guaranteed.

5. Check canonicals against real destination pages

For an ordinary unique page, compare the canonical with the preferred public URL that actually serves its content. Look for localhost origins, missing project paths, obsolete domains and unwanted /index.html variants. Fetch the destination too: a correctly spelled URL that leads to an error or unrelated page is not a useful canonical target.

SEO Tag supports the canonical_url front matter override. Use it deliberately for duplicate or substantially equivalent content, rather than treating it as a general field for whichever page you want to rank:

YAML
canonical_url: "https://example.com/docs/preferred-guide/"

Confirm that the intended owner from check 3 renders this value. A custom canonical: field has no effect unless your own code reads it. See Screpy's canonical tag guide for the broader duplicate-content decision.

Paginated archives need particular care. Google's pagination guidance recommends giving each page its own canonical URL. Page 2 usually contains different entries from page 1; pointing every archive page at page 1 can contradict that distinction.

Finally, compare the canonical with internal links and sitemap entries. Canonicalization is a signal, not a redirect or a guaranteed selection. Consistent signals help express your preference; they do not make a thin or unrelated destination equivalent.

6. Confirm that intended collection pages are built

A document can exist in the repository without having an individual public page. For a custom collection, inspect Jekyll's collection output settings. For example:

YAML
collections:
  guides:
    output: true
    permalink: /guides/:name/

With that illustrative configuration, _guides/domain-setup.md should generate a page at /guides/domain-setup/. The site's baseurl, if present, belongs in its public URL as well. Check the actual generated path and links; a source filename is not a reliable substitute for inspecting the permalink result.

Make a small expected-URL inventory from the pages you intend to publish. Compare it with the deployment artifact, including at least one document from every public collection. If the page is absent, resolve the build condition before debugging its metadata or asking a search engine to crawl it.

Also inspect deployment flags such as --drafts, --future and --unpublished, which alter what the build includes. A preview may deliberately show content that the production job excludes. Conversely, deploying a preview artifact can expose content you did not intend to release. Removing a source page or setting published: false only changes what Jekyll builds; confirm that the host also stops serving any stale previously deployed file.

7. Align sitemap membership and indexing policy

Treat sitemap inclusion, index exclusion and access protection as separate decisions. With jekyll-sitemap, sitemap: false excludes a page from the generated XML. It does not add a robots meta tag or prevent visitors from opening the URL.

There is also a canonical mismatch worth checking. The jekyll-sitemap 1.4.0 template builds locations from page or document URLs; it does not use the SEO Tag canonical_url override. If you canonicalize a duplicate elsewhere, inspect the XML rather than assuming that the override also changed sitemap membership. Prefer the canonical pages in your sitemap, following your actual content policy.

For a public page that should remain accessible but be excluded from search, this is an illustrative custom implementation:

YAML
---
noindex: true
sitemap: false
---

That noindex variable needs a reader in your shared head template:

LIQUID
{% if page.noindex == true %}
  <meta name="robots" content="noindex">
{% endif %}

The custom flag alone does nothing. Integrate this condition with any existing robots-tag owner, then confirm exactly one intended policy in the generated and public HTML. Keep the URL crawlable so a search engine can read the directive; blocking crawling can prevent Google from seeing noindex.

Open the public sitemap and compare a canonical page, an excluded page and a collection page with the expected results. Check that every included location uses the right domain and project path. Do not update modification dates merely to make old content look fresh. Screpy's sitemap guide and noindex guide explain the separate search controls. Neither a sitemap exclusion nor noindex is suitable protection for private information.

A project site can have correct metadata and broken navigation. An internal link hardcoded as /guides/domain-setup/ goes to the domain root; for a site under /docs, it may miss the intended page entirely.

For an internal path, let Jekyll apply baseurl:

LIQUID
<a href="{{ '/guides/domain-setup/' | relative_url }}">Custom domain setup</a>

With baseurl: "/docs", the rendered destination should be /docs/guides/domain-setup/. Use a route that actually exists in your project, and do not add /docs to the input path again. External links have a different purpose and should retain their intended absolute destinations.

Follow the built navigation, breadcrumbs, collection indexes and previous/next archive links as a visitor would. Important public pages should have useful links from relevant pages, not depend entirely on appearing in an XML sitemap. Check that templates produce ordinary anchors with real href values; Google's crawlable-link guidance explains why script-only interactions are a poor substitute.

Review link text as well as status codes. “Custom domain setup” tells a reader what comes next; a repeated “click here” does not. If an old path redirects, update the internal link to the intended destination when practical, then confirm that the change survives the production build.

9. Open the images used by the page

Inspect both the social-preview image URL in the head and the images a visitor sees in the body. They are separate outputs. A valid image setting does not prove the asset was copied into the deployment, is publicly retrievable or remains readable at its displayed size.

SEO Tag accepts an image object, illustrated here with a project-owned diagram:

YAML
image:
  path: /assets/images/domain-setup.png
  alt: "Diagram showing a custom domain pointing to the documentation site"

In the plugin's advanced usage, image metadata configures social output. Its alt value does not automatically populate body image attributes. A corresponding body image needs its own markup, for example:

LIQUID
<img src="{{ '/assets/images/domain-setup.png' | relative_url }}"
     alt="Diagram showing a custom domain pointing to the documentation site">

Replace the example asset and description with the real image. Check the resolved public URL, response type and visible result. Look for deployment paths that work locally but fail under a project subpath, illegible diagrams and unnecessarily large image files. Choose appropriate dimensions and delivery for the actual layout rather than claiming a universal performance gain.

Follow Google's image guidance: make useful images discoverable and describe their content accurately. Keyword lists in alt text do not explain a diagram to a reader.

10. Match structured data to real authors and dates

Inspect the JSON-LD already produced by the plugin before adding another Article script. In SEO Tag 2.9.1, page data influences the generated type, author, headline, canonical URL and dates. A dated page can receive BlogPosting, while other page types have different defaults. Do not assume every documentation page should be marked as an article.

For an actual post, use truthful fields in the format your installed version supports. This illustrative front matter must be replaced with the real author and dates:

YAML
author:
  name: "Actual author name"
  url: "https://example.com/about/"
date: "2026-10-20T09:00:00+03:00"
last_modified_at: "2026-10-23T14:30:00+03:00"

Check the plugin's structured-data implementation against the rendered result. The modified date can also be overridden through seo.date_modified, so inspect inherited defaults and overrides if the output differs from last_modified_at.

Compare the JSON-LD with the visible byline and dates. The profile URL should identify the actual author; dates should describe publication and meaningful changes. Do not renew them on every build to imply a new editorial update, or add credentials and review claims that did not occur.

Use Google's Article structured-data documentation when validating article pages. Valid markup helps describe a page; it does not guarantee a rich result, indexing or a ranking improvement.

11. Verify the deployed response and preserve evidence

Repeat the checks on the ordinary public URL after deployment. Read the complete HTML and headers, not just an HTTP 200 result. Confirm the intended heading and body, canonical, robots policy, links, images and structured data. A branded error page can also return 200; a correct local file can still be replaced by an older deployment.

For example, this Windows command saves a public response and its redirect-chain headers for inspection:

POWERSHELL
curl.exe -sS -L -D page.headers.txt -o page.html https://example.com/docs/guides/domain-setup/

Replace the URL with your actual page. Inspect the initial and final status, Location headers, final destination and any X-Robots-Tag as well as the HTML meta directive. For a moved page, compare the observed behavior with the intended redirect policy.

The jekyll-redirect-from plugin generates HTML redirect pages using a refresh directive. Installing it does not establish that your host returns an HTTP 301 or 308. Google's redirect guidance distinguishes these mechanisms; verify what the public server actually sends.

Copy this CSV into a release worksheet and replace each blank with an observed result. Mark a check passed only when its evidence matches the intended page policy.

CSV
check,expected,evidence,result
1,Production versions and command identified,Commit plus lockfile plus deploy log,
2,Correct public origin and baseurl,Generated canonical and image URLs,
3,Intentional metadata owners,Counts and values from public head,
4,Useful page-specific metadata,Rendered title and description,
5,Appropriate reachable canonical,Canonical URL plus destination response,
6,Intended pages built and served,Expected URL inventory plus artifact paths,
7,Sitemap and index policy aligned,XML membership plus readable robots directive,
8,Crawlable working internal links,Rendered hrefs plus destination responses,
9,Usable public image assets,Image responses plus visual and alt review,
10,Truthful coherent structured data,JSON-LD compared with visible author and dates,
11,Correct complete deployed response,Public URL plus headers plus saved HTML,

Use URL Inspection in Search Console to investigate Google's view of an important page after these checks. A successful indexing request is an accepted request, not confirmation that the page is indexed. Save the public evidence and deployment identity so a later change can be compared with a known release instead of another local preview.

Related posts

Keep reading practical SEO guides from the Screpy blog.

View all posts