Twitter Pane

Almost certainly, a time will come when a client asks for a list of Tweets to be displayed on their Drupal site.

photo of Mark Davies
Tue, 2014-11-25 10:31By markd

There are a plethora of modules out there that can help provide this functionality. For example:
Amongst others..

These are great modules and will likely do what you need, if not more.  An alternative lightweight option is to write a small ctools plugin to complete the simple functionality.  

Our site building process has moved more and more towards panels, panes and display suite.  A quick, exportable and configurable solution to showing tweets on your site, if using panels and ctools can be found below.

First we need to build out a boilerplate module to tell Drupal where to find our plugins.  This code is placed into your mymodule.module file, and of course you’ll need to write a .info file but you know that already!

 * Implements hook_ctools_plugin_directory().
function mymodule_plugins_ctools_plugin_directory($owner, $plugin_type) {
  if ($owner == 'ctools' && $plugin_type == 'content_types') {
    return 'plugins/' . $plugin_type;

Next up, the nuts and bolts of our plugin.  This code is placed into your file under mymodule/plugins/content_types and that directory is based from our hook_ctools_plugin_directory hook defined above.

$plugin = array(
  'single' => FALSE,
  'title' => t('Twitter timeline'),
  'description' => t('Shows a twitter timeline with basic configuration options.'),
  'category' => t(Twitter),
  'edit form' => 'mymodule_twitter_timeline_edit_form',
  'render callback' => 'mymodule_twitter_timeline_render',
  'admin info' => 'mymodule_twitter_timeline_admin_info',
  'defaults' => array(
    'username' => 'md2',
    'tweets_to_show' => 5,
    'widget_id' => '',
    'chrome' => '',

 * 'admin info' callback for panel pane.
function mymodule_twitter_timeline_admin_info($subtype, $conf, $contexts) {
  if (!empty($conf)) {
    $block = new stdClass;
    $block->title = $conf['override_title'] ? $conf['override_title_text'] : '';
    $block->content = t('Showing @tweets_to_show tweets from <em>@@username</em>.', array(
      '@tweets_to_show' => $conf['tweets_to_show'],
      '@username' => $conf['username'],
    return $block;

 * 'Edit form' callback for the content type.
function mymodule_twitter_timeline_edit_form($form, &$form_state) {
  $conf = $form_state['conf'];

  $form['widget_id'] = array(
    '#title' => t('Twitter Widget ID'),
    '#description' => t('The widget_id/application ID from your twitter account.'),
    '#type' => 'textfield',
    '#default_value' => $conf['widget_id'],
    '#required' => TRUE,

  $form['username'] = array(
    '#title' => t('Twitter username'),
    '#description' => t('The username of the twitter account in which to pull the tweets from.'),
    '#type' => 'textfield',
    '#default_value' => $conf['username'],
    '#required' => TRUE,

  $form['tweets_to_show'] = array(
    '#title' => t('Number of tweets to show'),
    '#description' => t('Used to control the number of tweets shown on the page initially. Defaults to 5.'),
    '#type' => 'select',
    '#options' => drupal_map_assoc(range(3, 12)),
    '#default_value' => $conf['tweets_to_show'],
    '#required' => TRUE,

  $form['chrome'] = array(
    '#title' => t('Control the widget layout'),
    '#description' => t('Control the widget layout and chrome by using the data-chrome="nofooter transparent" attribute on the embed code. Use a space-separated set of the following options'),
    '#type' => 'checkboxes',
    '#options' => array(
      'noheader' => t('No header'),
      'nofooter' => t('No footer'),
      'noborders' => t('No borders'),
      'noscrollbar' => t('No scrollbar'),
      'transparent' => t('Transparent'),
    '#default_value' => $conf['chrome'],
    '#required' => FALSE,

  return $form;

 * The submit form stores the data in $conf.
function mymodule_twitter_timeline_edit_form_submit($form, &$form_state) {
  foreach (array_keys($form_state['plugin']['defaults']) as $key) {
    if (isset($form_state['values'][$key])) {
      $form_state['conf'][$key] = $form_state['values'][$key];

 * Run-time rendering of the body of the block (content type)
 * See ctools_plugin_examples for more advanced info
function mymodule_twitter_timeline_render($subtype, $conf, $panel_args, $context = NULL) {
  $block = new stdClass();

  // initial content is blank
  $block->title = '';
  $block->content = '';
  // Include twitter javascript - by linking to the external file.
  drupal_add_js('//', 'external');

  $block->content = array(
    '#type' => 'link',
    '#title' => t('Tweets by @username', array('@username' => $conf['username'])),
    '#href' => check_url('' . $conf['username']),
    '#options' => array(
      'attributes' => array(
        'class' => array('twitter-timeline'),
        'data-widget-id' => check_plain($conf['widget_id']),
        'data-chrome' => check_plain($conf['chrome']),
        'data-tweet-limit' => check_plain($conf['tweets_to_show']),
        'data-screen-name' => check_plain($conf['username']),
      'html' => FALSE,

  if (!empty($conf['chrome'])) {
    $options = array();

    foreach ($conf['chrome'] as $option => $status) {
      if ($status) {
        $options[] = $option;

    if (count($options)) {
      $block->content['#options']['attributes']['data-chrome'] = implode(' ', $options);
  return $block;

Adding a new Twitter Pane
Because we are using ctools content type plugins we get a lot of nice stuff out of the box.  The setup is configurable, held in code and allows us to have multiple instances of our box (handy if you want to show tweets from multiple accounts on one site.)

Screenshot of Twitter timeline interface in Panels.

Twitter Widget ID

This holds the application ID that you will need to query the Twitter API, simply create your application under your account and copy and paste the ID into this textfield.

Twitter Username

Pretty self explanatory, stick in whatever twitter handle you wish to display tweets for.

Number of tweets to show

Pick a number, any number.

Control of widget layout

This allows you to control the display options of the output, you can show/hide header, footer, borders, scrollbar etc.

  • noheader: Hides the timeline header. Please refer to the timeline display requirements when implementing your own header.
  • nofooter: Hides the timeline footer and Tweet box, if included.
  • noborders: Removes all borders within the widget (between Tweets, cards, around the widget.) See also: border-color.
  • noscrollbar: Crops and hides the main timeline scrollbar, if visible. Please consider that hiding standard user interface components can affect the accessibility of your website.
  • transparent: Removes the background color.

This pane snippet only touches the surface of twitter’s API and there are a lot of other client side options that can be set, some additional form elements taking user choices would be all that is needed to allow total customisation of the twitter pane.

The main thing I took away once discovering the power of custom ctools plugins is how quick they are to write along with how easily they are made configurable.  This allows them to be used for not just a simple twitter timeline, but other tasks that you might normally throw a module onto a site for (facebook posts, social sharing widgets).