DEV Community

Cover image for Implementing Social Media Cards for Your Website
Paweł Kowalski for platformOS

Posted on • Originally published at

Implementing Social Media Cards for Your Website

Promoting content on social media is an important part of marketing. If you want to make sure your posts/tweets/stories are eye-catching or at least visible on the user's wall, you probably want to leverage OpenGraph tags to provide additional metadata to your content that will not only inform search engines about your content but also improve the appearence of social media cards.


When we started posting content on social media we noticed that our social media cards were missing images, descriptions. We decided to fix that on our documentation website and it proved to be pretty easy to do.

To check if your site is already optimized, use the following official tools:

Ideally what you want to see is a title, a description and an image showing up.


Most of the metadata we used are standard OpenGraph.

OpenGraph (Facebook, LinkedIn)

If you need more information about any of the properties used, read the OpenGraph official documentation.

<meta property="og:locale" content="en_US" />
<meta property="og:type" content="article" />
<meta property="og:site_name" content="platformOS Documentation" />
<meta property="article:section" content="Uncategorized" />

<meta property="og:title" content="{{ title }}" />
<meta property="og:description" content="{{ description }}" />
<meta property="og:url" content="{{ context.location.url }}" />

<meta property="article:published_time" content="{{ dates.created_at }}" />
<meta property="article:modified_time" content="{{ dates.content_updated_at }}" />
<meta property="og:updated_time" content="{{ dates.content_updated_at }}" />

<meta property="og:image" content="{{ 'images/pos-logo.png' | asset_url }}" />
<meta property="og:image:width" content="730" />
<meta property="og:image:height" content="412" />
Enter fullscreen mode Exit fullscreen mode

We hardcoded some of the metadata because we did not see the need to make it dynamic. You might want to also add author - consult the documentation to choose the best tags for your use case.

Here's an explanation for the dynamic parts:

  • title: a variable that we calculate based on what is in the current page metadata. We reused our title tag content here.
  • description: same as above, we reused our usual meta data description content here
  • image: absolute URL to the image. The image we used is 713x412px, but you can experiment with dimensions that fit your content/logo better.
  • url: absolute URL to the page (with query params if essential)
  • published_time: date when the content was first published - see below how we got the dates object
  • modified_time: datetime when the content was last modified - see below how we got the dates object
  • updated_time: datetime when the content was last modified - see below how we got the dates object


We did not use dates before, so we needed to pull those from the database using GraphQL. We used the admin_pages endpoint, filtered one page with the slug of the current page and pulled the date of file creation and the date of the last edit of the page body (not including metadata like title).

{% graphql page_dates, slug: %}
query get_dates($slug: String!) {
    per_page: 1
    filter: { slug: { value: $slug } }
  ) {
    results {
{% endgraphql %}

{% assign dates = page_dates | fetch: 'admin_pages' | fetch: 'results' | first %}
Enter fullscreen mode Exit fullscreen mode


Twitter uses its own set of metadata to extract for its cards preview.

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:description" content="{{ description }}" />
<meta name="twitter:title" content="{{ title }}" />
<meta name="twitter:image" content="{{ 'images/pos-logo-2to1.png' | asset_url }}" />
Enter fullscreen mode Exit fullscreen mode

Here's an explanation of new elements:

  • card: there are a couple of different card types that Twitter supports, we chose summary_large_image because it shows the image in a prolific way
  • image: Twitter requires the image to be in 2:1 aspect ratio for summary_large_image or it will not show, so we prepared another image for that reason


The difference in visibility is pretty big but what's more important, users are able to instantly tell what the link is about before they click it.


Twitter card before adding OpenGraph meta tags


Twitter card after adding OpenGraph meta tags

Structured data

After you have prepared your OpenGraph metadata, it is also a good idea to add so called structured data into your website.

Structured data helps search engines find and understand your content and website. It is organized and tagged with specific groups of text that help search engines understand the context of that information and can return accurate results to searchers.

This metadata is sometimes used by websites to generate rich snippets instead of OpenGraph. Additionally, this data is used by search engines to populate their rich snippets. Using structured data you can describe your content in detail. Because of that, it is more flexible. It is possible to describe the relation between entities (author, image, website). The more details you provide (within reason), the better.


<script type='application/ld+json'>
  "@context": "",
  "@graph": [
      "@type": "WebSite",
      "@id": "",
      "url": "",
      "name": "platformOS Documentation",
      "inLanguage": "en-US",
      "description": "Examples, tutorials, references, APIs, and best practices—everything you need to build future-proof applications on platformOS"
      "@type": "ImageObject",
      "inLanguage": "en-US",
      "url": "{{ 'images/pos-logo.png' | asset_url }}",
      "width": 730,
      "height": 412,
      "caption": "platformOS Documentation"
      "@type": "WebPage",
      "url": "{{ context.location.url }}",
      "name": "{{ title }}",
      "description": "{{ description }}",
      "isPartOf": {
        "@id": ""
      "inLanguage": "en-US",
      "primaryImageOfPage": {
        "@id": "{{ 'images/pos-logo.png' | asset_url }}"
      "datePublished": "{{ dates.created_at }}",
      "dateModified": "{{ dates.content_updated_at }}",
      "potentialAction": [
          "@type": "ReadAction",
          "target": [
            "{{ context.location.url }}"
Enter fullscreen mode Exit fullscreen mode

We basically recycled data we used in OpenGraph, and added very simple relations.


When you develop your own structured data, validate it on - it will show you warnings and errors should you encounter them.

Read the standard specification on:

Read these articles to get more practical information than from the official documentation:

Top comments (0)