Building Dublin Core metadata in blogs with Movable Type templates

| 5 Comments | No TrackBacks

This article is related to one that I published a long time ago, Using Dublin Core in RSS feeds. A lot of time has passed since then, and Movable Type has been enriched with numerous additional features that make it fairly easy to assign complete Dublin Core metadata headers to pretty much every page created with Movable Type.

Here are the necessary lines of code that you need to add to your Movable Type Main Index and Entry templates to generate an extensive amount of DC metadata for your blog; I will explain what each of them is doing, but for a detailed description what the DC terms mean, I would refer you to my earlier article, the DC-ASSIST tool from UKOLN, or the Dublin Core website, including their article on Expressing Dublin Core in HTML/XHTML meta elements.

1. Dublin Core meta tags for the Entry template

This is the more important set, as it provides detailed metadata for each entry posted in the blog. The following template automatically creates metadata for each blog entry using the following Dublin Core elements and terms: title, creator, subject, description, publisher, contributor, date, date.created, date.modified, type, format, identifier, language, relation.isPartOf, relation.isReferencedBy, relation.references, rights and rightsHolder.

(Note: Movable Type does not provide a tag for the blog owner's or main administrator's blog publisher's name, so the value for "DC.publisher" must be filled in manually.)

Copy and paste the following code into the Entry template, somewhere between the <head> and </head> tags:

<link rel="schema.DC" href="http://purl.org/DC/elements/1.1/" title="Dublin Core Metadata Element Set" /> 
<link rel="schema.DCTERMS" href="http://purl.org/dc/terms/" title="Dublin Core Terms" /> 
<meta name="DC.title" xml:lang="<$mt:BlogLanguage$>" content="<$mt:EntryTitle encode_html="1"$>" /> 
<meta name="DC.creator" content="<$mt:EntryAuthorDisplayName$>" /> 
<meta name="DC.subject" xml:lang="<$mt:BlogLanguage$>" content="<$mt:EntryCategory encode_html="1"$><mt:EntryIfTagged>, <mt:EntryTags encode_html="1" glue=", "><$mt:TagName$></mt:EntryTags></mt:EntryIfTagged>" /> 
<meta name="DC.description" xml:lang="<$mt:BlogLanguage$>" content="<$mt:EntryExcerpt encode_html="1"$>" /> 
<meta name="DC.publisher" content="[insert name of blog owner here]" />
<mt:IfCommentsActive><mt:Comments><mt:IfCommenterIsEntryAuthor><mt:Else><meta name="dc.contributor" content="<$mt:CommentAuthor$>" /></mt:IfCommenterIsEntryAuthor></mt:Comments></mt:IfCommentsActive> 
<meta name="DC.date" scheme="DCTERMS.W3CDTF" content="<$mt:EntryDate format_name="iso8601"$>" /> 
<meta name="DCTERMS.created" scheme="DCTERMS.W3CDTF" content="<$mt:EntryCreatedDate format_name="iso8601"$>" /> 
<meta name="DCTERMS.modified" scheme="DCTERMS.W3CDTF" content="<$mt:EntryModifiedDate format_name="iso8601"$>" /> 
<meta name="DC.type" scheme="DCTERMS.DCMIType" content="Text" /> 
<meta name="DC.format" scheme="DCTERMS.IMT" content="text/html" /> 
<meta name="DC.identifier" scheme="DCTERMS.URI" content="<$mt:EntryPermalink$>" /> 
<meta name="DC.language" scheme="DCTERMS.RFC4646" content="<$mt:BlogLanguage$>" /> 
<meta name="DCTERMS.isPartOf" scheme="DCTERMS.URI" content="<$mt:BlogURL$>" /> 
<mt:IfPingsAccepted><mt:Pings><meta name="DCTERMS.isReferencedBy" scheme="DCTERMS.URI" content="<$mt:PingURL$>" /></mt:Pings></mt:IfPingsAccepted> 
<mt:PingsSent><meta name="DCTERMS.references" scheme="DCTERMS.URI" content="<$mt:PingsSentURL$>" /></mt:PingsSent> 
<meta name="DC.rights" content="Copyright <$mt:EntryDate format="%Y"$> by <$mt:EntryAuthorDisplayName$>." /> 
<meta name="DCTERMS.rightsHolder" content="<$mt:EntryAuthorDisplayName$>" />

What this code does:

  • the two <link rel> lines provide the necessary namespace for the Dublin Core elements and terms
  • the Title element is generated from the entry's title
  • the Creator element is generated from the entry author's display name
  • the Subject element is generated from the entry's main category and all of its tags
  • the Description element is generated from an excerpt of the entry (either the one entered in Movable Type, or one that is generated from the first words of the text)
  • the Publisher element ("the entity responsible for making the resource available") cannot be determined by Movable Type; it must be entered manually in this line. However, as it is the same for all blog entries, this causes no further problems.
  • the Contributor element is generated from the names of all users who have left comments on this entry (except the entry author's name)
  • the Date element and the created and modified terms are generated from the entry's publish, creation an modification dates respectively (the first of these is editable, the latter two are not)
  • the Type and Format elements are "Text" and "text/html" by default for all HTML web pages and are thus entered as fixed values
  • the Identifier element is generated from the entry's permalink
  • the Language element is generated from the default language for date display set in Movable Type
  • the isPartOf term is generated from the blog's main URL
  • the isReferencedBy and references terms are generated by all incoming and outgoing trackback pings respectively.
  • the Rights element and RightsHolder term contain the entry author's display name; this may need to be edited if this is a blog where the publisher rather than the author holds the copyright

I'm using a version of this code for The Aardvark Speaks. Movable Type 4 is extremely flexible when it comes to adapting it to suit various needs; using Movable Type's custom fields it's even quite easy to do a multilingual blog and create correct metadata depending on the entry's main language (have a look at the source code of my German blog posts to see what this looks like).

2. Dublin Core meta tags for the Main Index template

This is largely similar to the Entry template and is different only in that it uses the dates from the most recently modified blog post and leaves out a couple of DC elements that do not apply to the index page. It automatically creates metadata for the blog index page using the following Dublin Core elements and terms: title, subject, description, publisher, contributor, date, date.modified, type, format, identifier, language, relation.hasFormat and rights. An option exists to include creator if all blog entries are written by the same person.

(Note: the value for "DC.publisher" must be filled in manually.)

Copy and paste the following code into the Main Index template, somewhere between the <head> and </head> tags:

<link rel="schema.DC" href="http://purl.org/DC/elements/1.1/" title="Dublin Core Metadata Element Set" /> 
<link rel="schema.DCTERMS" href="http://purl.org/dc/terms/" title="Dublin Core Terms" /> 
<meta name="DC.title" xml:lang="<$mt:BlogLanguage$>" content="<$mt:BlogName encode_html="1"$>" />
<meta name="DC.subject" xml:lang="<$mt:BlogLanguage$>" content="<mt:Tags top="10"><$mt:TagName encode_html="1"$><mt:Unless name="__last__">, </mt:Unless></mt:Tags>" />
<meta name="DC.description" xml:lang="<$mt:BlogLanguage$>" content="<$mt:BlogDescription encode_html="1"$>" />
<meta name="DC.publisher" content="[insert name of blog owner here]" />
<mt:Authors sort_by="created_on"><meta name="DC.contributor" content="<$mt:AuthorDisplayName$>" /></mt:Authors">
<mt:Entries lastn="1"><meta name="DC.date" scheme="DCTERMS.W3CDTF" content="<$mt:EntryDate format_name="iso8601"$>" /></mt:Entries>
<mt:Entries lastn="1" sort_by="modified_on"><meta name="DCTERMS.modified" scheme="DCTERMS.W3CDTF" content="<$mt:EntryModifiedDate format_name="iso8601"$>" /></mt:entries>
<meta name="DC.type" scheme="DCTERMS.DCMIType" content="Text" />
<meta name="DC.format" scheme="DCTERMS.IMT" content="text/html" />
<meta name="DC.identifier" scheme="DCTERMS.URI" content="<$mt:Link template="main_index" with_index="1"$>" />
<meta name="DC.language" scheme="DCTERMS.RFC4646" content="<$mt:BlogLanguage$>" />
<meta name="DCTERMS.hasFormat" scheme="DCTERMS.URI" content="<$mt:Link template="feed_recent"$>" />
<mt:Entries lastn="1"><meta name="DC.rights" content="Copyright <$mt:EntryDate format="%Y"$> by the author(s) and publisher of this blog." />
</mt:entries>
<!-- remove this line if all blog entries are written by the same author
<mt:Entries lastn="1"><meta name="DC.creator" content="<$mt:EntryAuthorDisplayName$>" /></mt:Entries>
remove this line if all blog entries are written by the same author -->

What this code does:

  • the two <link rel> lines provide the necessary namespace for the Dublin Core elements and terms
  • the Title element is generated from the blog's name
  • the Subject element is generated from the blog's ten most frequently used tags
  • the Description element is generated from the blog's description as entered in Movably Type
  • the Publisher element ("the entity responsible for making the resource available") cannot be determined by Movable Type; it must be entered manually in this line. However, as it is the same for all blog entries, this causes no further problems.
  • the Contributor element is generated from the display names of all authors for this blog
  • the Date element is generated from the last entry's publication date
  • the modified term is generated from the most recently edited entry's modification date
  • the Type and Format elements are "Text" and "text/html" by default for all HTML web pages and are thus entered as fixed values
  • the Identifier element is generated from the main index's URL as specified on Movable Type's Templates page
  • the Language element is generated from the default language for date display set in Movable Type
  • the hasFormat term is generated from the blog's XML feed URL as specified on Movable Type's Templates page
  • the Rights element contains a message with the year in which the last blog entry was published; the message should be edited to contain more specific information about the copyright status of the blog
  • the Creator element is commented out as it cannot adequately be generated for pages containing entries by multiple authors. If all blog entries are written by the same author, remove the two lines above and below the line with the Creator meta tag

No TrackBacks

TrackBack URL: http://homepage.univie.ac.at/horst.prillinger/cgi-bin/mt/mt-tb.cgi/308

5 Comments

Note: Movable Type does not provide a tag for the blog owner's or main administrator's name, so the value for "DC.publisher" must be filled in manually.

Not quite true.
There may be no built-in concept of this "owner" as an entirely separate blog config field for example, but there doesn't really need to be, unless there are further requirements here I may not be seeing. You can easily create it yourself from existing parts.

If the person is already in the system, the Authors tag can be filtered by role, and the default roles in the system include "Blog Administrator" and "Webmaster." You'll have to compare to decide which may be most appropriate for your case.
If the particulars of the role you're looking for are somehow different, you're still able to just create a new one of course, assign it to whoever's appropriate, and then filter for that.

You should also take note of the need_entry attribute on the template tag, since the admin/owner for the blog may not necessarily be an "author" in the literal sense.

Ah, you're right. I should've seen that coming.
With that in mind, though, I'd still propose a different change. You should take those higher-level elements like publisher and really anything that isn't entirely specific to a context(eg. current entry, this particular index template) and move that into a template module so you're only managing it in one spot.
Going a step further, for larger publishers managing multiple blogs, the module should be global rather than attached to any single blog. This would let you take advantage of some "inheritance" features of the mt:Include tag when pulling those shared elements in.

Some of us who work with MT have been pushing for custom fields to be definable for any given object for a while, like blogs, comments, etc. I'd encourage you to chime in with your own reasons if you haven't yet, to add another use case.

Leave a comment