Tabs on Facebook Pages

Last updated on
30 April 2025

This page still talks about FBML tabs. The latest fb_tab.module supports only iframe tabs. The techniques that follow still apply.

Profile tabs are a tricky and unwieldy part of the Facebook platform. They are limited both in their dimensions (currently, 520px wide), and in that they are strict FBML. Unlike iframe canvas pages (XFBML), profile tabs cannot contain regular javascript and have a number of other restrictions.

Facebook has already removed profile tabs from user pages. Currently, they can still be added to regular pages (i.e. a Fan Page or Application About Page). Facebook has deprecated FBML for canvas pages, so it's only reasonable to assume that sometime in the near future they will change how tabs work.

For these reasons, it's best to think of a tab as a landing page. All links, forms, and so on should lead users off the canvas and onto a canvas page or your website.

Bear in mind that if your application supports profile tabs, it may be added to any number of pages. It may be that every tab displays the same content (the Simple Case). Or, it could be that for each page on which your application is installed, the tab must be configured to display content unique to that page.

About FBML and Themes

Remember your tab content must be FBML which is not HTML. Drupal will produce HTML by default, but with a little prodding can produce FBML. The most flexible way to accomplish this is with an FBML theme.

Theming is a complex topic with lots of documentation elsewhere on drupal.org, so we won't go into that. And FBML is poorly documented on developers.facebook.com, but we couldn't do any better. To get started on your own FBML theme, see the example posted to drupalforfacebook.org.

The alternate way to produce FBML is with a menu callback specifically designed to produce it. Without showing all the menu code, a callback - something like this - will get around Drupal's theming and produce just FBML:

// Note that unlike regular callback which return content,
// we print content and then exit.
function my_module_fbml_callback() {
  print("<fb:title>Hello World</fb:title>");
  print("<p>I said hello.  Is anybody there?</p>");
  exit();
}

Simple Case

In the simple case, each page with the app installed displays the same content.

Required modules

  • fb_app.module
  • fb_canvas.module - because (for no good reason) Facebook requires tab URLs to be relative to a canvas URL.
  • fb_tab.module

Setup and Configuration

  • On your application remote settings, under "Facebook Integration" specify a canvas page.

  • Under admin >> build >> facebook apps, edit your application.

  • In the "profile tabs" fieldset, specify a tab name.

For "Path" you have number of options. If using an FBML theme, you could put any drupal path here. For example, "node", "node/42", or the path to a custom view you've created would all work.

If not using an FBML theme, but you defined a custom callback as described above, specify the path to your menu item in "Path".

Finally, you can build tab content by implementing hook_fb_tab. For this option, specify "fb_tab/view" as the path.

Press "Save" to submit the tab settings.

Complex Case, using hook_fb_tab()

In the complex case, the tab must be configured specifically for each page that has the app enabled. In this example we'll build a custom module which implements hook_fb_tab(). By using this, fb_tab.module will save our configuration for us, and allow only page admins to configure the page.

Required Modules

Same as above.

Setup and Configuration

Same as above. Enable an FBML theme and use "fb_tab/view" for your tab path. [[HOW DO I KNOW WHICH THEMES ARE FBML? IS GARLAND? - SW]]

When "fb_tab/view" is the path, hook_fb_tab() must be implemented. In this example, a module called eg_fb.module is implementing the hook. For your custom code, replace "eg_fb" with the name of your module.

This example uses the Organic Groups module. When our application is installed on a page, the admin will configure the tab by choosing one of groups they subscribe to. Once configured, the tab will show only content associated with that group.

/**
 * Implements hook_fb_tab().
 *
 * Here we allow the user to choose one of their organic groups.  When the tab
 * is viewed, the content of that group is displayed.
 *
 * @param $op
 *   We handle two operations.  When FB_TAB_OP_VIEW, we show the tab, or show
 *   a link to the config page if the tab has never been configured.  When
 *   FB_TAB_OP_FORM, we build the form elements needed for configuration.
 * @param $data
 *   $data['config'] will contain the settings saved from the configuration
 *   form.
 * @param $return
 *   When $op==FB_TAB_OP_VIEW, we build this datastructure with content to be
 *   rendered, via drupal_render().  When $op == FB_TAB_OP_FORM, we add form
 *   elements to this array.
 */
function eg_fb_fb_tab($op, $data, &$return) {
  if ($op == FB_TAB_OP_VIEW) {
    // fb_tab.module is asking us for the content of the tab.
    if (count($data['config'])) {
      // We have been configured, we can show a group.
      $og = node_load($data['config']['eg_fb_og']);
      og_set_group_context($og);
      drupal_set_title($og->title);
      // Show the default "river of news"
      $return['eg_fb_og'] = array(
        '#type' => 'markup',
        '#markup' => views_embed_view('og_ghp_ron', 'default', $og->nid),
      );
    }
    else {
      // We have not been configured, send user to configuration page.  Rather
      // than build a form to display here (on the Tab), we send the user to a
      // canvas page.  On a canvas page, we'll know the user's fbu (on Tab we
      // know only the page id).
      $return['eg_fb_fb_tab'] = array(
        '#type' => 'markup',
        '#markup' => t('This tab has not been configured.  <a href="!href">Click here to configure</a>.', array(
                        '!href' => fb_tab_config_url($data['profile_id']),
                      )),
        '#prefix' => '<p>',
        '#suffix' => '</p>',
      );
    }
  }
  elseif ($op == FB_TAB_OP_FORM) {
    // fb_tab.module is asking us for our custom form element.  fb_tab.module
    // will take care of saving the settings to the fb_tab table.
    // This element lets the user choose one of their organic groups.
    $return['eg_fb_og'] = array(
      '#type' => 'select',
      '#title' => t('Select a group to display in this tab'),
      '#options' => eg_group_options($GLOBALS['user']->uid),
      '#default_value' => $data['config']['eg_fb_og'],
      '#description' => t(''),
    );
  }
}

/**
 * Convenience function for a list of groups the user belongs to.
 * og.module should provide this but doesn't.
 */
function eg_group_options($uid) {
  $subs = og_get_subscriptions($uid);
  $options = array(0 => t('<none>'));
  foreach ($subs as $key => $val) {
    $options[$key] = $val['title'];
  }
  return $options;
}

Help improve this page

Page status: Not set

You can: