Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough
Sep 21 2014
Sep 21

When the search engine correctly reflects how important you think different parts of the content and metadata are, the simpler it is for editors to understand how it is functioning.
Then the search engine ceases to be a mysterious black box that delivers the result in an arbitrary manner. It becomes comprehensible as to why certain search hits land higher up and what they should do to influence the search hit presentation positively.

Make your content machine-readable

To enable the search engine to evaluate what part of the content is more important than another, it must be able to differentiate the various parts. Always apply language correct elements like h1 – h6, p, q etc, with comprehensive language class attributes.

Always begin with how the external search engines (mainly Google) interpret your data and let the internal search engine adapt correspondingly. This gives editors the opportunity to optimize the content both for Google and the internal search engine. Optimization for Google and for the internal search engine are effectively one and the same concept and when correctly done it is valuable for both.

Metadata is the weapon to beat Google

Google has the advantage of being able to interpret link deviations and to learn from a multiplicity of searches when ranking content, whereas the internal search engine has the advantage of using metadata which fits perfectly. You should capitalize on this.

Example of metadata for web – och intranet Keywords, best bets, description, personnel with content responsibility, type of site, organization/unit, subject and category etc. Example of metadata for e-commerce Storage status, campaign, discount, price, sales volume, product category etc.

The metadata may be used by your internal search engine to search in or to filter the search hit-list, the so-called facets. Imagination alone limits what metadata you may use and what functions you may build out from: contextual or personalized search are two examples.

But remember, that even metadata should be managed and that excessive metadata becomes slower to compile and to keep the content updated. Only use metadata that corresponds to a real user case scenario of importance for your business.

Taxonomy, ontology and semantic search

Sometimes you may want to establish a so-called taxonomi for the metadata attributes which define the elements within the organisation. A taxonomy aims to avoid calling one element by different names, which may create confusion and cause content to disappear. But remember that your users may not always understand your meaning or your ideas. By searches, it is your function to assist users as far as possible.

Power of keywords/best bets

Keywords or best bets are efficient for setting up site priorities for certain searches in the search hit list. Also a frequent way to apply keywords is to present them to the user so that he may click on a keyword and pull up all related content. This gives the user a quick overview on a subject. Another way is to let the user filter the search hit list on keywords. When showing keywords to the user, you would probably keep a certain flexibility in what keywords are presented. At the same time, you may want users to achieve good hits even when they are searching on similar words or pure synonyms for keywords. A good solution is to make it possible by adding synonyms to the keyword index.

It will be advisable to limit what keywords editors add, to enable them to associate synonyms in the keyword index in the search engine. Then, users searching on synonyms, make the right hit in the search- word list without editors having to restrict their own flexibility regarding what keywords are shown to users.

Good titles and descriptions

How hits are shown in the search hit list is decisive to the user’s reaction, that is, whether he will click on the word or not. When this does not distinctly signal that this search hit is going to answer the user’s question, he would not click even if the response is actually there. We recommend that you show different titles on the page and in the search hit list. The reason being that users understand the context of the page, whereas on the search hit list, it is completely independent without any context.

Different titles for pages and hitlists

We recommend that your content personnel are able to choose between creating a special title for the search hit list or the title of the page. Since <title> is used by Google, a domain or name of the whole web site is usually added to make it clear, in Google, where the page belongs. It may therefore be advisable to have addition metadata in the head line of the internal search engine.


  • For Google result page: <title>Page title | Page domain </title>
  • For site search result page: <meta name=”title” content=“Page title for internal search engine”>
  • For actual page: <h1>Page title on page</h1>

    Sometimes you want to show a particular description of a page when it is shown in the search hit list.

Google uses metadata description if present when it is displayed on Google`s search hit list. Even for the internal search hit list, it may be advisable to give a special description. We recommend that for all- embracing pages containing various further links, it is also useful to have a special description and this is even when pages contain little text but perhaps mostly tables, pictures or other data that do not display well in the search hit list.

Nov 12 2012
Nov 12

How to Hide Metadata From Showing on a Published Drupal Page

Drupal's FieldAPI gives site builders a wide variety of ways to attach custom data to content types and other entities. Sometimes, though, you're adding metadata -- stuff that shouldn't be displayed directly when a piece of content is shown, but can affect the content's relationships with other posts, or its overall appearance. The easiest way to do this yourself is to hide the field in question, then sneak extra CSS classes or IDs onto the node itself based on the field's value. A new module, Field Formatter CSS Class, automates that process and makes turning simple fields into extra CSS classes a no-brainer.

Screenshot of administration screen

As one might guess from its name, the module adds a new FieldAPI Formatter type -- "CSS Class." When selected, the field in question doesn't appear in the visible content of the node or entity in question. Instead, the field's value is turned into a CSS class and added to the entity's wrapper div. This is most useful when combined with a List field or a Text field with a small number of allowed values. When combined with some simple CSS rules in a custom theme (or added via a module like CSS Injector), this allows content editors to make easy choices that affect a node's visual appearance without hacking complex markup or embedded CSS rules into the content itself.

Screenshot of resulting change to site

Field Formatter CSS Class is also smart enough to sanitize the CSS classes that it adds -- even if you allow editors to enter custom text in a field, dangerous HTML attributes and CSS tricks will be scrubbed out. If you need a quick and simple way for editors to pass information about a node or other entity to the theme, Field Formatter CSS Class is a solution worth checking out!

Oct 22 2012
Oct 22

Anyone who's ever talked shop about Search Engine Optimization has heard of meta tags. Those bits of extra data jammed in an HTML document's HEAD section provide search engines, browsers, and other software with important information about a document's contents, related links and media, and more. There are quite a few ways to jam meta tags into a Drupal site, and there are even APIs to set the contents of a page's meta tags yourself, if you're a module developer. Thankfully, you don't have to sling code thanks to the excellent Meta Tags module.

Screenshot of administration screen

Maintained by prolific Drupal developer Dave Reid, Meta Tags provides a centralized configuration screen where common meta tags can be edited sitewide, for specific types of pages, and even for pages belonging to specific entity bundles. Need one set of tags for photo galleries and another for user profile pages? No sweat. Meta Tags uses standard Drupal tokens to build the contents of its tags, and the configuration options themselves can be exported and saved in Feature modules for easier deployment.

Screenshot of advanced options

Third-party modules can add new meta tags to the mix, and add new types of URL paths that need to receive custom tags. The Panels Meta Tags and Views Meta Tags projects, for example, allow each view and panel to have custom, token-driven meta tags just like nodes, users, and so on. Meta Tags is already a popular solution to the thorny problem of sitewide meta tag customization -- check it out if you need more than Drupal core's auto-generated ones.

Apr 24 2010
Apr 24
Share this

MDX 2010 FTW!

With a Drupal Beta planned for May 21, the time is coming for a Media Beta as well! Before we can do that, however, there are a few loose ends to tie up. I've identified two critical pieces for a happy Developer's eXperience (DX) before I'll be happy doing that. There are certainly more: see the Media issue queue for more.

MetaData Handling

The Media module creates Media entity objects, which are fieldable. That means we can already attach any fields or taxonomy to any media object, which goes a long way towards handling metadata. However, Media metadata needs are variable and complex. For instance, a field might be fine for adding a taxonomy vocabulary for Video genre or Bird species, but you would need something better if you want to automatically add video duration, YouTube categories, or grab a music file's getID3 data. Basically, we need a larger discussion of what's necessary, what's possible, and how we get there. See this Media metadata issue for more background.

Display Formatting

Currently, we're using the Styles module to power display formatting. We may or may not continue using that. In any case, we'll need to ensure the formatters more closely follow Media Types, and we'll need to offer a pluggable UI for changing formatter style presets, similar to Image Styles (Imagecache in core, for those not yet familiar).

Media DX Summit 2010?

I'd love to lock up some fellow developers for a couple of days in a room to bang on these ideas. At the same time, my partner Gwen is due on May 22 for our second child, so firstly, I can't really travel any time in the foreseeable future, and secondly, even if we had a summit here in Harrisburg, it would either have to be like this week, or in mid-summer. Considering the deadlines involved for this, we need to get cranking. Thus, the summit I would love to see happen will probably either have to happen remotely, or perhaps without my involvement. :(

Anything Else?

Are there any other issues you would suggest to be critical beta-blockers? Do you have any thoughts to add to the issues I've suggested? Please add to this thread!

Aaron Winborn

(Cross-posted at g.d.o.)

Apr 26 2009
Apr 26

Finally upgraded this site from Drupal 5 to 6. There's nothing special in that, it all went very smoothly and I just changed the theme again. But on the way I thought I'd get a bit of RDFa into the site - so the most interesting stuff on this, and other pages, you probably can't see.

RDFa has always made a huge amount of sense to me, and there's a push to get it into core for 7, which is brilliant, so testing a bit more in here seemed a sensible thing.

Central to implementing a bit more RDF of any sort into Drupal at the moment is the rdf module. Here it's making some nice changes to the header, and adding the name spaces. It's easy to add more that the default too - I certainly wanted Creative Commons and Web of Trust that weren't there already, for example.

Also pretty important, and I guess the way it's going to go with fields in core, is RDF CCK module. This is a lovely module, which when installed with its dependencies, will auto suggest as you type mappings from the imported vocabularies (excellent stuff :) The module's at work here on the profile nodes. However as the rest of the site is based on pretty simple nodes (title, body, with a user and taxonomy) and comments (same but without taxonomy) and no extra fields most of the rest of the RDFa magic's in the template.php and a bit in the appropriate *.tpl.php for now.


First off with nodes just to make sure the subject is usually set I changed the first <div> in the node.tpl.php to include an about="/path/to/node":

<div about="<?php print $node_url; ?>" id="node-<?php print $node->nid; ?>" class="<?php print $classes; ?>"><div class="node-inner">

This means even when it's on a page with multiple nodes the content inside will have correct subject

Next I wanted the dc:subject. I'll get round to integrating with some controlled topic vocabulary, but for now it's referenced on my site. Anyway for this in the THEMENAME_preprocess_node it's just a case of redoing the terms variable:

  $terms = taxonomy_link('taxonomy terms', $vars['node']);
  foreach($terms as &$term) {
    $term['attributes']['property'] = 'dc:subject';
  $vars['terms'] = theme('links', $terms);

Next up the node author. For this I've overridden the theme_username to accept a $options for the link. It's not always the case that the username is an author obviously, so this you choose on pulling the display.

-function theme_username($object) {
+function THEMENAME_username($object, $options = array()) {
   if ($object->uid && $object->name) {
     // Shorten the name when it is too long or it will break many tables.
@@ -8,9 +8,10 @@
     else {
       $name = $object->name;
-    if (user_access('access user profiles')) {
-      $output = l($name, 'user/'. $object->uid, array('attributes' => array('title' => t('View user profile.'))));
+    $profile = content_profile_load('profile', $object->uid);
+    if ($profile && node_access('view', $profile)) {
+      $options['attributes']['title'] = t('View @title', array('@title' => $profile->title));
+      $output = l($name, 'node/'. $profile->nid, $options);
     else {
       $output = check_plain($name);

This needs a bit of thinking about for those occasions when a non-registered, anonymous, user is allowed post and enter their name and url, but it should be as easy to do the same thing on these occasions too if it were so desired (not sure if it makes sense with 'nofollow'?). After making the theme override it's then simple enough to call from the THEMENAME_preprocess_node as:

  // node author link
  $vars['author'] = theme('username', user_load(array('uid' => $vars['node']->uid)), array('attributes' => array('property' => 'dc:creator cc:attributionName', 'rel' => 'foaf:maker sioc:has_creator cc:attributionURL')));

There are lots of predicates here, for most it's clear if their object should be the URL for the user or the literal value of the name string. I'm not 100% sure over the dc:creator though, it's going to the plain text name which seemed to be the best practice suggestion when used with so many others. But, hey, I might be wrong, in which case it wants to be in 'rel'.

I'll deal with the created, updated, stuff below with the comments, because I did a bit of user display side stuff with THEME_node_submitted that complicates it more than I have with THEME_comment_submitted. The logic works the same in both.

Now this all works, except of course that if the nodes are show on the page itself the title isn't displayed by the node.tpl.php but by the page.tpl.php.


I'm guessing there's a whole lot more that can be done here for site wide metadata, but so far I've just gone for the general licence, which is actually in a block, and the title. The line for the title in the page.tpl.php is as simple as:

           <?php if ($title): ?>
              <?php print $title; ?>
            <?php endif; ?>

With the empty about it's related to the page itself, and with pages with other objects on them they will only be related if their about object is the same.


The object for this can just be the url fragment, so I've make this available as $comment_url in THEMENAME_preprocess_comment and then popped it in the <div> just as above.

The title and the user are much as the node, as is the date which I'll describe here. The wish is to add the dcterms:created (and for some nodes the dcterms:modified) both of which best have an object value as a W3C datetime. So for the comment date I've just made a THEMENAME_comment_submitted theme function overrride.

function THEMENAME_comment_submitted($comment) {
  return t('Submitted by !username on !datetime.',
      # note the additional theme() param here for THEMENAME_username() as above
      '!username' => theme('username', $comment, array('attributes' => array('property' => 'dc:creator cc:attributionName', 'rel' => 'foaf:maker sioc:has_creator cc:attributionURL'))),
      '!datetime' => '<span property="dcterms:created" content="'. date('c', $comment->timestamp) .'">'. format_date($comment->timestamp) .'</span>',

It's worth noting though the date 'c' switch is PHP 5 only, and it's apparently full ISO 8601.

The other difference for comments here is that SIOC can describe the relationships between them nicely. Having toyed around with various ideas of where to put sioc:has_reply and sioc:reply_of I was struggling to find anything better than an otherwise empty element, or making an 'in reply to...' link to pop into (and CSS display: none) the submitted information. I'm sure there's a better way, but for now:

  $parent_path = 'node/'. $vars['comment']->nid;
  $parent_options['fragment'] = $vars['comment']->pid ? 'comment-'. $vars['comment']->pid : '';
  $parent_options['attributes']['rel'] = "sioc:reply_of";
  $vars['parent_link'] = l(t('in reply to...'), $parent_path, $parent_options);

Another one that's bothering me is I want to identify what the content is, but encoded content is hard work, from what I gather using RSS 1.0 content is going to be the way, but was just a start.


Throughout CURIE used from:-

 @prefix dc: <http://purl.org/dc/elements/1.1/>.
 @prefix dcterms: <http://purl.org/dc/terms/>.
 @prefix sioc: <http://rdfs.org/sioc/ns#>.
 @prefix foaf: <http://xmlns.com/foaf/0.1/">
 @prefix cc: <http://creativecommons.org/ns#>.
 @prefix wot: <http://xmlns.com/wot/0.1/>.

Mar 25 2008
Mar 25

A first part of many about feeds.

The Transmission network, a group for sharing videos for social change, have been working on developing a free metadata standard for video interchange. Before this what there has been is tied to Yahoo! MRSS which one wouldn't call proactive in working with the community for growth and development of their standard.

So the Transmission folks have got some backing and come up with an XML standard for video metadata that in the docs (and in political free background) is linked to Atom. There's a working sort of beta version 0.9 on it's way to becoming a real 1.0 release.

I've implemented it for the video module for Drupal. An example atom feed with plenty of metadata. This requires the patch I committed to the Atom module to allow enclosures as well as additional namespaces.

The fact that no one has previously pushed a metadata standard for Atom, or moved the Yahoo! RSS namespace beyond it's stale position, is interesting. People who actually make and screen videos are crying out for this metadata. They will quickly list off what they want to be made available.

Yet, despite the user demand for metadata, I challenge you to find an implementation of MRSS that includes all of the metadata that it could make available. I really want to find them too, so let me know! (I now exclude Drupal sites with a video module after 16 March because my patch to make proper feeds with the metadata that is available was committed).

It's a shame too. Because the demand is already there from the video community end users. The MRSS standard doesn't seem to be too bad either, it fits a lot of the present videocasting requirements - there is much I feel the Transmission standard could learn from it there. However unlike the Transmission standard the Yahoo! one doesn't meet all the requirements of the present day video creator or user. Yet even with the rise of demand making the Yahoo! MRSS outline an XML standard or developing it with the community seems not to be happening, at the moment.

All that is happening with feeds is CMS developers are starting to develop feeds that actually include enclosures. This is essential as the interest in videocasting becomes greater - miro must have a lot to be praised for here. But the information and formats the video community really want and need is not there. If you actually look at the feeds produced quite often they don't even display how big the file is!

Part of the problem has to be that video related data is pretty complicated and there is quite a bit of it. How long has it taken me to get used to all the different codecs, framerates, and so forth - I'm still getting used to it?!

But that's no excuse. Why aren't Content Management Systems storing this information with videos if it is made available? Why aren't they discovering it if it's not available? Even your really non-demanding user wants to know the if 'the quality is any good' and if 'they can play this video'. It's not rocket science to do either... but I suspect that leads me to a future post...

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web