diff --git a/README.txt b/README.txt
index 861d863..e52d5f5 100644
--- a/README.txt
+++ b/README.txt
@@ -22,6 +22,9 @@ The primary features include:
 * The Dublin Core meta tag schema may be added by enabling the "Extra meta
   tags" module.
 
+* The Open Graph Protocol meta tags, as used by Facebook, may be added by
+  enabling the "Open Graph meta tags" module.
+
 * A pluggable system allow the inclusion of new meta tags in addition to the
   ones provided by this module.
 
diff --git a/nodewords_og/includes/nodewords_og.nodewords.tags.inc b/nodewords_og/includes/nodewords_og.nodewords.tags.inc
new file mode 100644
index 0000000..10a4cfe
--- /dev/null
+++ b/nodewords_og/includes/nodewords_og.nodewords.tags.inc
@@ -0,0 +1,322 @@
+<?php
+/**
+ * @file
+ * Metatag hook implementations for the Open Graph Protocol.
+ */
+
+function nodewords_og_form_default(&$form, &$content, $name, $elemtype = 'textfield') {
+  $form[$name] = array(
+    '#tree' => TRUE,
+  );
+
+  $form[$name]['value'] = array(
+    '#type' => 'textfield',
+    '#title' => nodewords_og_get_tag_label($name),
+    '#default_value' => empty($content['value']) ? '' : $content['value'],
+    '#description' => nodewords_og_get_tag_description($name),
+  );
+
+  if ($elemtype == 'textfield') {
+    $form[$name]['value']['#maxlength'] = variable_get('nodewords_max_size', 350);
+  }
+}
+
+function nodewords_og_get_tag_label($name) {
+  $tags = nodewords_og_nodewords_tags_info();
+  return (isset($tags[$name]['label']) ? $tags[$name]['label'] : t('Unknown tag: @name', array('@name' => $name)));
+}
+
+function nodewords_og_get_tag_description($name) {
+  $tags = nodewords_og_nodewords_tags_info();
+  return (isset($tags[$name]['description']) ? $tags[$name]['description'] : '');
+}
+
+function nodewords_og_og_title_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:title');
+}
+
+function nodewords_og_og_title_prepare(&$tags, $content, $options)    {
+  if (!empty($content['value'])) {
+    $tags['og:title'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_type_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:type');
+}
+
+function nodewords_og_og_type_prepare(&$tags, $content, $options)    {
+  if (!empty($content['value'])) {
+    $tags['og:type'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_image_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:image');
+
+  $form['og:image']['value'] += array(
+    '#element_validate' => array('nodewords_validate_element'),
+    '#validate_args' => array(
+      'module' => 'nodewords_og',
+      'callback' => 'nodewords_og_og_image_form_validate',
+    ),
+  );
+}
+
+function nodewords_og_og_image_form_validate($element, &$form_state) {
+  if (!empty($element['#value'])) {
+    $canonical_url = trim($element['#value'], '/');
+
+    if (!empty($canonical_url) && !valid_url(drupal_urlencode($canonical_url))) {
+      form_error($element, t('Image URL must be a relative URL.'));
+    }
+  }
+}
+
+function nodewords_og_og_image_prepare(&$tags, $content, $options)  {
+  if (!empty($content['value'])) {
+    $tags['og:image'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_url_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:url');
+
+  $form['og:url']['value'] += array(
+    '#element_validate' => array('nodewords_validate_element'),
+    '#validate_args' => array(
+      'module' => 'nodewords_basic',
+      'callback' => 'nodewords_basic_canonical_form_validate',
+    ),
+  );
+}
+
+function nodewords_og_og_url_prepare(&$tags, $content, $options)    {
+  if (!empty($content['value'])) {
+    $tags['og:url'] = check_url(
+      nodewords_url(
+        trim($content['value']), $options
+      )
+    );
+  }
+}
+
+function nodewords_og_og_site_name_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:site_name');
+}
+
+function nodewords_og_og_site_name_prepare(&$tags, $content, $options)    {
+  if (!empty($content['value'])) {
+    $tags['og:site_name'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_description_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:description', 'textarea');
+
+  $form['og:description']['value'] += array(
+    '#cols' => 60,
+    '#rows' => 6,
+    '#wysiwyg' => FALSE,
+  );
+}
+
+function nodewords_og_og_description_prepare(&$tags, $content, $options)    {
+  if (!empty($content['value'])) {
+    $tags['og:description'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_email_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:email');
+}
+
+function nodewords_og_og_email_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:email'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_phone_number_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:phone_number');
+}
+
+function nodewords_og_og_phone_number_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:phone_number'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_fax_number_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:fax_number');
+}
+
+function nodewords_og_og_fax_number_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:fax_number'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_latitude_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:latitude');
+}
+
+function nodewords_og_og_latitude_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:latitude'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_longitude_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:longitude');
+}
+
+function nodewords_og_og_longitude_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:longitude'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_street_address_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:street-address');
+}
+
+function nodewords_og_og_street_address_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:street-address'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_locality_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:locality');
+}
+
+function nodewords_og_og_locality_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:locality'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_region_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:region');
+}
+
+function nodewords_og_og_region_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:region'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_postal_code_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:postal-code');
+}
+
+function nodewords_og_og_postal_code_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:postal-code'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_country_name_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:country-name');
+}
+
+function nodewords_og_og_country_name_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:country-name'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_video_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:video');
+
+  $form['og:video']['value'] += array(
+    '#element_validate' => array('nodewords_validate_element'),
+    '#validate_args' => array(
+      'module' => 'nodewords_og',
+      'callback' => 'nodewords_og_og_video_form_validate',
+    ),
+  );
+}
+
+function nodewords_og_og_video_form_validate($element, &$form_state) {
+  if (!empty($element['#value'])) {
+    $url = trim($element['#value'], '/');
+
+    if (!empty($url) && !valid_url($canonical_url)) {
+      form_error($element, t('Video URL must be a valid URL.'));
+    }
+  }
+}
+
+function nodewords_og_og_video_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:video'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_video_width_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:video:width');
+}
+
+function nodewords_og_og_video_width_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:video:width'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_video_height_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:video:height');
+}
+
+function nodewords_og_og_video_height_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:video:height'] = $content['value'];
+  }
+}
+
+function nodewords_og_og_video_type_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'og:video:type');
+}
+
+function nodewords_og_og_video_type_prepare(&$tags, $content, $options) {
+  if (!empty($content['value'])) {
+    $tags['og:video:type'] = $content['value'];
+  }
+}
+
+function nodewords_og_fb_admins_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'fb:admins');
+
+  $form['fb:admins']['value'] += array(
+    '#validate_args' => array(
+      'module' => 'nodewords_og',
+      'callback' => 'nodewords_og_fb_admins_form_validate',
+    ),
+  );
+}
+
+/**
+ * Validate the values passed as facebook user IDs.
+ */
+function nodewords_og_fb_admins_form_validate($element, &$form_state) {
+  if (!preg_match('/^($|([0-9]+)(,[0-9])*$)/', $element['#value'])) {
+    form_error($element, t('The Facebook admins value must be a comma separated list of Facebook user IDs.'));
+  }
+}
+
+function nodewords_og_fb_admins_prepare(&$tags, $content, $options)  {
+  if (!empty($content['value'])) {
+    $tags['fb:admins'] = $content['value'];
+  }
+}
+
+function nodewords_og_fb_app_id_form(&$form, $content, $options) {
+  nodewords_og_form_default($form, $content, 'fb:app_id');
+}
+
+function nodewords_og_fb_app_id_prepare(&$tags, $content, $options)    {
+  if (!empty($content['value'])) {
+    $tags['fb:app_id'] = $content['value'];
+  }
+}
diff --git a/nodewords_og/nodewords_og.info b/nodewords_og/nodewords_og.info
new file mode 100644
index 0000000..bc8b762
--- /dev/null
+++ b/nodewords_og/nodewords_og.info
@@ -0,0 +1,6 @@
+name = Open Graph meta tags
+description = Define Open Graph meta tags for Drupal pages.
+dependencies[] = nodewords
+dependencies[] = nodewords_basic
+core = 6.x
+package = Meta tags
diff --git a/nodewords_og/nodewords_og.module b/nodewords_og/nodewords_og.module
new file mode 100644
index 0000000..03eb4a7
--- /dev/null
+++ b/nodewords_og/nodewords_og.module
@@ -0,0 +1,147 @@
+<?php
+
+/**
+ * Implements hook_nodewords_api().
+ */
+function nodewords_og_nodewords_api() {
+  return array(
+    'version' => '1.12'
+  );
+}
+
+/**
+ * Implementation of hook_nodewords_tags_info()
+ * @return void
+ */
+function nodewords_og_nodewords_tags_info()  {
+  $cached = cache_get('nodewords_og:tags');
+  if (!$cached || empty($cache->data) || time() > $cache->expire) {
+    $tagsrc = nodewords_og_get_tags();
+
+    $tags = array();
+    foreach ($tagsrc as $key => $value) {
+      $callback = 'nodewords_og_'.strtr($key, ':-', '__');
+      $label = t('Open Graph: !labelsuffix', array('!labelsuffix' => (!empty($value['labelsuffix']) ? $value['labelsuffix'] : $key)));
+      $tags[$key] = $value + array(
+        'callback' => $callback,
+        'context' => array(
+          'allowed' => array(
+            NODEWORDS_TYPE_DEFAULT,
+            NODEWORDS_TYPE_NODE,
+            NODEWORDS_TYPE_PAGE
+          ),
+        ),
+        'label' => $label,
+        'templates' => array(
+          'head' => array(
+            $key => NODEWORDS_META_PROPERTY,
+          ),
+        ),
+        'tokens' => TRUE,
+      );
+    }
+
+    cache_set('nodewords_og:tags', $tags);
+  }
+  else {
+    $tags = $cached->data;
+  }
+
+  require_once dirname(__FILE__) . '/includes/nodewords_og.nodewords.tags.inc';
+  return $tags;
+}
+
+function nodewords_og_get_tags() {
+  $tags = array(
+    'og:title' => array(
+      'labelsuffix' => t('Title'),
+      'description' => t('The title of the object as it should appear in the graph.'),
+    ),
+    'og:type' => array(
+      'labelsuffix' => t('Type'),
+      'description' => t('The type of your object e.g. movie. <a href="@url" target="_blank">See the list of supported types</a>.', array('@url' => 'https://developers.facebook.com/docs/opengraph/#types')),
+    ),
+    'og:image' => array(
+      'labelsuffix' => t('Image'),
+      'description' => t('An image URL which should represent your object within the graph. The image must be at least 50px by 50px and have a max aspect ratio of 3:1.'),
+    ),
+    'og:url' => array(
+      'labelsuffix' => t('URL'),
+      'description' => t("The canonical URL of your object that will be used as it's permanent ID in the graph. Use <code>&lt;front&gt;</code> for the front page."),
+    ),
+    'og:site_name' => array(
+      'labelsuffix' => t('SiteName'),
+      'description' => t('A human readable name for your site, e.g. "IMDB".'),
+    ),
+    'og:description' => array(
+      'labelsuffix' => t('Description'),
+      'description' => t('A one to two sentence description of your page.'),
+    ),
+    'og:email' => array(
+      'labelsuffix' => t('Email'),
+      'description' => t('Should only be used when appropriate.'),
+    ),
+    'og:phone_number' => array(
+      'labelsuffix' => t('Phone Number'),
+      'description' => t('Should only be used when appropriate.'),
+    ),
+    'og:fax_number' => array(
+      'labelsuffix' => t('Fax Number'),
+      'description' => t('Should only be used when appropriate.'),
+    ),
+    'og:latitude' => array(
+      'labelsuffix' => t('Latitude'),
+      'description' => t('Latitude of the location this page refers to.'),
+    ),
+    'og:longitude' => array(
+      'labelsuffix' => t('Longitude'),
+      'description' => t('Longitude of the location this page refers to.'),
+    ),
+    'og:street-address' => array(
+      'labelsuffix' => t('Street Address'),
+      'description' => t('Street address of the location this page refers to.'),
+    ),
+    'og:locality' => array(
+      'labelsuffix' => t('Locality'),
+      'description' => t('Locality, city or suburb of the location this page refers to.'),
+    ),
+    'og:region' => array(
+      'labelsuffix' => t('Region'),
+      'description' => t('Region or state of the location this page refers to.'),
+    ),
+    'og:postal-code' => array(
+      'labelsuffix' => t('Postal Code'),
+      'description' => t('Post code or zip of the location this page refers to.'),
+    ),
+    'og:country-name' => array(
+      'labelsuffix' => t('Country Name'),
+      'description' => t('Country name of the location this page refers to.'),
+    ),
+    'og:video' => array(
+      'labelsuffix' => t('Video URL'),
+      'description' => t('URL of a video. Facebook only supports SWF (Shockwave Flash) format videos.'),
+    ),
+    'og:video:width' => array(
+      'labelsuffix' => t('Video Width'),
+      'description' => t('Width of the video in pixels, e.g 640.'),
+    ),
+    'og:video:height' => array(
+      'labelsuffix' => t('Video Height'),
+      'description' => t('Height of the video in pixels, e.g 385.'),
+    ),
+    'og:video:type' => array(
+      'labelsuffix' => t('Video Type'),
+      'description' => t('Content type of the video, e.g "application/x-shockwave-flash"'),
+    ),
+    'fb:admins' => array(
+      'label' => t('Facebook: Admins'),
+      'description' => t('A comma-separated list of either Facebook user IDs that administer this page.'),
+    ),
+    'fb:app_id' => array(
+      'label' => t('Facebook: App ID'),
+      'description' => t('A comma-separated list of Facebook Platform application IDs that administer this page.'),
+    ),
+  );
+
+  return $tags;
+}
