Need some help with your project? Contact me

Adding Facebook Open Graph tags to your Drupal site

Please keep in mind that the Metatag modules provides tags for Open Graph. So I recommend using this module if you don't have some specific logic you need to implement.

In this article we are going to look at implementing the Facebook Open Graph (OG) tags on a Drupal 7 site. It involves a bit of coding but nothing too major so bear with me. All the code we are going to write goes into the theme's template.php file so no need to to create a module for it. And if your theme does not yet have this file, go ahead and create it.

The purpose of this article is to demonstrate doing this in code (because its fun and you might need it depending on the logic you need to perform). Alternatively, of course, you can use the Metatag module for this.

Why use Open Graph tags?

I'm sure by now you know that people share pages on Facebook and you want your site to be shared as much as possible. You also know that a little teaser information is made available on Facebook when you share these pages (title, image, short description).

But have you ever noticed that with some sites, when you share pages on Facebook, or like/recommend them, some random, unintented image gets used in this teaser. Or the description is not correct, or even the title is not right. Facebook is quite good at picking the right elements to show there but sometimes it doesn't manage by default. And you can't expect the random user who shares your page to make adjustments to the text or title. So what do you do? You use Open Graph meta tags.

What are the Open Graph meta tags?

These are simple <meta> tags that you put in the head of your site to specify which elements should be used by Facebook for various purposes. For instance, you specify a link to an image and then Facebook knows exactly which image to use when building the teasers. The same goes with the title, description and many others.

The tag is quite simply structured. It contains a property attribute in which you specify what this tag is for and a content attribute where you specify what should be used for this property. Let's see an example for the title:

<meta property="og:title" content="This is the article title" />

Simple. You'll also notice that the property attribute value is preceeded by og:. This stands for Open Graph and Facebook will recognize it as such. Here are some examples for other more common OG tags:

<meta property="og:url" content="http://webomelette.com/article-url" />
<meta property="og:site_name" content="Web Omelette" />
<meta property="og:type" content="blog" />

The first one is the canonical URL for the page, the second is the site title and the third is the type of site.

But how do we add them to Drupal?

I wrote a while back an article on this site in which I looked at how you can add your own custom tags into the <head> of the site. And there we learned that we use the drupal_add_html_head() function inside of a preprocess one to achieve this.

So let's say that our Article nodes don't show up properly in the Facebook teasers and we would like to specify OG tags for the title, image and description. We will do this in the theme's template.php file inside of the template_preprocess_node() function:

function theme_name_preprocess_node(&$vars) {

}

Inside this function we get access to the node information being loaded and we can test to make sure we are adding our OG tags only to the pages that load these nodes:

// If the node is of type "article", add the OG tags
if ($vars['type'] == 'article') {
  // Inside this conditional, we define and add our OG tags
}

First, let's create the title tag, the simplest of them all. It will be represented by the node title:

$og_title = array(
  '#tag' => 'meta',
  '#attributes' => array(
    'property' => 'og:title',
    'content' => $vars['title'],
  ),
);

drupal_add_html_head($og_title, 'og_title');

If you remember from the other article, this is how we create a new meta tag in the site header. We define a renderable array that describes the tag (type and attributes) and we use the drupal_add_html_head() function to set it. Simple. Now if you clear the cache and go to an article page you'll notice in its source a new tag:

<meta property="og:title" content="The title of the article" />

This was simple. Let's see how we can extract the image URL and specify it inside a new tag for the image Facebook will use:

$img = field_get_items('node', $vars['node'], 'field_image');
$img_url = file_create_url($img[0]['uri']);

$og_image = array(
  '#tag' => 'meta',
  '#attributes' => array(
    'property' => 'og:image',
    'content' => $img_url,
  ),
);

drupal_add_html_head($og_image, 'og_image');

So what happens here? First, we use the field_get_items() function to retrieve the field called field_image from the loaded node. This will return an array of one or more images (depending on how the field is set up and how many images are in it).

Next, we use the image file URI inside the file_create_url() function to turn it into an absolute URL. Then, just like above, we create the renderable array with the og:image property and the image URL as the content. The result will be:

<meta property="og:image" content="http://your-site.com/sites/all/files/your-image.jpg" />

Finally, let's see how we can get a small chunk of our body field and use that as a description for Facebook:

$body_field  = field_view_field('node', $vars['node'], 'body', array('type' => 'text_plain'));

$og_description = array(
 '#tag' => 'meta',
 '#attributes' => array(
   'property' => 'og:description',
   'content' => text_summary($body_field[0]['#markup']),
 ),
);

drupal_add_html_head($og_description, 'og_description'); 

Instead of using the same function as when we retrieved the image field earlier, we use field_view_field() in this case. The reason is that it already prepares the body for output and we can specify a text format to use. We want to use plain text to avoid printing all the HTML markup that is usually found in the body field.

Next, like above, we create our renderable array. Only this time, we also use the text_summary() function to trim the text down to a reasonable default of 600 words (the defaul teaser length on the site). If you want to specify a different length, you could pass it as the third argument, like so:

text_summary($body_field[0]['#markup'], NULL, 100),

This will trim it to 100 words. One thing I noticed about this function however is that it doesn't trim nicely. It will end the chunk in the middle of the sentence even if its API says it will try to find a sensible place. For this purpose it doesn't really matter because Facebook will trim it down anyway to a shorter version.

Conclusion

So there you have it. Now you can use the Open Graph meta tags on your Drupal site to let Facebook know about your content. It's a handy social helper that can greatly improve your social presence by making your site more appealing on Facebook.

Comments

Isn't better to use the core RDF API instead of manually rebuilding the "<> @property @content" triple in the hook_preprocess_page ?

https://api.drupal.org/api/drupal/modules!rdf!rdf.module/group/rdf/7

Why not use https://drupal.org/project/metatag

No coding and you can use the same functionality.

I haven't tried it but sounds like it can definitely be an option. However, doesn't hurt to know there are multiple ways of doing things :)

Thanks!

Metatag only add tag, so if you already has same tag then you will have duplicate tags. This article very nice, it will open your to use hook_html_head_alter() also.

Will this work in preprocess_page to set images for frontpage, user profile pages and view pages???

Wah, this is tutorial drupal very nice. I will practice this it. salam drupaler

Great Thanks for this very nice tutorial; well explained. thanks you!

Good tutorial, Thanks :)

Is this for D7? D6? D8? Or doesn't it matter?

D7. Thanks for pointing out the omission. I updated the article to include this.

Great tutorial, Thanks a lot

Add new comment

You can post comments in Markdown and basic HTML tags.
For code blocks, wrap your code within '~~~'. For example:
~~~
$var = 'my variable';
~~~