Welcome to the Geeks & God Static Archive. Read more »

Building a Custom Media Page in Drupal

User Rating:
Average: 4.6 (10 votes)

This tutorial explains how I used a custom Drupal module to create a richer user experience for the Cornerstone Church Media page. It builds on my earlier tutorial on Creating a Simple Drupal Module and does not require advanced PHP skills. This technique could also be used to build a custom front page for a site.

When we first launched the Cornerstone website on Drupal, the Media page was a lackluster mess of plain text and links that didn't really grab a site visitor's attention. A few months ago, Cornerstone's designer sent me a mock-up of a new graphics-rich design for the page.

After separating content from presentation, it was clear that the page was simply two views and a menu with a little CSS applied. The Recent Sermons view and Cornerstone Media menu could be simple unordered lists. The Cornerstone Series was simply an adaptation of our existing Cornerstone Series page view.

I started by creating a view named media_recent_sermons. I did not need to create a page or block display. This tutorial uses the view output generated from Defaults. I also created a menu called menu-cornerstone-media. (note: Drupal prepends the menu- to whatever menu name you enter.) I already had a view called current_series, which I tweaked a little with the changes we wanted to make.

Now it was time to generate a page. Like my previous tutorial, I used the hook_menu() API to create a new page with a URL of /media:

  * Implementation of hook_menu().
function mysite_menu() {
  $items['media'] = array(
    'title' => 'Media',
    'page callback' => 'mysite_page_media',
    'access arguments' => array('access content'),
    'type' => MENU_NORMAL_ITEM,
  return $items;

This tells Drupal to set up a page at /media titled "Media", using the function mysite_page_media() to generate the content and allowing access to anyone with permission to "access content".

The magic happens in the page callback, where I used two functions, views_embed_view() and menu_tree() to render the contents of my views and menu. Here's a stripped down version so you can see how it actually works:

 * Simplified page callback for the media page.
function mysite_page_media() {
  $output = '<div>';
  $output .= '<div>'. views_embed_view('media_recent_sermons') .'</div>';
  $output .= '<div>'. menu_tree('menu-cornerstone-media') .'</div>';
  $output .= '<div>'. views_embed_view('series') .'</div>';
  $output .= '</div>';
  return $output;

Of course, we want to add nice things like titles and markup to help us theme our page, so my actual output is a little more complicated. I also added links to a FAQ page and to the full list of sermon series.

 * Page callback for the media page.
function mysite_page_media() {
  $output = '<div id="media-index"><div class="clear-block">';
  $output .= '<div id="media-recent-sermons">';
  $output .= '<div class="section-header clear-block"><h2 class="title">'. t("Recent Sermons") .'</h2></div>';
  $output .= views_embed_view('media_recent_sermons') .'</div>';
  $output .= '<div id="media-cornerstone-media">';
  $output .= '<div class="section-header clear-block">'
  $output .= '<h2 class="title">'. t("Cornerstone Media") .'</h2>'. l('(?)', 'media/faq');
  $output .= '</div>';
  $output .= menu_tree('menu-cornerstone-media') .'</div>';
  $output .= '</div>';
  $output .= '<div id="media-cornerstone-series">';
  $output .= '<div class="section-header clear-block">';
  $output .= '<h2 class="title">'. t("Cornerstone Series") .'</h2>'. l(t("more series"), 'media/series');
  $output .= '</div>';
  $output .= views_embed_view('series') .'</div>';
  $output .= '</div>';
  return $output;

You may notice the use of the Drupal l() and t() functions to create links and make all hard-coded strings translatable.

Before adding the CSS needed to make the cool-looking buttons, the rendered HTML output looks a bit like this:

(Note: I did add the necessary floats to div#media-recent-sermons and div#media-cornerstone-media before taking this screenshot.)

The rest of the job was standard CSS text-replacement techniques, which I won't detail here, since it's not Drupal-specific.

I've spent a lot of time looking at the Drupal API Reference to figure this stuff out. There are some decent examples there to get you started. However, this site only documents Drupal Core. The Lullabot Drupal API Reference includes documentation for popular contrib modules, including Views. This reference (along with an old blog post by Matt Farina) was invaluable for trying to figure out how to do this.

Update 22-Nov-2010: Changed MENU_CALLBACK to MENU_NORMAL_ITEM in mysite_menu() function.

Mini Panels


I didn't find this tutorial until after I had already hit my head against my desk a few times, and then tried out mini panels, available in the panels module. It allows you to create mini panels as block which you can then add to a page, etc. In mini panels you can select the layout (in your example 2 columns) and then add the 2 blocks you created. An example would be the homepage I created here NY Throw Down. The example being the news block with images and then on the right a text list of news.

drupal module construction



Iam new webs in drupal,

how can i will make some module for add/list/edit/delete a modules.




Hi harish,

I'm sorry, I don't understand your question. If you're looking to list content with edit and delete links, check out Views, the most popular Drupal contributed module. Or, create a new thread with more detail and hopefully someone can help you.



is the page cached?


hello and thanks for this tutorial.

I think I could use this technique to obtain a nice url to display some html tables that result from complex sql elaborations that can't be obtained with views module: now I use a switch() in the main template page to check for the presence of a specific nid and then include the output of a custom function, an hack I'm not so happy with.

a coleague of mine was theoretically concerned about the fact that the pages created that way (sql -> result -> string elaborations -> echo html table) are not cached, like views pages are, so performances could be affected, to be very picky.

anyway, could you tell me if with that technique pages are cached?

thanks again.

this is very good tutorial; I


this is very good tutorial; I have been trying to create custom module but couldn't created that. After reading this I'm able to create my custom form.

Thanks alot.

Where do i put/create this?


This tutorial seems great, I just can't figure out where to put this code! Any help?



See the Module Tutorial


See my tutorial about how to create a module. That will give you the framework. The code in this tutorial simply becomes additional functions within that .module file.


Thanks for the tutorial so


Thanks for the tutorial so much! I'm only a beginner in the Drupal world, so I'm sure these tips will be extremely helpful for me and many others like me;)
ringtone maker