One BIG WordPress Site: A Case Study

I recently finished a big project, a few months in the making, that tests the limits of "WordPress as a CMS." At some points in development, I wondered if it was a crazy idea to do this all in WordPress -- but the easy UI (for my client) and quick development (for me) made it work & made it worth it.

The site is a re-design of a custom ASP.NET site developed 2002-2006 for Jerry Rupiper, the owner of Washington Island Realty and webmaster of washingtonisland.com (see washingtonisland.com circa October 2007). The WI.com website is mostly for tourists interested in visiting the island for the first time or planning a return trip. The original site featured information about the island, a comprehensive directory of local businesses, an events calendar, as well as some hosted advertiser sites. The new site would do the same thing (better), add a blog for residents and people interested in what's happening on the island, and a more active calendar.

Homepage: Before

So, to make this project useful for other WordPress developers, I'll go through some of the more interesting parts of the site and explain: How'd you do that?! The project uses the Thematic WordPress Thematic Framework by ThemeShaper, relies heavily on the Flutter WordPress CMS Plugin by Freshout,  and uses a handful of other WordPress plugins (see the bottom of the post for a list) in addition to jQuery and Google Apps. The rest of this post will go through features of the site and briefly explain how they were accomplished.

Homepage Slideshow

What better way to welcome people to the site (and island) than with big, colorful pictures?! But, slow-loading photos are not going to keep people on the site, so (in addition to compressing the photos), the slideshow uses the jQuery Cycle plugin combined with a callback function to dynamically add slides after the page has been loaded.

Picture 3

The homepage template contains the loop (like normal), and then below the #container div, the following chunk of code:
<div id="supersize">
     <img src="<?php echo get_bloginfo( 'stylesheet_directory' ); ?>/images/slideshow/1.jpg">
     <img src="<?php echo get_bloginfo( 'stylesheet_directory' ); ?>/images/slideshow/2.jpg">
</div>
This #supersize div contains the first two slides of the homepage slideshow, enough to get Cycle going once the page has loaded. The page also contains this JavaScript:
<?php wp_enqueue_script('cycle', get_stylesheet_directory_uri() .'/js/jquery.cycle.js', 'jquery'); ?>
<script type="text/javascript">
jQuery(function($){
     $('#supersize').cycle({
          random: 0,
          delay:  -2000,
          speed: 500,
          fx: 'fade',
          timeout: 6000,
          before:   onBefore
      });
      var slidesAdded = false;
      function onBefore(curr, next, opts) {
          if (!opts.addSlide || slidesAdded)  return;
          for (var i=3; i < 10; i++)  opts.addSlide('<img src="http://src of slides/'+i+'.jpg" width="1024" height="768" />');
          slidesAdded = true;
      };
});
</script>
The onBefore callback adds the rest of the slides to #supersize after the page is loaded. This speeds up the page loading, especially if the user doesn't plan on sticking around for all 10 slides and just clicks into the site.

Flickr Photostream

The Visitor's Guide intro page shows off more of the island's sites with thumbnails from the Washington Island Flickr photostream. The photostream is added to the page by the simple flickrRSS plugin by Dave Kellam combined with this quick plugin, which I wrote to add a shortcode to the site: http://gist.github.com/154365

Picture 7

Local Businesses: Custom Write Panel #1

Local Business listings are a key part of WI.com, powering the directories (Local Business Directory & Accommodations directory), banner advertisements, and advertiser pages hosted by WI.com. There are three types local businesses listed on WI.com: advertisers with hosted pages, advertisers with banner ads that link to their own website, and un-paid listings that the owner of WI.com lists to make the directory more useful. Using the Flutter WordPress CMS Plugin by Freshout, I setup a "Custom Write Panel" (Freshout's name for a custom content type or post type) called "Local Business." The Local Business write panel is where all local businesses are defined, regardless of the type of listing.

Local Business Custom Write Panel

The tools that make this custom write panel useful are:
  • Local Business Directory template,
  • Accommodations directory template,
  • Advertisements Widget, and
  • Local Business Page template.

The Local Business & Accommodations directories are very similar to category listings (template pages that use multiple loops to only display posts within the correct categories) with some added CSS & jQuery for display and behavior. Both pages use the jQuery plugins quickSearch by Rik Lomas and Smart Lists by Benjamin Keen.

Local Business Directory

The Advertisements widget is defined in functions.php, it uses WP_Query() to retrieve Local Business posts and then display their banner ads (uploaded as "Ad Image" in the custom write panel defined by Flutter). Then, depending on whether the advertiser has an "External Link" defined or not, the banner ad will either link to the advertiser's website or their WI.com hosted page.

Advertiser pages hosted on WI.com are displayed by the Local Business template, (see Category Templates in the WordPress codex), which can be customized in the Custom Write Panel using the "Template Options" defined by Flutter. Although this implementation crosses the line I like to draw between content and presentation, this is how the template handles customization:

<?php $border_color = get('template_border');
$content_bkg_color = get('template_content_bkg');
$bkg_img = get('template_bkg');
echo '<span id="bkg_img" style="display:none;">'.$bkg_img.'</span>';
$bkg_color = get('template_bkg_color');
echo '<span id="bkg_color" style="display:none;">'.$bkg_color.'</span>';
$banner = get('template_banner');  ?>
<div id="container">
     <div id="content" style="<?php if ($border_color) { ?> border:5px solid <?php echo $border_color; ?>;<?php } if ($content_bkg_color) { ?>background-color:<?php echo $content_bkg_color;  }?>">
          <?php the_post(); ?>
          <?php if ($banner) { echo '<div><img src="'.$banner.'">'; } ?>
...
<script type="text/javascript">
jQuery(function($){
     var bkg_img = $('span#bkg_img').text();
     if (bkg_img == 'Painted Blue') {
          $('body').css("background", "url(http://imgsrc.gif) top center fixed no-repeat" );
     }
     if (bkg_img == 'Painted Green') {
          $('body').css("background", "url(http://imgsrc.gif) top center fixed no-repeat" );
     }
     var bkg_color = $('span#bkg_color').text();
     if (bkg_color) {
          $('body').css("background", bkg_color );
     }
});
</script>

News (Blog Posts): Custom Write Panel #2

To keep things simple, blog posts are also a custom write panel. This lets me hide  Custom Fields, and Categories, and guarantees that the WI.com bloggers will always have the appropriate "News" category attached to their blog posts.

Edit News Write Panel

The Island News page (the blog), uses multiple loops to only display posts in the "News" category, and an action in the functions.php file excludes Local Businesses (the only other category used on the site) from the RSS Feed and Post Archives.

function gloss_remove_glossary_cat( ) {
     global $wp_query;
     if( is_home() || is_feed() || ( is_archive() && !is_category() )) {
          $wp_query->query_vars['cat'] = '-3';     // Local Businesses
     }
}
add_action('pre_get_posts', 'gloss_remove_glossary_cat' );

Events Calendar

I initially tried to approached events as a third custom write panel (see this post: WP+jMonthCalendar=Fancy), but found that handling multi-day events within Flutter's custom write panels (at that time, could be better now -- the plugin is constantly being updated) was too big of a stumbling block to work though. Dealing with archives of previous months' events and trying to minimize the number of queries to the WP database was also something I was unprepared to handle. I quickly switched to Google Calendar + FullCalendar, a jQuery plugin by Adam Shaw.

My client can login to Google Calendar, create events there, and then see them automatically added to the calendar on his site. He can also give friends & colleagues permission to add events to the calendar, the same way he can add users to the WordPress site as bloggers. FullCalendar reads the calendar's public feed and turns it into an easy-to-theme and quick-to-load full-month calendar.

Picture 6

Using FullCalendar is incredibly easy, the only thing I had trouble with was when Google spontaneously (and erratically) started sending the feed in German, which was fixed by adding &hl=en to the end of the feed's URL.

Google Maps

After trying Google Map plugins for WordPress, and finding that they really slowed down the site (even on pages that didn't have embedded maps!), I decided to switch to direct iframe embedding. This can open up a site to some vulnerabilities (if you don't trust people posting to use iframes responsibly), but in this situation, I wasn't worried about my client abusing iframes.

By adding the following filter to functions.php, the Google Maps embed code is now allowed by TinyMCE:

add_filter('tiny_mce_before_init', create_function( '$a', '$a["extended_valid_elements"] = "iframe[id|class|title|style|align|frameborder|height|longdesc|marginheight|marginwidth|name|scrolling|src|width]"; return $a;') );

List of Plugins

Edit: (9/23/09) I ended up using WP Super Cache instead of Hyper Cache and DB Cache
This entry was posted in WPMU, wordpress and tagged , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

14 Comments

  1. Posted July 27, 2009 at 4:29 pm | Permalink

    I found your article from the Flutter site. I really like what you’ve done with the washington site, not only from a technical point of view but also design. The site looks so much better, a lot less scary and off putting than the previous site. Nice one.

  2. Posted July 29, 2009 at 11:27 pm | Permalink

    Wow.
    That’s pretty impressive. Especially considering how relatively little crazy custom programming there was to make it happen!

    Oh, and, FYI, I got here via an Ian Stewart Tweet.

  3. Posted July 29, 2009 at 11:57 pm | Permalink

    Nicely done! thanks for the writeup.

  4. Sheril Jebasingh
    Posted July 29, 2009 at 11:57 pm | Permalink

    Useful article. Thanks for sharing.

  5. Posted July 30, 2009 at 8:59 am | Permalink

    Congratulations, excellent work, truly an inspiration for us non-coders.

  6. Posted July 30, 2009 at 10:07 am | Permalink

    Great article, great rebuild and thanks for opening my eyes to some new plugins here.

  7. Posted August 11, 2009 at 12:55 pm | Permalink

    You’ve done an amazing job with the website. Thanks for writing this case study. Its very helpful.

  8. Posted September 3, 2009 at 3:52 am | Permalink

    This is an excellent article. Just the kind of thing I love to read!!

    Wanted to let you know that HeadSpace2 by John Godley does a few of the things you’ve got other plugins for, aside from all its SEO goodness.

    It would replace in the list above Page Menu Editor and Ultimate Google Analytics. It also does loads of other nifty things.

    Since you’ve got a few other of John’s plugins there, I thought you might like to stick with him some more :)

    I do!

    Cheers,

    -Alister


    Alister Cameron // Blogologist
    http://www.alistercameron.com

    Mob. 04 0404 5555
    Fax 03 8610 0050

    Click here to find me online:
    http://clicktoadd.me/alicam

  9. Posted October 13, 2009 at 7:32 pm | Permalink

    Wow, this post was like a life preserver. I’m building a website for a nonprofit using WP as the CMS (and a bit of Google apps) for just the reasons you listed, but I’ve been completely stumped by what to use for a calendar. I began with Google calendar but none of the WP plugins I found had the features the client wanted. I was just tonight looking at how I might embed an AJAX or PHP calendar in the WP site when I found your post. FullCalendar is new to me but it looks just right. So thanks for taking the time to write up this case study.

  10. Posted October 13, 2009 at 8:52 pm | Permalink

    Hi. I’m having a complete failure of imagination here. How do I integrate FullCalendar into Wordpress? I’m just realizing that all the jQuery scripts I’ve used in WP had already been converted to a WP plugin by some kind, clever person.

    If it helps here’s my skill level: Good with html & CSS but just starting to learn PHP.

    • Esther
      Posted October 13, 2009 at 9:01 pm | Permalink

      This is the code I use in my calendar.php (WordPress template file):

      <div id="full-calendar"></div>
      <noscript>
      <div class="message">Some message to my users & a link to the calendar if they have JS turned off...</div>
      </noscript>
      

      And this is my JavaScript:

      <script type="text/javascript">
      jQuery(function($){
      	$('#full-calendar').fullCalendar({
      		events: $.fullCalendar.gcalFeed('http://mygooglefeedURL',
      			{ className: 'gcal-events' }
      		),
      		eventClick: function(event) {
      			window.open(event.url, 'gcalevent', 'width=700,height=600');
      			return false;
      		},
      		loading: function(bool) {
      			if (bool) $('#loading').show();
      			else $('#loading').hide();
      		},
      		abbrevDayHeadings: false
      	});
      });
      </script>

      You’ll also need to make sure that you include the jQuery FullCalendar plugin and GCal support. Use the wp_enqueue_script() function to include /js/fullcalendar/fullcalendar.min.js, /js/fullcalendar/gcal.js, and /js/fullcalendar/jquery/ui.core.js.

      • Posted October 13, 2009 at 9:58 pm | Permalink

        Excellent. I was just looking up the wp_enqueue_script () function. Thanks so much for your help.

  11. Posted November 20, 2009 at 6:04 am | Permalink

    Great case study Esther!

    I wish I took the time to document my projects this well. And really nice redesign!

  12. Posted December 10, 2009 at 7:58 am | Permalink

    Excellent case study! washingtonisland.com sure looks (and I bet, functions) a lot better.

    What made you choose wordpress as opposed to drupal or joomla btw?

2 Trackbacks

  1. By Case studies ? - WordPress Tavern Forum on August 2, 2009 at 8:57 am

    [...] may appreciate their work getting exposure. A case study found via Ian Stewarts tweets: http://blog.estherswhite.net/2009/07…-a-case-study/ Opinions ? Other case study urls [...]

  2. [...] Shared Outta Bounds – One BIG WordPress Site: A Case Study [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>