Including dynamic Open Graph and Twitter meta tags in head

I suppose my question is twofold:

  1. What is the best way to add page-specific dynamic meta tags to OJS?
  2. Is there a reason why Open Graph og: and Twitter twitter: meta tags haven’t been added by default to OJS?

For context, I’m talking about adding tags like those shown below. They help with the shareability of the journal’s content, which in turn supports academia and discourse. I’m using the Health Sciences Theme if that changes the meta tags displayed.

<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://journal.bahaistudies.ca/online">
<meta property="og:title" content="The Journal of Bahá’í Studies">
<meta property="og:description" content="The central outlet for Bahá’í scholarship in North America.">
<meta property="og:image" content="https://journal.bahaistudies.ca/public/icons/jbs-mockup.png">

<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://journal.bahaistudies.ca/online">
<meta property="twitter:title" content="The Journal of Bahá’í Studies">
<meta property="twitter:description" content="The central outlet for Bahá’í scholarship in North America.">
<meta property="twitter:image" content="https://journal.bahaistudies.ca/public/icons/jbs-mockup.png">

As you can see with the preview below, the website presented with a custom short description that fits nicely in a share box across many sites. The issue I’m having is that while I’ve been able to add the static code above, I’m not sure how it would be best to make sure they’re dynamic to show the article or issue data linked. Below, you can see that this is actually to an article but the metadata is global to the journal.

From what I can tell, I could edit /lib/pkp/templates/frontend/components/headerHead.tpl but I’m not sure how to pull variables properly or what that would look like. It doesn’t seem like you can add smarty variables in fields like those provided by the Custom Header Plugin–I might be wrong.

So I’m wondering what might be a good approach to dynamically pulling metadata from the current page/article and injecting it into the head. This could then apply further to other structured data like adding schemas such as ScholarlyArticle in JSON format.

My Installation Information

Version Major Minor Revision Build Date installed
3.2.1.2 3 2 1 2 2021-01-19
Setting Name Setting Value
OS platform Linux
PHP version 7.4.3
Apache version Apache/2.4.41 (Ubuntu)
Database driver mysqli
Database server version 8.0.22-0ubuntu0.20.04.3

Hi @benaltair,

Here is an example of the plugin that adds those tags on the article landing page: GitHub - Vitaliy-1/socialMeta: Social Meta Plugin for OJS 3

2 Likes

Hi,
I have implemented schema.org (jsonld) in our theme: psychopen-theme/schema_json_ld.tpl at main - leibniz-psychology/psychopen-theme (github.com)

This workaround is partially dynamic, but some fields have fixed values. I’ m planning to build this as a plugin, but I haven’t had time to do this yet.

Maybe this will help you as inspiration :wink:

1 Like

This is great! Thanks for linking. I’ll give it a go :blush:

Awesome - that’s a great start. The manual fields all seem to be global anyway so I’ll see if I can adapt it to our needs.

Do you just reference this tpl file in one of the template files? Haven’t done that before.

Yes, it’s included in the headerHead.tpl

Got it, working beautifully! Thanks for the pointer. I’m adding a featured image to a couple of the objects as Google’s search tools suggested too. :pray:t2:

For what it’s worth, I’ll post my solution so far. I have adapted @RBoelter’s schema code and taken cues from @Vitaliy’s socialMeta plugin. Initially, these solutions are template files but could be adapted to plugins as @RBoelter mentioned. Please anyone feel free to do that if you know how - that is outside my experience so far.

If you’d like to implement this yourself, you’ll need to create the files below in your theme directory (eg. /plugins/themes/[themeName]/templates/frontend/components or in the default folder /templates). You’ll also need to modify the code below to fit your needs, including setting your own social media links, organization name and website, etc. This can all be dynamically pulled with PHP, which would be a more resilient solution. If anyone cares to do this, please post your adaptation! This would be a necessary step to a plugin adaptation.

The schema file is very similar to the one mentioned above but with added tags and logic. Additionally, I will mention that the logic around the images is quite proprietary to our use case so you may want to adjust that. You can read more about my little foray into CDN configuration on a seperate post: How do I use an image CDN to compress photos? - #5 by benaltair

schema_json_ld.tpl

{**
 * templates/frontend/objects/schema_json_ld.tpl
 *
 * Copyright (c) 2019 Ronny Bölter
 *
 * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
 *
 * @brief Writes a schema.org jsonld string to the header. Should be reworked as a plugin and in a more elegant way.
 * TODO Rework as plugin!
 *
 * Found from forum post and adapted from Github here:
 * https://github.com/leibniz-psychology/psychopen-theme/blob/main/templates/frontend/objects/schema_json_ld.tpl
 *
 *}
{assign var="indexURI" value="{url page="index" }"}
{assign var=indexURI value=$indexURI|explode:"/index.php"}
    <script type="application/ld+json">
        {
            "@context": "http://schema.org",
            "@graph": [
                {
                    "@type" : "Organization",
                    "@id": "https://journal.bahaistudies.ca/",
                    "name": "The Journal of Bahá’í Studies",
                    "logo": {
                        "@type": "ImageObject",
                        "name": "JBSLogo",
                        "url": "https://abs.imgix.net/public/images/jbs-black.png"
                    },
                    "url": "https://journal.bahaistudies.ca/",
                    "sameAs": [
                        "https://twitter.com/bahaistudies",
                        "https://vimeo.com/bahaistudies",
                        "https://www.facebook.com/bahaistudies/",
                        "https://www.instagram.com/bahaistudies/"
                    ],
                    "memberOf" : {
                        "@type" : "Organization",
                        "@id": "https://bahaistudies.ca/",
                        "url": "https://bahaistudies.ca/",
                        "name": "Association for Bahá’í Studies",
                        "logo": {
                            "@type": "ImageObject",
                            "name": "ABSLogo",
                            "url": "https://abs.imgix.net/public/images/abs-black.png?"
                        },
                        "address":{
                            "@type" : "PostalAddress",
                            "addressCountry": "Canada",
                            "addressLocality": "Ottawa",
                            "addressRegion": "Ontario",
                            "postalCode": "K1N 7K4",
                            "streetAddress": "34 Copernicus Street"
                        },
                        "email" : "abs-na@bahaistudies.ca",
                        "telephone": "+1 613-233-1903"
                    }
                }{if $requestedPage=='index' || $requestedPage==''},
                    {

                        "@type" : "WebSite",
                        "@id": "{$indexURI[0]}",
                        "url": "{$indexURI[0]}",
                        "name": "{if $currentJournal}{$currentJournal->getLocalizedPageHeaderTitle()|strip_tags:false|escape|strip}{else}{$pageTitleTranslated}{/if}",
                        {if $journalDescription}
                          "description": "{$journalDescription|strip_tags:false|escape|strip}",
                        {/if}
                        "potentialAction" : {
                            "@type" : "SearchAction",
                            "target" : "{url page="search"}?query={ldelim}srch_str{rdelim}",
                            "query-input": "required name=srch_str"
                        },
                        "accessMode": ["textual", "visual"],
                        "accessModeSufficient": ["textual", "visual"],
                        "accessibilityAPI": "ARIA",
                        "issn": [{if $printIssn}"{$printIssn}"{/if}{if $printIssn && $onlineIssn}, {/if}{if $onlineIssn}"{$onlineIssn}"{/if}
                        ],
                        "image": {
                        "https://abs.imgix.net/public/icons/jbs-mockup.png"
                       },
                        "license": "https://creativecommons.org/licenses/by-nc-sa/4.0/",
                        "copyrightHolder" :{
                            "@type" : "Organization",
                            "@id": "https://bahaistudies.ca/"
                        },
                        "publisher": {
                            "@type" : "Organization",
                            "@id": "https://journal.bahaistudies.ca/"
                        }
                    }
                {/if}{if $issue && $currentJournal && $requestedPage!='index' && $requestedPage!=''},
                    {assign var="thumb" value=$currentJournal->getLocalizedSetting('journalThumbnail')}
                    {
                        "@id": "{url page="issue" op="view" path=$issue->getId()}",
                        "@type": "PublicationIssue",
                        "issueNumber": "{$issue->getNumber()}",
                        "datePublished": "{$issue->getDatePublished()|date_format:"%Y-%m-%d"}",
                        "name" : "{$issue->getLocalizedTitle()|strip_tags:false|escape|strip}",
                        {if $issueCover}
                            "image": "{$issueCover|escape}",
                        {elseif $issueThumb}
                            "image": "{$publicFilesDir}/{$issueThumb}",
                        {/if}
                        {if $publishedArticles}
                            "hasPart":[
                                {foreach name=sections from=$publishedArticles item=section name=foo}
                                    {foreach from=$section.articles item=article name=bar}
                                        {
                                            "@type": "ScholarlyArticle",
                                            "headline" : "{$article->getLocalizedTitle($article->getLocale())|strip_tags:false|escape|strip|truncate:110}",
                                            "name" : "{$article->getLocalizedTitle($article->getLocale())|strip_tags:false|escape|strip}",
                                            "mainEntityOfPage": {
                                                "@type": "WebPage",
                                                "url": "{url page="article" op="view" path=$article->getId()}",
                                                "@id": "{url page="article" op="view" path=$article->getId()}",
                                                "name": "{$article->getLocalizedTitle($article->getLocale())|strip_tags:false|escape|strip|truncate:110}"
                                            },
                                            "image": {
                                            "https://abs.imgix.net/public/icons/jbs-mockup.png"
                                           },
                                            {*"@id": "{url page="article" op="view" path=$article->getId()}",*}
                                            "url": "{url page="article" op="view" path=$article->getId()}",
                                                {if $article->getLocalizedCoverImage()}
                                                    "image": "{$article->getLocalizedCoverImageUrl()|escape}",
                                                {elseif $issueCover}
                                                    "image": "{$issueCover|escape}",
                                                {elseif $issueThumb}
                                                    "image": "{$publicFilesDir}/{$issueThumb}",
                                                {elseif $thumb}
                                                    "image": "{$publicFilesDir}/{$thumb.uploadName|escape:"url"}",
                                                {/if}
                                                {if $article->getAuthors()}
                                                    "author": [
                                                        {foreach from=$article->getAuthors() item=author  name=foo}
                                                            {
                                                                "@type": "Person",
                                                                {if $author->getLocalizedAffiliation()}
                                                                    "affiliation": "{$author->getLocalizedAffiliation()|strip_tags:false|escape|strip}",
                                                                {/if}
                                                                {if $author->getOrcid()}
                                                                    "sameAs": "{$author->getOrcid()|escape}",
                                                                {/if}
                                                                "name" : "{$author->getFullName()|strip_tags:false|escape|strip}"
                                                            }{if not $smarty.foreach.foo.last},{/if}
                                                        {/foreach}
                                                    ],
                                                {/if}
                                            "pagination": "{$article->getPages()|escape}",
                                            {if $article->getDatePublished()}
                                              "datePublished": "{$article->getDatePublished()|date_format:"%Y-%m-%d"}",
                                            {/if}
                                            {if $article->getLastModified()}
                                                "dateModified": "{$article->getLastModified()|date_format:"%Y-%m-%d"}",
                                            {elseif $article->getDatePublished()}
                                                "dateModified": "{$article->getDatePublished()|date_format:"%Y-%m-%d"}",
                                            {/if}
                                                "publisher": {
                                                    "@type" : "Organization",
                                                    "@id": "https://journal.bahaistudies.ca/",
                                                    "url": "https://journal.bahaistudies.ca/"
                                                }
                                        }{if not ($smarty.foreach.foo.last && $smarty.foreach.bar.last)},{/if}
                                    {/foreach}
                                {/foreach}
                            ],
                        {/if}
                        "isPartOf": {
                            "@type": [
                                "PublicationVolume",
                                "Periodical"
                            ],
                            "name": "{$currentJournal->getLocalizedPageHeaderTitle()|strip_tags:false|escape|strip}",
                            "issn": [
                                {if $printIssn}"{$printIssn}",{/if}
                                {if $onlineIssn}"{$onlineIssn}"{/if}
                            ],
                            "volumeNumber" : "{$issue->getVolume()}",
                            "datePublished" : "{$issue->getYear()}",
                            "publisher": {
                                "@type" : "Organization",
                                "@id": "https://journal.bahaistudies.ca/",
                                "url": "https://journal.bahaistudies.ca/"
                            }
                        }
                    }{if $article && not $publishedArticles},
                        {foreach from=$pubIdPlugins item=pubIdPlugin}
        {if $pubIdPlugin->getPubIdType() == 'doi'}
        {if $issue->getPublished()}
        {assign var=pubId value=$article->getStoredPubId($pubIdPlugin->getPubIdType())}
        {else}
        {assign var=pubId value=$pubIdPlugin->getPubId($article)}{* Preview pubId *}
        {/if}
        {/if}
        {/foreach}
        {if $pubId}
        {assign var="doiUrl" value=$pubIdPlugin->getResolvingURL($currentJournal->getId(), $pubId)|escape}
        {/if}
                        {
                                "@type": "WebPage",
                                "@id": "{url page="article" op="view" path=$article->getId()}",
                                "url": "{url page="article" op="view" path=$article->getId()}",
                                "name": "{$article->getLocalizedTitle($article->getLocale())|strip_tags:false|escape|strip}",
                                "description": "{$article->getLocalizedAbstract()|strip_tags:false|escape|strip}",
                                "breadcrumb": "Archives > Volume {$issue->getVolume()}({$issue->getNumber()}) > {$article->getLocalizedTitle($article->getLocale())|strip_tags:false|escape|strip|truncate:110}",
                                "speakable":
                                 {
                                  "@type": "SpeakableSpecification",
                                  "xpath": [
                                    "/html/head/title",
                                    "/html/head/meta[@name='description']/@content"
                                    ]
                                  },
                                "isPartOf": {
                                    "@type" : "Website",
                                    "@id": "{$indexURI[0]}",
                                    "url": "{$indexURI[0]}",
                                    "name": "{if $currentJournal}{$currentJournal->getLocalizedPageHeaderTitle()|strip_tags:false|escape|strip}{else}{$pageTitleTranslated}{/if}"
                                },
                                "mainEntity": {
                            "@type": "ScholarlyArticle",
                            {*"@id": "{url page="article" op="view" path=$article->getId()}",*}
                            "mainEntityOfPage": "{url page="article" op="view" path=$article->getId()}",
                            "image":
{if $issue->getLocalizedCoverImageUrl()}
                            "{$issue->getLocalizedCoverImageUrl()|escape}"
{elseif $issue->getIssueSeries()}
                            "https://abs.imgix.net/public/images/blank-cover.png?w=400&h=600&mark64=aHR0cHM6Ly9hYnMuaW1naXgubmV0L3B1YmxpYy9pbWFnZXMvamJzLXdoaXRlLnBuZw&mark-align=middle%2Ccenter&mark-w=0.80&mark-y=106&txt={$issue->getIssueSeries()}&txt-font=PTSerif-Regular&txt-color=fff&txt-align=middle%2Ccenter&txt-size=22&txt-clip=ellipsis&auto=format&exp=-10&hue=132&bg=00395B&blend64=aHR0cHM6Ly9hYnMuaW1naXgubmV0L3B1YmxpYy9pbWFnZXMvZmxvdXJpc2gucG5nP2ludmVydD10cnVlJnJvdD0xODA&blend-align=bottom%2Ccenter&blend-w=0.30&blend-mode=normal&blend-y=203"
{else}
                            "https://abs.imgix.net/public/icons/jbs-mockup.png"
{/if}
                           ,
                            "isPartOf":
                                {
                                    "@type": "PublicationIssue",
                                    "@id": "{url page="issue" op="view" path=$issue->getId()}",
                                    "url": "{url page="issue" op="view" path=$issue->getId()}",
                                    "name" : "{$issue->getLocalizedTitle()|strip_tags:false|escape|strip}",
                                    "issueNumber": "{$issue->getNumber()}",
                                    "datePublished": "{$issue->getDatePublished()|date_format:"%Y-%m-%d"}"
                                },
                            "headline" : "{$article->getLocalizedTitle($article->getLocale())|strip_tags:false|escape|strip|truncate:110}",
                            "name" : "{$article->getLocalizedTitle($article->getLocale())|strip_tags:false|escape|strip}",
                             {if $article->getLocalizedSubtitle($article->getLocale())}
                                "alternativeHeadline":"{$article->getLocalizedSubtitle($article->getLocale())|strip_tags:false|escape|strip|truncate:110}",
                            {/if}
        {if $article->getLocalizedCoverImage()}
                                "image": "{$article->getLocalizedCoverImageUrl()|escape}",
                            {elseif $issueCover}
                                "image": "{$issueCover|escape}",
                            {elseif $issueThumb}
                                "image": "{$publicFilesDir}/{$issueThumb}",
                            {/if}
                            "description": "{$article->getLocalizedAbstract()|strip_tags:false|escape|strip}",
                            {if $doiUrl}
                                "sameAs": "{$doiUrl}",
                            {/if}
        {if $section && $section->getLocalizedTitle()}
                                "articleSection" : "{$section->getLocalizedTitle()|escape}",
                            {/if}
        {if $article->getDatePublished()}
                                "datePublished": "{$article->getDatePublished()|date_format:"%Y-%m-%d"}",
                            {/if}
        {if $article->getLastModified()}
                                "dateModified": "{$article->getLastModified()|date_format:"%Y-%m-%d"}",
                            {elseif $article->getDatePublished()}
                                "dateModified": "{$article->getDatePublished()|date_format:"%Y-%m-%d"}",
                            {/if}
                            "url" : "{url page="article" op="view" path=$article->getId()}",
                            "pagination": "{$article->getPages()|escape}",
                            "publisher": {
                                "@type" : "Organization",
                                "@id": "https://journal.bahaistudies.ca/",
                                "url": "https://journal.bahaistudies.ca/"
                            },
                            {if $article->getGalleys()}
        {assign var="galleysTotalView" value=0}
        {foreach from=$article->getGalleys() item=galley name=galleyList}
        {assign var="galleysTotalView" value=$galleysTotalView+$galley->getViews()}
        {/foreach}
                                "interactionStatistic": {
                                    "@type": "InteractionCounter",
                                    "userInteractionCount": "{$galleysTotalView}"
                                },
                            {/if}
        {if $article->getAuthors()}
                                "author": [
                                    {foreach from=$article->getAuthors() item=author  name=foo}
                                        {
                                            "@type": "Person",
                                            {if $author->getLocalizedAffiliation()}
                                                "affiliation": "{$author->getLocalizedAffiliation()|strip_tags:false|escape|strip}",
                                            {/if}
        {if $author->getOrcid()}
                                                "sameAs": "{$author->getOrcid()|escape}",
                                            {/if}
                                            "name" : "{$author->getFullName()|escape}"
                                        }{if not $smarty.foreach.foo.last},{/if}
        {/foreach}
                                ],
                            {/if}
                            "isAccessibleForFree": "true",
                            "inLanguage": "{$article->getLocale()}"
                        }
                         }
                    {/if}
        {/if}
            ]
        }
    </script>
    {if $announcements}
        {assign var="thumb" value=$currentJournal->getLocalizedSetting('journalThumbnail')}
        <script type="application/ld+json">
            {
                "@context": "http://schema.org",
                "@graph": [
                    {foreach name=announcements from=$announcements item=announcement name=foo}
                        {
                            "@type": "NewsArticle",
                            "headline": "{$announcement->getLocalizedTitle()|strip_tags:false|escape|strip}",
                            "datePublished": "{$announcement->getDatePosted()|date_format:"%Y-%m-%d"}",
                            "dateModified": "{$announcement->getDatePosted()|date_format:"%Y-%m-%d"}",
                            "url": "{url router=$smarty.const.ROUTE_PAGE page="announcement" op="view" path=$announcement->getId()}",
                            {if $thumb}
                                "image": "{$publicFilesDir}/{$thumb.uploadName|escape:"url"}",
                            {/if}
                            "mainEntityOfPage": {
                                "@type": "WebPage",
                                "@id": "{url router=$smarty.const.ROUTE_PAGE page="announcement" op="view" path=$announcement->getId()}"
                            },
                            {if $announcement->getLocalizedDescription()}
                                "articleBody": "{$announcement->getLocalizedDescription()|strip_tags:false|escape|strip}",
                            {else}
                                "articleBody": "{$announcement->getLocalizedDescriptionShort()|strip_tags:false|escape|strip}",
                            {/if}
                            "author": "{$currentJournal->getLocalizedPageHeaderTitle()|strip_tags:false|escape|strip}",
                            "publisher": {
                                "@type" : "Organization",
                                "@id": "https://journal.bahaistudies.ca/",
                                "url": "https://journal.bahaistudies.ca/"
                            }
                        }{if not $smarty.foreach.foo.last},{/if}
            {/foreach}
                ]
            }
        </script>
    {/if}

social_meta.tpl

{**
 * templates/frontend/objects/social_meta.tpl
 *
 * Copyright (c) 2021 Ben Altair, Association for Baha'i Studies, https://bahaistudies.ca/
 *
 * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
 *
 * @brief Prepares open graph and twitter social tags for the header for SEO and sharing.
 *
 *}
    {* Open Graph / Twitter Tags *}
{if $article}
    <meta property="og:type" content="article"/>
{else}
    <meta property="og:type" content="website"/>
{/if}
{if $article}
{foreach from=$pubIdPlugins item=pubIdPlugin}
{if $pubIdPlugin->getPubIdType() != 'doi'}
    {continue}
{/if}
{assign var=pubId value=$article->getStoredPubId($pubIdPlugin->getPubIdType())}
{if $pubId}
    {assign var="doiUrl" value=$pubIdPlugin->getResolvingURL($currentJournal->getId(), $pubId)|escape}
<meta property="og:url" content="{$doiUrl}"/>
{else}
    <meta property="og:url" content="{$currentUrl}"/>
{/if}
{/foreach}
{else}
    <meta property="og:url" content="{$currentUrl}"/>
{/if}
{if $article}
    <meta property="og:title" content="{$article->getLocalizedTitle()|strip_unsafe_html}"/>
{else}
    <meta property="og:title" content="{$pageTitleTranslated|strip_tags}"/>
{/if}
    <meta property="og:site_name" content=""/>
{if $article}
    <meta property="og:description" content="{$article->getAuthorString()|escape}"/>
{else}
    <meta property="og:description" content="A peer-reviewed academic journal by the Association for Bahá’í Studies."/>
{/if}
{if $article or $issue}
{if $issue->getLocalizedCoverImageUrl()}
    <meta property="og:image" content="https://abs.imgix.net/public/images/desk.jpg?mark={$issue->getLocalizedCoverImageUrl()|escape}&mark-w=360&mark-x=315&mark-y=323&mark-rot=23&crop=left&h=900&w=900&fit=crop"/>
    <meta property="og:image:secure_url" content="https://abs.imgix.net/public/images/desk.jpg?mark={$issue->getLocalizedCoverImageUrl()|escape}&mark-w=360&mark-x=315&mark-y=323&mark-rot=23&crop=left&h=900&w=900&fit=crop"/>
    <meta property="twitter:image" content="https://abs.imgix.net/public/images/desk.jpg?mark={$issue->getLocalizedCoverImageUrl()|escape}&mark-w=360&mark-x=315&mark-y=323&mark-rot=23&crop=left&h=900&w=900&fit=crop"/>
{elseif $issue->getIssueSeries()}
{assign var=basicCover value="https://abs.imgix.net/public/images/blank-cover.png?w=400&h=600&mark64=aHR0cHM6Ly9hYnMuaW1naXgubmV0L3B1YmxpYy9pbWFnZXMvamJzLXdoaXRlLnBuZw&mark-align=middle%2Ccenter&mark-w=0.80&mark-y=106&txt={if $issue->getIssueSeries()}{$issue->getIssueSeries()}{/if}&txt-font=PTSerif-Regular&txt-color=fff&txt-align=middle%2Ccenter&txt-size=22&txt-clip=ellipsis&auto=format&exp=-10&hue=132&bg=00395B&blend64=aHR0cHM6Ly9hYnMuaW1naXgubmV0L3B1YmxpYy9pbWFnZXMvZmxvdXJpc2gucG5nP2ludmVydD10cnVlJnJvdD0xODA&blend-align=bottom%2Ccenter&blend-w=0.30&blend-mode=normal&blend-y=203"}
    <meta property="og:image" content="https://abs.imgix.net/public/images/desk.jpg?mark64={base64_encode($basicCover)}&mark-w=360&mark-x=315&mark-y=323&mark-rot=23&crop=left&h=900&w=900&fit=crop"/>
    <meta property="og:image:secure_url" content="https://abs.imgix.net/public/images/desk.jpg?mark64={base64_encode($basicCover)}&mark-w=360&mark-x=315&mark-y=323&mark-rot=23&crop=left&h=900&w=900&fit=crop"/>
    <meta property="twitter:image" content="https://abs.imgix.net/public/images/desk.jpg?mark64={base64_encode($basicCover)}&mark-w=360&mark-x=315&mark-y=323&mark-rot=23&crop=left&h=900&w=900&fit=crop"/>
{else}
    <meta property="og:image" content="https://abs.imgix.net/public/images/jbs-mockup.png?txt={$issue->getIssueSeries()|escape}&txt-align=middle%2C%20center&txt-font=PTSerif-Bold&txt-size=50&txt-color=white&txt-pad=100&w=900&h=900&fit=clip&txt-shad=42&txt-clip=ellipsis"/>
    <meta property="og:image:secure_url" content="https://abs.imgix.net/public/images/jbs-mockup.png?txt={$issue->getIssueSeries()|escape}&txt-align=middle%2C%20center&txt-font=PTSerif-Bold&txt-size=50&txt-color=white&txt-pad=100&w=900&h=900&fit=clip&txt-shad=42&txt-clip=ellipsis"/>
    <meta property="twitter:image" content="https://abs.imgix.net/public/images/jbs-mockup.png?txt={$issue->getIssueSeries()|escape}&txt-align=middle%2C%20center&txt-font=PTSerif-Bold&txt-size=50&txt-color=white&txt-pad=100&w=900&h=900&fit=clip&txt-shad=42&txt-clip=ellipsis"/>
{/if}
{else}
    <meta property="og:image" content="https://abs.imgix.net/public/images/jbs-mockup.png?h=900&w=900&fit=crop"/>
    <meta property="og:image:secure_url" content="https://abs.imgix.net/public/images/jbs-mockup.png?h=900&w=900&fit=crop"/>
    <meta property="twitter:image" content="https://abs.imgix.net/public/images/jbs-mockup.png?h=900&w=900&fit=crop"/>
{/if}
    <meta property="og:image:width" content="900"/>
    <meta property="og:image:height" content="900"/>
    <meta property="og:image:alt" content="The cover of this journal issue." />
{if $article}
    <meta property="og:article:modified_time" content="{$article->getLastModified()|date_format:'%Y-%m-%d'}"/>
{elseif $article}
    <meta property="og:article:published_time" content="{$article->getDatePublished()|date_format:'%Y-%m-%d'}"/>
{/if}
{if $article}
    <meta property="og:article:section" content="{$section->getLocalizedTitle()|escape}"/>
{/if}
{if $article}
    {foreach from=$article->getAuthors() item=author  name=foo}
<meta property="og:article:author" content="{$author->getFullName()|escape}"/>
    {/foreach}
{/if}
    <meta property="og:locale" content="{$primaryLocale}"/>
    {if $languageToggleLocales && $languageToggleLocales|@count > 1}
{foreach from=$languageToggleLocales item="localeName" key="localeKey"}
{if $localeKey !== $currentLocale}
<meta property="og:locale:alternate" content="{$localeKey}"/>
{/if}
{/foreach}
{/if}
{if !empty($keywords[$currentLocale])}
 
{foreach from=$keywords item=keyword}
{foreach name=keywords from=$keyword item=keywordItem}
<meta property="og:article:tag" content="{$keywordItem|escape}"/>
{/foreach}
{/foreach}
{/if}
    <meta property="twitter:card" content="summary"/>
    <meta property="twitter:url" content="{$currentUrl}"/>
    <meta property="twitter:site" content="@bahaistudies"/>
    <meta property="twitter:title" content="{$pageTitleTranslated|strip_tags}"/>
{if $article}
    <meta property="twitter:description" content="{$article->getAuthorString()|escape}"/>
{else}
    <meta property="twitter:description" content="A peer-reviewed academic journal by the Association for Bahá’í Studies, connecting the teachings of the Bahá’í Faith to the needs of humanity."/>
{/if}
    <meta property="twitter:image:alt" content="The cover of this journal issue." />

Now, you’ll need to modify headerHead.tpl of the currently enabled theme by adding the following two references. This will pull the relevant template objects into the <head> of every page. I put mine right under that row that has {load_stylesheet context="frontend"}.

{* Include social metadata *}
{include file="frontend/objects/social_meta.tpl"}
{* Include JSON Schema.org metadata *}
{include file="frontend/objects/schema_json_ld.tpl"}

As I mentioned above, wherever images are concerned, there is a bit more going on. That is because I’m using imgix to dynamically generate images so that when you share a page like the ones below, it will show the actual issue cover in the image (look closely next to the coffee mug). Additionally, I’m dynamically generating covers for older issues that we’re importing right now that never had print covers.

From my tests with the Google Structured Data Testing Tool it is currently fully passing with a ton of embedded machine-readable data. Additionally, testing on the Twitter Card validator and Facebook Debugger show the same results. By the way, a nice simple tool for previewing metadata to get a sense of how it flows on each platform, you can use Meta Tags.

Thank you both for helping find a solution that will work for now.

2 Likes