Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(blog): add seo and gatsby blog post #10780

Closed
wants to merge 4 commits into from

Conversation

DSchau
Copy link
Contributor

@DSchau DSchau commented Jan 2, 2019

Description

This PR adds a blog post re: SEO + Gatsby, with a particular focus on the new SEO component we've made available in the default and blog starters.

I'm open to tweaking this however (or making a guide?), but didn't want to overwrite anything existing content and it does seem to make sense as a blog post.

As always, feedback more than welcome, and huge shout-out to @fk and @LekoArts for lots of prior art, here!

Preview

localhost_8000_blog_2019-01-04-seo-and-gatsby_

@DSchau DSchau requested a review from a team January 2, 2019 20:27
@LekoArts
Copy link
Contributor

LekoArts commented Jan 2, 2019

Nice, I like that you included the image part. I gave a lengthy explanation to that on Discord couple of days ago, so now I can link to a blogpost then.

Did you link to the "Add an SEO component" doc? What about linking to JSONLD and/or an example with that?

@DSchau
Copy link
Contributor Author

DSchau commented Jan 2, 2019

@LekoArts definitely will want to add the link(s) in!

@khalwat
Copy link

khalwat commented Jan 3, 2019

Hey @DSchau I was asked my Kyle to have a read through the article, here are some bullet-pointed notes I took for it:

-- meta keywords is entirely ignored by Google both for ranking and indexing, and has been for many years. Indeed, it is a signal to Google if the meta keywords is stuffed with nonsense to consider it SEO spam. Some other search engines do look at it, tho.

-- The <title> tag is far more important to SEO, so perhaps mention that in place of meta keywords for the bare minimum

-- meta images should be sized appropriately, and in the appropriate aspect ratio for the social service in question, and in the right image format. Both Twitter and Facebook have size restrictions for images beyond which they will just completely ignore the image

-- Article doesn't seem to discuss the recommended title length and description lengths, which is relatively important... and to truncate them appropriately

-- The article probably should discuss <link rel="canonical"> given how important that can be depending on the structure of the site, to help in avoiding duplicate content issues. At the very least, it'd show how to use Helmet to add a link instead of a meta tag

-- Probably beyond the scope, but the article doesn't touch on JSON-LD structured data, which is increasingly important to the Google Knowledge Graph as well as the Google SERP in terms of presentation

Other things that may or may not be beyond the scope of the article:

-- Sitemaps and how GoogleBot uses them to help spend its crawl budget where you want it to

-- hreflang tags for multi-lingual sites to point to the same content in other languages

-- robots tag to ensure or prevent bots from indexing the site (we don't want our staging sites indexed, for instance, otherwise duplicate content issues

-- referrer tag

-- 301 redirects when an old site is redone into a shiny new site, with presumably rewritten URLs

-- Not SEO related, but might be kinda cool of Gatsby includes a humans.txt as a default part of the template; if so, add in an author meta tag

Otherwise, it looks okay i guess? I'm slightly unclear on the premise of the article; if it's just a lightweight example of "How to SEO with Gastby" then it probably is fine. Perhaps it should talk a bit more about each page should have a unique title & description that reflects the content on the page... and to avoid duplicate descriptions/titles

I'd consider mentioning the importance of speed as it pertains to SEO as well, especially since Gatsby addresses performance so well. GoogleBot has a "performance budget" in time that it uses to crawl your site; the faster the site, the more it can crawl. You will also get a boost in the SERP if your site is:

  • mobile friendly
  • https
  • fast

...so sell Gatsby on these benefits that it provides!

If I can offer any other assistance/input, please feel free to ask!

Some articles I wrote that may be useful:

https://nystudio107.com/blog/modern-seo-snake-oil-vs-substance

https://nystudio107.com/blog/json-ld-structured-data-and-erotica

SEO presentation I did back in 2017:

https://vimeo.com/246846978

@DSchau
Copy link
Contributor Author

DSchau commented Jan 3, 2019

@khalwat you’re the best—thank you so much! I’ll address this feedback tomorrow and get it ship-shape.

@khalwat
Copy link

khalwat commented Jan 3, 2019

Don't get me wrong, it's quite good -- and the hard part of any article is deciding:

1 - What it should be
2- What to leave out

...but if you have any specific questions or things you want to run by me, feel free!

@LekoArts
Copy link
Contributor

LekoArts commented Jan 3, 2019

@khalwat Thanks for your insights, will read through the articles tomorrow. Regarding the JSONLD: https://github.com/LekoArts/gatsby-starter-prismic/blob/master/src/components/SEO/SEO.jsx
Would that be a good (and also correct) example? I did that to the best of my knowledge 😅 Normal JSONLD gets applied everywhere, the „article“ one only for the blogposts.

@khalwat
Copy link

khalwat commented Jan 3, 2019

@LekoArts So it looks fine... you probably always want to have:

-- Something that is a main entity of page (not only if it is an article -- you can default to just WebPage
-- A BreadcrumbList because Google will display this on the SERP

Take a look at how the Google Structured Data Testing Tool consumes the JSON-LD for my An Annotated webpack 4 Config for Frontend Web Development article page (disclose the Article and see everything that's filled in).

This was generated by the SEOmatic plugin that I wrote for Craft CMS. The generated JSON-LD looks like this:

<script type="application/ld+json">
{
    "@context": "http://schema.org",
    "@type": "Article",
    "author": {
        "@id": "https://nystudio107.com/#identity"
    },
    "copyrightHolder": {
        "@id": "https://nystudio107.com/#identity"
    },
    "copyrightYear": "2018-10-23T09:40:00-04:00",
    "creator": {
        "@id": "https://nystudio107.com/#creator"
    },
    "dateModified": "2018-11-21T17:54:10-05:00",
    "datePublished": "2018-10-23T09:40:00-04:00",
    "description": "As web development becomes more complex, we need tooling to help us build modern websites. Here's a complete real-world production example of a sophisticated webpack 4 config",
    "headline": "An Annotated webpack 4 Config for Frontend Web Development",
    "image": {
        "@type": "ImageObject",
        "url": "http://nystudio107.test/img/blog/_1200x630_crop_center-center_82_none/webpack-4-annotated-config.png"
    },
    "inLanguage": "en",
    "mainEntityOfPage": "http://nystudio107.test/blog/an-annotated-webpack-4-config-for-frontend-web-development",
    "name": "An Annotated webpack 4 Config for Frontend Web Development",
    "publisher": {
        "@id": "https://nystudio107.com/#creator"
    },
    "url": "http://nystudio107.test/blog/an-annotated-webpack-4-config-for-frontend-web-development"
}
</script>
<script type="application/ld+json">
{
    "@context": "http://schema.org",
    "@id": "https://nystudio107.com/#identity",
    "@type": "Organization",
    "address": {
        "@type": "PostalAddress",
        "addressCountry": "US",
        "addressLocality": "Webster",
        "addressRegion": "NY",
        "postalCode": "14580"
    },
    "alternateName": "nys",
    "description": "We do technology-based consulting, branding, design, and development. Making the web better one site at a time, with a focus on performance, usability & SEO",
    "email": "info@nystudio107.com",
    "founder": "Andrew Welch, Polly Welch",
    "foundingDate": "2013-05-02",
    "foundingLocation": "Webster, NY",
    "image": {
        "@type": "ImageObject",
        "height": "1042",
        "url": "https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/site/nys_logo_seo.png",
        "width": "1042"
    },
    "logo": {
        "@type": "ImageObject",
        "height": "60",
        "url": "http://nystudio107.test/img/site/_600x60_fit_center-center_82_none/nys_logo_seo.png",
        "width": "60"
    },
    "name": "nystudio107",
    "sameAs": [
        "https://twitter.com/nystudio107",
        "https://www.facebook.com/newyorkstudio107",
        "https://plus.google.com/+nystudio107com",
        "https://www.youtube.com/channel/UCOZTZHQdC-unTERO7LRS6FA",
        "https://github.com/nystudio107"
    ],
    "url": "https://nystudio107.com/"
}
</script>
<script type="application/ld+json">
{
    "@context": "http://schema.org",
    "@id": "https://nystudio107.com/#creator",
    "@type": "Organization",
    "address": {
        "@type": "PostalAddress",
        "addressCountry": "US",
        "addressLocality": "Webster",
        "addressRegion": "NY",
        "postalCode": "14580"
    },
    "alternateName": "nys",
    "description": "We do technology-based consulting, branding, design, and development. Making the web better one site at a time, with a focus on performance, usability & SEO",
    "email": "info@nystudio107.com",
    "founder": "Andrew Welch, Polly Welch",
    "foundingDate": "2013-05-02",
    "foundingLocation": "Webster, NY",
    "image": {
        "@type": "ImageObject",
        "height": "1042",
        "url": "https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/site/nys_logo_seo.png",
        "width": "1042"
    },
    "logo": {
        "@type": "ImageObject",
        "height": "60",
        "url": "http://nystudio107.test/img/site/_600x60_fit_center-center_82_none/nys_logo_seo.png",
        "width": "60"
    },
    "name": "nystudio107",
    "url": "https://nystudio107.com/"
}
</script>
<script type="application/ld+json">
{
    "@context": "http://schema.org",
    "@type": "BreadcrumbList",
    "description": "Breadcrumbs list",
    "itemListElement": [
        {
            "@type": "ListItem",
            "item": {
                "@id": "http://nystudio107.test/",
                "name": "Homepage"
            },
            "position": 1
        },
        {
            "@type": "ListItem",
            "item": {
                "@id": "http://nystudio107.test/blog",
                "name": "Blog Index"
            },
            "position": 2
        },
        {
            "@type": "ListItem",
            "item": {
                "@id": "http://nystudio107.test/blog/an-annotated-webpack-4-config-for-frontend-web-development",
                "name": "An Annotated webpack 4 Config for Frontend Web Development"
            },
            "position": 3
        }
    ],
    "name": "Breadcrumbs"
}
</script>

Note that it includes an Organization for both the Creator and the Identity, and look how they are referenced from the Article schema, by ID rather than duplicating the information.

Also note that even though it is a "Blog" we're using the Article schema rather than BlogPosting -- this is because that is a specific type that Google looks for, and will consider for the SERP pages: Google Article

There is what is defined on schema.org, and then there are the specific sub-types that Google looks for and consumes.

@LekoArts
Copy link
Contributor

LekoArts commented Jan 3, 2019

Thanks for the tips!

-- Something that is a main entity of page (not only if it is an article -- you can default to just WebPage

What do you mean with that?

@khalwat
Copy link

khalwat commented Jan 3, 2019

From the code I looked it, it appeared to me that it wasn't adding a JSON-LD object that was the mainEntityOfPage unless it was an article. So I was saying you might want to include a generic WebPage JSON-LD object that is the mainEntityOfPage by default for every page, unless it's an article. In which case you include that.

Yes, it's true, that by default Google assumes everything is a WebPage but this gives you the opportunity to add additional properties to it.

EDIT -- okay I see, I misread the code. It looks like you include WebSite by default. I'd suggest changing that to WebPage and adding mainEntityOfPage attributes, and possibly other useful attributes like author, creator, publisher, etc.

Copy link
Contributor

@shannonbux shannonbux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love the length, organization, and tone of this article! I agree it could be made into a guide also, with just slight editing.

Just made some suggestions. One overall suggestion is to shift from "let's" and "we" to "you" oriented language to focus it on the reader more. This is what we decided to do in the docs, though no decision has been made for the blog. It would just make it easier to make this into a guide and also potentially focuses all the reasons and instructions squarely on the reader

date: 2019-01-04
author: Dustin Schau
cover: images/seo.jpg
excerpt: "SEO and Gatsby: A Perfect Pairing. Learn how Gatsby implements SEO utilizing React Helmet and smart defaults and how you can use these tools to implement your own!"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been relentlessly trained to prefer "using" to "utilizing" simply because it's one syllable shorter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could also be shorter "Learn how to use Gatsby to implement SEO with React Helmet and smart defaults!

docs/blog/2019-01-04-seo-and-gatsby/index.md Outdated Show resolved Hide resolved
docs/blog/2019-01-04-seo-and-gatsby/index.md Outdated Show resolved Hide resolved
/>
```

These are the _bare minimum_ requirements that should be implemented for simple and basic SEO. However--we can go further, and we can go further with the powerful combo of content rendered at _build time_ powered by Gatsby and GraphQL. Let's dive in.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can go further is repeated twice.


### `StaticQuery`

Gatsby distinguishes between page-level queries and component queries. The former can use page GraphQL queries while the latter can use a new in Gatsby v2 feature called [`StaticQuery`][gatsby-static-query]. A StaticQuery will be parsed, evaluated, and injected at _build time_ into the component that is requesting the data. This is a perfect scenario in which we can create an SEO component with sane defaults that can be easily extended.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is obvious to readers; since it isn't obvious to me, I'll just ask: why is this a perfect scenario for an SEO component?


Gatsby distinguishes between page-level queries and component queries. The former can use page GraphQL queries while the latter can use a new in Gatsby v2 feature called [`StaticQuery`][gatsby-static-query]. A StaticQuery will be parsed, evaluated, and injected at _build time_ into the component that is requesting the data. This is a perfect scenario in which we can create an SEO component with sane defaults that can be easily extended.

### Creating the component
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this header and first sentence could be more specific for easier scanning


> Note: `react-helmet` is enabled, by default, in gatsby-starter-default and gatsby-starter-blog
>
> If you're not using those: [follow this guide for installation instructions][gatsby-plugin-react-helmet]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"those starters," (could be obvious, though also could easily be confused as referring to react-helmet plus one of the starters, which is close to what you mean, just not exactly the same)

export default SEO
```

whew, getting closer! This will now render the `meta` `description` tag, and will do so using content injected at build-time with the `StaticQuery` component. Additionally, it will add the `lang="en"` attribute to our root-level `html` tag to silence that pesky Lighthouse warning 😉
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whew


whew, getting closer! This will now render the `meta` `description` tag, and will do so using content injected at build-time with the `StaticQuery` component. Additionally, it will add the `lang="en"` attribute to our root-level `html` tag to silence that pesky Lighthouse warning 😉

If you remember earlier, I claimed this was the bare bones, rudimentary approach to SEO, and that still holds true. Let's enhance this functionality this and get some useful functionality for sharing a page via social networks like Facebook, Twitter, and Slack.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete second "this"

@wardpeet
Copy link
Contributor

wardpeet commented Feb 8, 2019

ping @gatsbyjs/ecosystem

@wardpeet wardpeet added status: awaiting author response Additional information has been requested from the author and removed status: awaiting reviewer response A pull request that is currently awaiting a reviewer's response labels Feb 8, 2019
@DSchau DSchau added status: WIP and removed status: awaiting author response Additional information has been requested from the author labels Feb 8, 2019
@DSchau
Copy link
Contributor Author

DSchau commented Feb 8, 2019

@wardpeet this isn's technically ready. I'd like to finish #10921 before merging this in!

@t2ca
Copy link
Contributor

t2ca commented Feb 20, 2019

I would suggest removing the keywords meta, like mentioned above, google does not use this at all.
What is more important to google is the title and description.

@DSchau
Copy link
Contributor Author

DSchau commented Apr 24, 2019

This is probably still publishable--however it would be nice to have #10921 merged in, as well (which is currently blocked).

I think SEO is a thing people kinda/sorta understand--so providing some general, helpful info would be very valuable!

@marcysutton
Copy link
Contributor

marcysutton commented May 17, 2019

This is fantastic learning material! However, I do think it would make a better Docs Reference Guide or Advanced Tutorial, since blog post material is usually more about storytelling than how-to's (at least in where you'd look for them). After a while it also would get buried amongst blog posts, so I think that will be important in the long run to help people find your awesome contribution. The SEO page is pretty light on details, too, perhaps we could add it to "Tutorials > Advanced Tutorials" and link from the Docs Guide (dependent on #14071)?

To also echo what @shannonbux said, too: referencing "you" will focus the narrative on the reader.

@marcysutton
Copy link
Contributor

Closed in favor of #14125!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants