-
Notifications
You must be signed in to change notification settings - Fork 12
Social Media Cards
This page contains documentation for a feature in preparation for history.state.gov |
Social Media Cards[^1] provide a way of controlling preview metadata for links shared on social media, including preview images, titles, and descriptions. This page described how hsg-project generates this metadata, and how that generation can be controlled, over-written, or extended.
[^1]: Sometimes referred by other names, such as "Social Previews" or "Social Media Previews"
Social Media Cards are generated by social media sites such as Twitter and Facebook when links are shared. Linked pages can define images, link titles, descriptions and more by providing the relevant metadata properties as <meta/>
elements in the HTML header.
Generally, this metadata conforms to the Open Graph Protocol, or is at least based on the same conventions[^2]; we will differentiate it from other types of metadata in this document as Open Graph metadata.
Open Graph metadata is normally provided as a meta
element with a key defined by a CURIE[^3] as the @property
and the value defined using @content
:
<meta property="og:type" content="website"/>
[^2]: see "Twitter Cards and Open Graph" on Twitter's Getting Started documentation. [^3]: Compact URIs
The HTML head
element is generated for all hsg-project pages by the same site.xml
template using exist-db's HTML templating module and resulting in a call to config:app-meta
:
<meta data-template="config:app-meta"/>
The config:app-meta
function populates the Open Graph metadata using a set of strings representing the metadata CURIEs (by default the sequence in $config:OPEN_GRAPH_KEYS
), and a mapping from CURIEs to functions (by default the map $config:OPEN_GRAPH
).
The set of strings or open graph keys define which metadata properties are to be populated; the corresponding entries in the open graph map define the functions which do so. This allows for some flexibility in customising how the metadata is populated for a particular page.
One of the required Open Graph properties, the default value for hsg-project is website
. Using other values may require additional properties to be defined.
<meta property="og:type" content="website"/>
This property is required by Twitter, and has the default value of summary
. There should not be more than one twitter:card
property per page, but if there is, the last will take priority.
<meta property="twitter:card" content="summary">
This property specifies the Twitter username of the website, @HistoryAtState
.
<meta property="twitter:site" content="@HistoryAtState">
This property specifies the human readable name of the web site:
<meta property="og:site_name" content="Office of the Historian">
One of the required Open Graph properties, this is the title of the page or resource; for hsg-project, the title may come from a number of possible sources:
- The static title of the page as defined by
div[@id='static-title']
$config:PUBLICATIONS?publication-id?title
- The first HTML heading on the page (
h1|h2|h3
) - The default fallback text of
Office of the Historian
<meta property="og:title" content="Latest News">
A one to two sentence description of the object. The default value is currently hard-coded.
<meta property="og:description" content="Office of the Historian">
One of the required Open Graph properties, this is the canonical URL of the object/page:
<meta property="og:url" content="https://history.state.gov">
One of the required Open Graph properties, this specifies one or more images that will be displayed with the link when shared in social media posts. A number of optional (but useful) metadata properties can follow each image:
Image width
: og:image:width
in pixels
Image height
: og:image:height
in pixels
Image MIME type
: og:image:type
Image alt text
: og:image:alt
By default, images will be taken from the associated TEI document for the page, if there is one. The default Office of the Historian logo is also provided as a fallback.
<meta property="og:image" content="https://static.history.state.gov/images/avatar_big.jpg">
<meta property="og:image:width" content="400">
<meta property="og:image:height" content="400">
<meta property="og:image:alt" content="Department of State heraldic Shield"/>
[^4]: Open Graph Specification [^5]: Twitter Cards Markup Tag Reference
As the population of Open Graph metadata is triggered from the same template function for every page, providing information for custom graph metadata for a given page needs to be done using the $model
application data map provided by exist-db's templating mechanism. This can be provided by any templating function in the page template that occurs as an ancestor of the site template:surround
templating function:
<div data-template="pages:load">
<div data-template="templates:surround" data-template-with="templates/site.xml" data-template-at="content">
<!-- Open Graph parameters could be provided here for the pages:load function-->
</div>
</div>
Any templating function that supports customising the Open Graph for this page must support parameters given by attributes in the HTML template file: data-template-open-graph-keys
, data-template-open-graph-keys-exclude
, and data-template-open-graph-keys-add
.
The most straightforward way of customising Open Graph generation for a page is to provide the properties within a div element with id static-open-graph
:
<div data-template="pages:load">
<div id="static-open-graph" data-template="pages:suppress">
<meta property="og:description" content="Custom hard-coded description goes here."/>
</div>
<div data-template="templates:surround" data-template-with="templates/site.xml" data-template-at="content">
<!-- Open Graph parameters could be provided here for the pages:load function-->
</div>
</div>
The provided properties are excluded from generation from the Open Graph map keys, and are copied to the page's HTML head instead of the corresponding function. NB: if the Open Graph property in question is generated using a key that doesn't match the property name, it may be necessary to use data-template-open-graph-keys-exclude
to prevent duplicate properties; see below.
If unique functions to populate one or more of the open graph properties is required, the $config:OPEN_GRAPH
map can be replaced or extended by adding it to the $model
map with the key open-graph
.
For example, let's consider the case where the time the last article was changed was particularly important: we could replace the open graph map as follows:
open-graph: map:merge((
$config:OPEN_GRAPH,
map {
"article:modified_time": function($node, $model) {<meta property="article:modified_time" content="{current-dateTime()}"/>}
}
))
Note that this approach may not be the best: most functions that generate Open Graph properties will have good re-use value, and it may be more appropriate to add the functionality to the default $config:OPEN_GRAPH
map instead, and simply specify different/additional Open Graph keys.
Even if you do decide to customize the Open Graph map, the functions added will have no effect unless the corresponding curie (in our example article:modified_time
) is also specified in the sequence of Open Graph keys
A new set of Open Graph keys can be specified as a whitespace separated list of values in the data-template-open-graph-keys
parameter:
<div data-template="pages:load" data-template-open-graph-keys="og:title og:type og:image og:url article:modified_time">
<div data-template="templates:surround" data-template-with="templates/site.xml" data-template-at="content">...</div>
</div>
Although it may often be more desirable to simply specify any additional keys using the data-template-open-graph-keys-add
parameter:
<div data-template="pages:load" data-template-open-graph-keys-add="article:modified_time">
<div data-template="templates:surround" data-template-with="templates/site.xml" data-template-at="content">...</div>
</div>
The effect of which is to add any keys specified to the current list of Open Graph keys, either defined by data-template-open-graph-keys
if present, or else using the default $config:OPEN_GRAPH_KEYS
.
It may be desirable to remove the generation of a default open graph property, which can be done in a similar way using data-template-open-graph-keys-exclude
:
<div data-template="pages:load" data-template-open-graph-keys-exclude="og:locale">
<div data-template="templates:surround" data-template-with="templates/site.xml" data-template-at="content">...</div>
</div>
And it is also possible to combine 'add' and 'exclude' to replace one function with another; 'exclude' is always processed first:
<div data-template="pages:load" data-template-open-graph-keys-exclude="twitter:card" data-template-open-graph-keys-add="twitter:card_large">
<div data-template="templates:surround" data-template-with="templates/site.xml" data-template-at="content">...</div>
</div>