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

Twitter and OpenGraph cards not rendering for root URL and most pages #3590

Closed
tannerdolby opened this issue Apr 22, 2021 · 20 comments
Closed

Comments

@tannerdolby
Copy link
Contributor

tannerdolby commented Apr 22, 2021

I was certain that the Twitter card was rendering correctly for pages on MDN, but it looks like the required <meta> tags for the Twitter summary and OpenGraph cards don't exist.

Screen Shot 2021-04-21 at 9 27 27 PM

The following <meta> tags should be added for the Twitter social share card to render correctly.

<meta name="twitter:card" content="summary_large_image"> <!-- or content="summary" -->
<meta name="twitter:site" content="@MozDevNet">
<meta name="twitter:title" content="MDN Web Docs">
<meta name="twitter:description" content="Some description text for the page">
<meta name="twitter:image" content="https://foobar.com/some-image.jpg">
<meta name="twitter:image:alt" content="Some alt text">

I couldn't track down where exactly the document metadata inside the <head> was being generated or manually typed, but if the <meta> tags are being written in a template, we could define the metadata in YAML format or another data source to populate the content of the required Twitter card meta tags. E.g. below is an example of defining the metadata as template variables and passing them into the required <meta> tags.

---
twitter_card_type: summary_large_image
twitter_handle: MozDevNet
twitter_card_title: MDN Web Docs
twitter_card_desc: Some description text for the page
twitter_card_image: https://foobar.com/buzz.jpg
twitter_card_image_alt: Some alt text

or maybe from an object

data:
  card_type: summary
  twitter_handle: FooBar

and access in the template {{ data.card_type }} 
---
<head>
  <meta name="twitter:card" content="{{ twitter_card_type }}">
  <meta name="twitter:site" content="@{{ twitter_handle }}">
  <meta name="twitter:title" content="{{ twitter_card_title }} ">
  <meta name="twitter:description" content="{{ twitter_card_desc }}">
  <meta name="twitter:image" content="{{ twitter_card_image }}">
  <meta name="twitter:image:alt" content="{{ twitter_card_image_alt }}">
</head>

This seems like a solid way to add support for the social share Twitter summary card. We could also add <meta> tags for the OpenGraph protocol (Facebook card) which look like:

<meta name="og:title" content="MDN Web Docs">
<meta name="og:type"  content="website">
<meta name="og:url" content="https://developer.mozilla.org/en-US/">
<meta name="og:description" content="Some description text for the page">
<meta name="og:image" content="https://foobar.com/some-image.jpg">
<meta name="og:image:alt" content="Some alt text">

These <meta> tags could also have their content populated through template variables or from another data source like mentioned for the Twitter card tags.

Thoughts

If the document metadata in the <head> is being rendered elsewhere and injected into the page, maybe writing a function to generate the <meta> tags needed for the Twitter summary code would be a start in that direction. Going further down this route, (my eleventy knowledge thinks "shortcode") but creating a KS macro that accepts the 6 string arguments or a single object argument with all the nested key/value pairs to generate the <meta> tags could be a good idea. That's if the metadata is being generated server side.

@tannerdolby
Copy link
Contributor Author

The twitter summary card comes in two flavors: summary and summary_large_image. The generic summary card is a small photo in the left with title and desc on right, and the summary_large_image card is a larger image placed on top with title and description underneath.

Summary card: <meta name="twitter:card" content="summary">

Screen Shot 2021-04-21 at 10 24 05 PM

Large summary card: <meta name="twitter:card" content="summary_large_image">

Screen Shot 2021-04-21 at 10 23 36 PM

@tannerdolby
Copy link
Contributor Author

tannerdolby commented Apr 22, 2021

@peterbe I could have sworn that the social share Twitter card worked when I shared a page on twitter to someone referencing a documentation page about 2-3 weeks ago. Let me know your thoughts on this.

@peterbe
Copy link
Contributor

peterbe commented Apr 22, 2021

@peterbe I could have sworn that the social share Twitter card worked when I shared a page on twitter to someone referencing a documentation page about 2-3 weeks ago. Let me know your thoughts on this.

Could it be that, unlike that Card Validator app, the real Twitter will fall back to the regular HTML meta tags that we have.

@peterbe
Copy link
Contributor

peterbe commented Apr 22, 2021

If someone knows of a tweet of an MDN URL it would be nice to look at.

@tannerdolby
Copy link
Contributor Author

tannerdolby commented Apr 22, 2021

I did a few test tweets on Twitter and the summary card isn't rendering.

Since the <meta name="twitter:*"> tags aren't in the <head>, the real Twitter won't be able to render the card just like validator because the regular HTML meta tags that it might fallback to still doesn't include <meta name="twitter:*"> tags.

Test tweet 1

Screen Shot 2021-04-22 at 1 02 26 PM

Test tweet 2

Screen Shot 2021-04-22 at 1 10 07 PM

Unless those <meta name="twitter:*"> tags are added, it looks like every MDN URL won't have a Twitter summary card rendered.

When I paste the URL into a tweet, there isn't a summary card generated. Twitter is most likely using the validator behind the scenes to verify the URL when pasted (or manually entered) into tweet has a valid summary card rendered and then pop it into the tweet. Nothing is generated when I paste an MDN URL into the tweet box shown below.

Screen Shot 2021-04-22 at 1 06 42 PM

@Ryuno-Ki
Copy link

Looking at view-source:https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox (that is, Ctrl-U on https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox ) I can confirm, that the <meta /> tags are not part of the initial HTML.

@tannerdolby
Copy link
Contributor Author

tannerdolby commented Apr 23, 2021

@peterbe I noticed all of the Mozilla hacks article pages do have the appropriate <meta> tags for a Twitter summary card and Facebook (OpenGraph) card, this is where I originally saw the summary card on Twitter, I tweeted one of Chris Mills blog posts from mozilla hacks and the summary card rendered nicely.

Screen Shot 2021-04-22 at 8 18 12 PM

I don't think the document metadata tags inside the <head> are being created in mdn/content as I couldn't find any of them there. I tracked down where the <head> was being defined for the [homepage}(https://developer.mozilla.org/en-US/) and it's here in Yari at client/public/index.html, should be a straight forward fix for this one. I couldn't find the template that each of the pages after /en-US/* use to update the <head> there, so that's next.

It seems the title template variables for every .html page in mdn/content is what populates the <title>,

---
title: Flexbox
...
---

Where it would be <title>{{ title }} - Learn web development | MDN</title> or another string after the {{ title }}. The title variable is being used somewhere in Yari (or mdn/content) to fill the <title> tags, its probably happening in a .tsx file somewhere I just can't seem to track down where. This is where the updating will need to be done for adding OpenGraph and Twitter <meta> tags while using the template data to populate the tags content="" dynamically for ones that will be changing.

@peterbe
Copy link
Contributor

peterbe commented Apr 23, 2021

I don't think it would be hard to inject. But is it worth it? It probably is because people do use Twitter no matter what you might think about proprietary bloat that fills up your HTML.
I do wonder, if we instead go for the OpenGraph HTML meta tags, will Twitter be able to build a pretty card out of that?

@tannerdolby
Copy link
Contributor Author

tannerdolby commented Apr 23, 2021

Yeah, it doesn't seem hard to inject. I think it is worth it. There are so many people using MDN (and potentially sharing links on social media) that having a summary card for both Twitter and Facebook appear rather than just a plain link would be better.

If we instead go for only the OpenGraph meta tags, ie

<head>
  <meta name="og:title" content="{{ title }} - Learn web dev | MDN">
  <meta name="og:type"  content="website">
  ...
</head>

Then browsers will only have a social share card for Facebook and Twitter won't be able to render one. Unless we use the information from each of the OpenGraph tags to populate the Twitter card meta tags eg:

const $head = $('head');

$('meta').each((i, elem) => {
    let $meta = $(elem);
    let name = $meta.attr('name');
    let content = $meta.attr('content');
  
    switch (name) {
      case "og:title":
        $head.append(`<meta name='twitter:title' content='${content}'>`);
      	break;
      case "og:url":
        $head.append(`<meta name='twitter:site' content='@MozDevNet'>`);
      	break;
      case "og:type":
        $head.append(`<meta name='twitter:card' content='summary_large_image'>`);
      	break;
      case "og:description":
        $head.append(`<meta name='twitter:description' content='${content}'>`);
     	break;
      case "og:image":
        $head.append(`<meta name='twitter:image' content='${content}'>`);
      	break;
      case "og:image:alt":
        $head.append(`<meta name='twitter:image:alt' content='${content}'>`);
      	break;
      default:
       // maybe append some default Twitter meta tags if the OpenGraph tags don't exist
    }
});

which would evaluate these OpenGraph cards

<meta name="og:title" content="MDN Web Docs">
<meta name="og:type"  content="website">
<meta name="og:url" content="https://developer.mozilla.org/en-US/">
<meta name="og:description" content="Some description text for the page">
<meta name="og:image" content="https://foobar.com/some-image.jpg">
<meta name="og:image:alt" content="Some alt text">

and create Twitter card meta tags like this

<meta name="twitter:title" content="MDN Web Docs">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@MozDevNet">
<meta name="twitter:description" content="Some description text for the page">
<meta name="twitter:image" content="https://foobar.com/some-image.jpg">
<meta name="twitter:image:alt" content="Some alt text">

@peterbe
Copy link
Contributor

peterbe commented Apr 23, 2021

First of all, we don't have images, which is a shame. I sometimes wish we could take a screenshot of the page (without the header and sidebar) and make that the image.
But I think my point is that 362 worth of bytes to add to the HTML. On top of the OpenGraph ones.
I'm not super worried about that but the summary string could be a lot larger and then you'll end up including that 4 times.

  1. The <meta name="description">
  2. The Twitter one
  3. the OpenGraph one
  4. The summary within the HTML page itself

So which websites can use and benefit from the OpenGraph tags?

By the way, I don't mind adding these so much. But the proprietary bloat of bending to Twitters will is a bit annoying so I'm also not rushing to it :)

@Ryuno-Ki
Copy link

Although Facebook is the most known consumer of Open Graph protocol, the circumstance that it is based on RDFa protocol allows for other crawlers to also understand it. Google is listed towards the end of that page.

Twitter is entirely proprietary here …

@peterbe
Copy link
Contributor

peterbe commented Apr 23, 2021

On https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/getting-started under the heading "Twitter Cards and Open Graph" it says

"When the Twitter card processor looks for tags on a page, it first checks for the Twitter-specific property, and if not present, falls back to the supported Open Graph property. This allows for both to be defined on the page independently, and minimizes the amount of duplicate markup required to describe content and experience."

So, let's reinstate the Open Graph meta tags and see how Twitter handles that.

@tannerdolby
Copy link
Contributor Author

First of all, we don't have images, which is a shame. I sometimes wish we could take a screenshot of the page (without the header and sidebar) and make that the image.

@peterbe We could but it's a bit of setup. If we had a sort of social share image generator that happens at build time, maybe using puppeteer to load the page and take a screenshot of the document with certain dimensions (to not include header and sidebar)

page.screenshot({
  path: '/someDir/splat',
  type: 'jpeg',
  clip: { x: 0, y: 0, width: 800, height:  
});

and have the background be an image or some color that would handle generating the social share image and then the image output to some dir can be accessed via URL assets/generated-social.jpg

@tannerdolby
Copy link
Contributor Author

tannerdolby commented Apr 23, 2021

So, let's reinstate the Open Graph meta tags and see how Twitter handles that.

Completely agree, let's see how the Twitter card processor handles that. Thanks for posting that bit from card reference, I wasn't aware that the processor would fallback to the supported OpenGraph property. Seems like the last bit of the puzzle would just be generating images for the OpenGraph meta tag.

@peterbe
Copy link
Contributor

peterbe commented Apr 23, 2021

First of all, we don't have images, which is a shame. I sometimes wish we could take a screenshot of the page (without the header and sidebar) and make that the image.

@peterbe We could but it's a bit of setup. If we had a sort of social share image generator that happens at build time, maybe using puppeteer to load the page and take a screenshot of the document with certain dimensions (to not include header and sidebar)

page.screenshot({
  path: '/someDir/splat',
  type: 'jpeg',
  clip: { x: 0, y: 0, width: 800, height:  
});

and have the background be an image or some color that would handle generating the social share image and then the image output to some dir can be accessed via URL assets/generated-social.jpg

In the past, I've used a service where you just point to a URL and it generates (and caches!) the screenshots based on something like puppeteer. Perhaps if you can combine it with a CSS selector or something to make it without the header and sidebar it could be neat. But it's bound to get very expensive at our scale.

Let's park that discussion for another day. Let's focus on Open Graph :)

@tannerdolby
Copy link
Contributor Author

@peterbe That sounds like a neat service! Yeah combining with some sort of selector or bit to make the dimensions not include the header or sidebar that'd be nice, but if it's very expensive with scale probably best to park for later.

Open Graph it is :)

peterbe added a commit that referenced this issue Apr 23, 2021
@Ryuno-Ki
Copy link

Dropping https://docs.htmlcsstoimage.com/ which is used by forem (dev.to) => new issue?

@tannerdolby
Copy link
Contributor Author

@Ryuno-Ki That's a really neat tool. Could definitely be useful down the line to generate the social share image for each SPA page. The current setup in #3623 renders a social card from the Open Graph meta tags for each social site besides Twitter, which should work as the twitter validator falls back to the Open Graph tags as Peter mentioned above from the docs. But it doesn't seem to be working as the docs say.

@peterbe
Copy link
Contributor

peterbe commented Apr 26, 2021

Dropping https://docs.htmlcsstoimage.com/ which is used by forem (dev.to) => new issue?

Discussion first. Then if we decide to act on it, discussions can be turned into issues.
(Bugs don't need to go that route. Nor feature topics that have been discussed offline)

@Ryuno-Ki
Copy link

Alright. #3638

@Gregoor Gregoor closed this as completed in 586bc31 May 4, 2021
peterbe added a commit to peterbe/yari that referenced this issue Jun 1, 2021
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

No branches or pull requests

3 participants