Closed DirtyF closed 5 years ago
Would it be possible to break this down into smaller plugins as well? For example, what if I would like to have JSON-LD, but not Twitter Cards?
I would imagine that the SEO plugin loads those smaller plugins and expose them under a single API. Maybe a lerna repo?
Are there any thoughts on how this should work?
My approach is currently a collection of shortocdes, so you'd end up with something like this that you could mix and match as desired:
{% metaTitle pageTitle %}
{% metaDescription pageDescription %}
{% canonical absolutePageUrl %}
{% twitterSummaryCard author.twitter.name, pageTitle, pageDescription, pageImage %}
{% opengraphBasic pageTitle, ogpType or 'website', site.url, pageImage or site.logo %}
I'm not sure how well that would work in a generic form for json-ld since it's basically kvps you can use in any number of ways.
My current implementation of the above is here: https://github.com/AndrewAsquith/andrewasquith-ca/tree/master/_11ty/shortcodes
Yeah, my idea would have been to write seo as a collection of shortcodes (so everybody is free to mix and match as they please).
Then one additional shortcode {% seo %}
which uses the single shortcodes under the hood.
The information should be placed in a JSON under _data/
, so it is available from everywhere.
So I've been playing with my implementation and ended up settling on this for the moment:
https://github.com/AndrewAsquith/andrewasquith-ca/blob/master/src/site/_includes/components/meta.njk
Does it make sense to pull my shortcodes out into a plugin? And how far to take that? I left some generic shortcodes in rather than implementing every possibility. And while I have a quick check to try and ensure the JSON is well formed, it's probably still possible to end up with invalid markup. I'd rather not be responsible for a project that sullies 11ty's name. ;)
Any other ideas or better implementations?
@chrisdmacrae I couldn't find anything in your public repos, but that doesn't mean it's not hiding until it's ready.
@zachleat do you have any suggestions/feedback ?
I set SEO manually.
My project is still localhost, I haven't released it yet.
Example like this:
{# meta SEO #}
{% include "meta-seo.njk" %}
The meta-seo.njk
can be found here.
I'm currently playing around with microformats2 h-event and its JSON-LD pendant.
Currently not quite happy with the structure of my event.njk
partial:
<div class="h-event vevent">
<h3>
<a class="p-name summary u-url url" href="{{ event.url }}">{{ event.name }}</a>
</h3>
<p>
From
<span class="dt-start dtstart" datetime="{{ event.startDate }}">
<abbr class="value" title="{{ event.startDate }}">
{{ event.startDay }}.{{ event.startMonth }}.{{ event.startYear }}
</abbr>
</span>
to
<span class="dt-end dtend" datetime="{{ event.endDate }}">
<abbr class="value" title="{{ event.endDate }}">
{{ event.endDay }}.{{ event.endMonth }}.{{ event.endYear }}
</abbr>
</span>
{% if event.location %}
at <span class="p-location location">
{% set location = event.location %}
{% include "_partials/location.njk" %}
</span>
{% endif %}
</p>
</div>
<script type="application/ld+json">
{
"@context": "http://schema.org/",
"@type": "Event",
"name": "{{ event.name }}",
"url": "{{ event.url }}",
"startDate": "{{ event.startDate }}",
"endDate": "{{ event.endDate }}"{% if event.location %},
"location": {
"@type": "Place",
"name": "{{ event.location.name }}",
"address": {
"@type": "PostalAddress",
"streetAddress": "{{ event.location.address }}",
"postalCode": "{{ event.location.postalCode }}",
"addressLocality": "{{ event.location.locality }}",
"addressCountry": "{{ event.location.country }}"
}
}
{% endif %}
}
</script>
I keep my events in a Data File for now. Maybe switching to a collection later on.
Right now I solve this without a plugin using the {% block %}
inheritance features.
In your main base template you should have a basic SEO block. Here is a reasonable starting point
<title>
{%- if title -%}
{{title}} - {{site.title}}
{%- elseif renderData.title -%}
{{renderData.title}} - {{site.title}}
{%-else-%}
{{site.title}} {{site.strapline}}
{%- endif -%}
</title>
<meta name="description" content="{% block description %}{{site.description}}{% endblock %}">
<meta name="robots" content="index,follow">
<meta name="generator" content="Eleventy">
<meta name="subject" content="Your site subject">
{%- block seo -%}
<!--Twitter Card-->
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@{{site.twitter}}">
<meta name="twitter:creator" content="@{{site.twitter}}">
<meta name="twitter:url" content="{{site.baseURL}}{{page.url}}">
<meta name="twitter:title" content="{{title}}">
<meta name="twitter:description" content="{{ site.description }}">
<!--Schema-->
<link rel="author" href="{{site.baseURL}}">
<link rel="publisher" href="{{site.baseURL}}">
<meta itemprop="name" content="{{title}}">
<meta itemprop="description" content="{{ site.description }}">
<!-- Facebook OpenGraph -->
<meta property="fb:app_id" content="{{site.FB_APP_ID}}">
<meta property="og:url" content="{{site.baseURL}}{{page.url}}">
<meta property="og:type" content="website">
<meta property="og:title" content="{{title}}">
<meta property="og:description" content="{{ site.description }}">
<meta property="og:site_name" content="{{site.title}}">
<meta property="og:locale" content="en_GB">
<meta property="article:author" content="{{site.baseURL}}">
{%- endblock -%}
Next, within each inherited template you have the option of including a more page specific {% block seo %}
which will override the values in the base template.
Here is an example
{%- block seo -%}
<!--Twitter Card-->
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@{{site.twitter}}">
<meta name="twitter:creator" content="@{{site.twitter}}">
<meta name="twitter:url" content="{{site.baseURL}}{{page.url}}">
<meta name="twitter:title" content="{{title}}">
<meta name="twitter:description" content="{{content | striptags | truncate(196) }}">
<meta name="twitter:image" content="{{featuredImageThumbnail}}">
<!--Schema-->
<link rel="author" href="{{site.baseURL}}">
<link rel="publisher" href="{{site.baseURL}}">
<meta itemprop="name" content="{{title}}">
<meta itemprop="description" content="{{content | striptags | truncate(196) }}">
<meta itemprop="image" content="{{featuredImageThumbnail}}">
<!-- Facebook OpenGraph -->
<meta property="fb:app_id" content="{{site.FB_APP_ID}}">
<meta property="og:url" content="{{site.baseURL}}{{page.url}}">
<meta property="og:type" content="website">
<meta property="og:title" content="{{title}}">
<meta property="og:image" content="{{featuredImageThumbnail}}">
<meta property="og:description" content="{{content | striptags | truncate(196) }}">
<meta property="og:site_name" content="{{site.title}}">
<meta property="og:locale" content="en_GB">
<meta property="article:author" content="{{site.baseURL}}">
{%- endblock -%}
Obviously wherever you see a {{site.XXXX}}
variable it indicates site level data which is typically defined within a site.json
file in your _data
folder.
Wait, I can use blocks like in Jinja2/Django? :O
(You should have an option to declare noindex
, e.g. for search result page)
This repository is now using lodash style issue management for enhancements. This means enhancement issues will now be closed instead of leaving them open.
View the enhancement backlog here. Don’t forget to upvote the top comment with 👍!
11ty-plugin-seo
helps add necessary markup for SEO./cc @chrisdmacrae