Keeping your CDN-hosted CSS and JS from caching and causing you to rip your hair out

CDNs are great for distributing bandwidth and speeding up your site, but if you’re using a static pull, you’re going to have an issue if you make a tiny tweak to your CSS file, unless you invalidate the file in your CDN panel. Of course, that’s not always practical, and it takes a few minutes to take. However, version numbers make everything work smoothly!

This is my simple fix to dealing with CDN and versioning. I’m using this in WordPress, but it can be easily adapted to pretty much anything.

function get_version_from_datestamp($str_file){
 $str_version = date ('y.n.j.G.i', filemtime($str_file)); //YY.M.D.H.MM
 return $str_version;

This function takes the full path to the file and returns a version number based off of the date (my full function assumes just a relative path and then appends the full file path to it). When using wp_register_script or wp_register_style, simply call this in place of a static version number. When you update the file on the server, it automagically updates the version number! No fuss, no muss, no invalidating, no worrying about the version number itself.

More WordPress Theme Streamlining

In my last post (nearly five months ago…) I discussed creating constants for things that WordPress loves to run to the database to get.  Now, constants are great, but sometimes you just want to roll everything into an easily-used array and be done with it.  So, for the majority of my theme options, I do just that.  I’m a stickler for naming conventions, because it’s so much easier to deal with after the fact.  Name it properly and give it a prefix, and you shouldn’t have trouble finding it or figuring out what it does a year down the road when you don’t even remember writing it.  When creating theme options for a particular site, I start all of them with a prefix – say, to_ – and then a highly descriptive name.  ‘to_home_page_splash_image’ is pretty self-explanatory.

Prefixing all of my theme options the same allows me to go to the database once and grab them all at the same time:

add_action('after_setup_theme', 'mytheme_lifeshield_setup');

function mytheme_option_setup(){
 global $wpdb;

 $arr_results = $wpdb->get_results("SELECT * FROM $wpdb->options WHERE option_name LIKE 'to_%';");
 $arr_to_options = array();
 foreach($arr_results as $obj_result){
  $arr_to_options[$obj_result->option_name] = $obj_result->option_value;
 $GLOBALS['to_options'] = $arr_to_options;

Now, when I need a particular option, I just reference the global variable: . No need for yet another get_bloginfo() call.

Using Constants to Streamline Your WordPress Theme

Working with a large corporate site that gets plenty of traffic and runs WordPress has taught me a few things about WordPress that I don’t particularly like.   The biggest complaint I have is that WordPress views the database like a swarm of bees views a bear attacking their hive: hit it repeatedly hoping that it goes down.  Doing a freelance gig and discovering that your client’s hosting has a database cap of 75000 hits/hour is not a fun situation when they’re getting around 1000 page views per hour and it’s pushing that cap.  Caching is great except that this was go-live, and there was a lot of data to cache for the first few hours.  Even still, caching doesn’t help everything.

So what can you do to help smoke those bees down?  Get a little nimble with your code and stop relying on WordPress conventions for everything.

bloginfo() and get_bloginfo()

These two functions are bad news, because they make a database request every time.  If you’re designing a custom theme for a site and you’re not expecting a lot of changes to the name and tagline, making heavy use of these functions is going to bog you down. Here’s what I did:

define('THM_TITLE', 'Page Title');

Then, where you’d be using bloginfo(‘name’), you just change that to echo THM_TITLE;

Instead of relying on get_bloginfo(‘name’) to hit the database just to figure out what my site’s name is, I just tell it in code with a constant.  I used the THM_ prefix to localize it for my theme and ensure I’m not crashing into any other defined constants (in practice I use a more descriptive prefix).  Obviously, hard-coding the name doesn’t work if you’re running a multisite or are building a theme for wide use, but if you’re building for a static installation to use WordPress as a CMS, you’ve just saved yourself one database call.  The name is just the first thing to tackle, though.  The biggest culprit I encountered was get_bloginfo(‘siteurl’);.  I used this all over my theme to make sure my images and stylesheets and script calls were all originating from the correct URL.  Now, it’s technically OK to leave this out, but let’s go for accuracy.  I work with development and integration servers, so this needs to be dynamic.  At the top of my functions.php, I added

define('THM_SITEURL', get_bloginfo('siteurl');

And then I replaced every instance of get_bloginfo(‘siteurl’) with THM_SITEURL.  That saved me 10 database calls on my home page alone.

Here’s a few others that I use:
Theme diretory URL:
define('THM_TEMPLATE_DIRECTORY', THM_SITEURL.'/wp-content/themes/theme_directory');

Pingback URL:
define('THM_PINGBACK_URL', THM_SITEURL.'/xmlrpc.php');

define('THM_CHARSET', 'UTF-8');

All told, between those five defined constants, I reduced my database calls on my home page initiated by my theme from 22 to 5.

Don’t stop there, though.  Just about everything in get_bloginfo can be hard-coded for a standard, out-of-the-box WordPress setup.  And chances are, if you’re running a highly custom theme, you can deal with hard-coding the rest.

Go Live: Wharton Magazine

The process of designing and implementing a new website for Wharton Magazine was not a simple undertaking.  The magazine already had a website running OpenType/RedDot CMS, administered in large part by a third-party vendor.  Neither the CMS nor the maintenance arrangement were working very well for the magazine staff, which lead to discussions of what direction to go.  From the beginning of the process, I was an advocate for not only moving to WordPress, but also integrating with Wharton’s vast multi-site setup to take advantage of the existing framework and the resources it already had in place.

Wharton Magazine Home Page

The existing Wharton Blog Network would also need to be integrated, moving it from its standalone setup into the larger framework while maintaining all of its functionality.  As the ‘users’ on the Blog Network did not need to be users in the traditional WordPress sense, the integration of the network proved to be a chance to streamline the posting process for the web principals on the magazine staff.

I took full advantage of the features in WordPress 3 to create multiple post types and taxonomies to support the various parts of the site.  The Issue archive took the old and complex CMS system and transformed it into a setup that would allow the staff to compile articles and create the entire online version over time and organize them correctly before launching them to the site.

The end result is a site that the Wharton Magazine staff can maintain and update autonomously, building a growing archive of back issues with a click of a button.

Go Live: LifeShield, Inc.

I joined the LifeShield team near the beginning of a site-wide overhaul to move from a static page framework to a more marketing-friendly CMS approach. The IT team had identified WordPress as their CMS of choice, and I moved into a lead role in customizing the site and integrating the existing framework.  The layout had been designed by third-party firm and required extensive modification to fit into the existing business model.  Additionally, there was a marketing and tracking codebase that didn’t play well with the way  WordPress runs.  Integrating the two was not straightforward, and involved a lot of dancing around the WordPress core.  My primary goal was to have a seamless integration that did not involve a single edit to a WordPress core file, and achieved that by making extensive use of WordPress hooks and error handling.

LifeShield, Inc.

In addition to the WordPress core, I added a number of external pages for community crime stats using the Google Maps V3 engine and a third-party crime aggregator.  The first step was to format the data imports to be search-friendly, and then it was on to creating a JSON app to load new data points when the user scrolled around the map.  There was a lot of query-magic to generate the returns in a web-friendly time frame.

LifeShield Crime Stats

The database contains millions of records, and we only wanted around 1000 at any given time – in a particular radius around a particular point for a particular time frame.  The solution was to write a query that narrowed itself: first by calculating a box, then by calculating the radius, and finally narrowing by date.  My first attempt produced results in around 3 minutes, and the final production query returns in under a second.

For the curious:

[crime_table] d
d.latitude > [latitude_minimum]
AND d.latitude < [latitude_maximum] AND d.longitude > [longitude_minimum]
AND d.longitude < [longitude_maximum]
AND ROUND(SQRT(POWER(69.1 * (d.latitude - [requested_latitude]), 2) + POWER(69.1 * ([requested_longitude] - d.longitude) * COS(d.latitude / 57.3), 2)), 0) AND timestamp(d.datetime) = DATE_SUB(now(), INTERVAL [requested_time_start] DAY);
) tt
tt.datetime ASC
0, [requested_limit];

The latitude and longitude mins and maxes are calculated on the fly by adding or subtracting the following from each: (distance_in_miles + (distance_in_miles * .25)) / 69.

HTML5 Video Roundup

I’ve just jumped feet-first into HTML5, and I must say, it’s pretty awesome. I’m actually learning a lot about HTML4 as I go, due to the great writing by Mark Pilgrim (I’ve read the printed version).

My first HTML5 challenge was video, and a challenge it was. For as browser- and code-friendly as HTML5 is, getting all of the pieces to fall into place was still a daunting task. Thankfully, the internet provided all the answers that I needed. The problem, however, was asking the right questions. There was no one answer that I could find, so I’m writing it. This isn’t new information, it’s an assembly of all the pieces I needed to get video working correctly on my site.

Obviously, there are a number of browsers out there vying for market share, and to distinguish themselves from one another, they have collectively made the decision to not support a single standard of, well, anything. Video is no exception. The unfortunate truth is that you’re going to need four different video formats if you want to ensure that everyone is going to see your video. The good news is that HTML5 makes that a snap!

1 – HTML5 markup
Mark Pilgrim handles the gritty details of what video formats to choose and why (including how to encode your video), but after that, you need markup:

<video controls width="500" height="300" poster="poster.jpg">
<source src="video.mp4" type="video/mp4" />
<source src="video.ogv" type="video/ogg" />
<source src="video.webm" type="video/webm" />

This will display whichever version the browser can handle, with video controls, using the specified image as the first screen. Between MPG4, Theora/Vorbis and WebM, that takes care of playing your video on every browser capable of supporting HTML5, which at this point, is most of the market. Something else to note here is that iOS 3 apparently only reads the first <source /> tag, so you need to make sure that your MPG4 video source is first on the list (as in the example). This problem was fixed in iOS 4, but if it were as easy as a new version, you’d never again have heard “IE6” after October 2006.

2 – Flash, for older browsers (and by “old” I mean “Internet Explorer”)
Next up, you’ll want your Flash. There are a number of ways to handle Flash, so I’m not going to get into them here. Whatever you were using to display Flash before will continue to work. You want to place it right before the </video> tag. If the browser doesn’t support HTML5, it will ignore the <video> tag and execute your Flash. Problem solved!

3 – A few stragglers
We’re three quarters of the way there. Just two more things to note:

A) MIME types! These are really really important. Make sure the MIME type you’re declaring in your <source /> tag is actually what you’re serving. If you’re hosting your videos on S3, make sure you set your MIME types for each file to what they should be. S3 defaults to application/octet, which will cause Firefox to stare blankly at you while you wonder why there’s a hole where your video should be. Other browsers fail a bit more gracefully.

B) The poster attribute. Again, iOS 3 is a troublemaker. It’s not that it ignores the poster attribute altogether (which would actually be nice) – no, it dumps it over the controls and wreaks havoc on the ability to play the video. After wading through a lot of conversations where people wondered if there was a solution, a coworker and I finally hit on a solution that works. I hate error trapping for one browser, but if you know you’re going to have people using it, then it’s a necessity.

Basically, we check for iOS 3, and create the video tag with JavaScript:

var osString = navigator.appVersion;
if (osString.indexOf("OS 3_") != -1 && osString.indexOf("like Mac") != -1) {
// create video tag for iOS 3
document.write('<video controls="true" width="500" height="300" id="video_player">');
// create video tag for the rest of civilization
document.write('<video controls="true" width="500" height="300" poster="/alumni/giving/images/The_Campaign_Final-poster.jpg" id="video_player">');

And that’s all there is too it. Hope this saves you some time.

Go Live: Wharton Alumni and Giving to Wharton

These two sites went live at the beginning of September, and while I’m still ironing out bugs, the public side of the sites is worth mentioning here.

Wharton AlumniGiving to Wharton

Both of these sites are built in RedDot CMS (actually, it’s OpenText CMS now, but we still call it RedDot).  From January to, well, now, the majority of my job has been converting the old static site to RedDot.  I can’t say that this process has been an easy one.  I was responsible for the creation and implementation of the bulk of the pages and this required me to learn a completely new system that was coded in Germany.  I experienced European coding a few years ago after IQ outsourced a project to Poland.  Most of the syntax of languages is written in English (with the random Hebrew PHP error message), but that doesn’t mean that people who speak Polish or German are going to code in English.  What might seem like a perfectly logical variable name in Polish probably isn’t going to make nearly as much sense when it’s been run through Babelfish.  Likewise, Germans don’t have the same knack for writing concise English description as a native English speaker does.  The major impediment to learning RedDot was figuring out what exactly all the constructs inside it actually did, because the names given to a majority of them didn’t seem to accurately describe them.

The other major hurdle was that the team that manages the RedDot server is a school-wide resource, and a number of other departments were designing and launching sites in RedDot, often without the benefit of a developer.  This meant that the RedDot team was not only trying to build and launch a number of other sites, they were tackling my near-incessant questions, and dealing with an upgrade that resulted in a lot of things breaking.  On top of that, they were outsourcing major issues to one of the few RedDot vendors, a company of 15 people located somewhere near Vancouver.

So, here are the run-downs for both sites.  A quick note concerning the publishing:  Our RedDot setup has two publication packages: Staging and Production.  Additionally, we have three servers: Development, Staging and Production.  As these terms relate, it’s a bit confusing.  Ideally, RedDot Staging publishes to the Development server, and RedDot Production publishes to the Staging server.  The reason for that is that the Staging server pushes everything to the Production server once every 15 minutes.  We don’t have direct access to the Production server.

Giving to Wharton

This site actually went smoothly from start to (almost) finish.  The site itself was populated with content and, for all intents and purposes, ready to launch by the end of May.   As the project neared go-live, a number of the stakeholders came forward with content changes and section revamps.  All of these were handled fairly smoothly, and the only hang-up came right before go-live when we realized that the Staging publication package and the Production publication package were not mirroring each other.  The interim solution has been to publish both packages to the Development server, make necessary changes, and push them to the Staging server manually.

Wharton Alumni

This part of the project was a bear.  From the very beginning, the installation was fraught with problems that we kept attempting to address.  It seemed at every point that once one was fixed, two more would crop up.  Finally, nearing the go-live point, we decided to scrap the entire thing and re-create it.  This turned out to be a very effective tactic.  Scrapping 8 months of development wasn’t an easy argument to win, but the result was a completed site in just over two weeks.  The 8 months of combating bugs gave me a lot of good insight into RedDot’s inner workings, so once I had a bug-free environment, construction of the site went very smoothly.  The same publishing problem from the Giving site showed up, however, and at the moment, we’re still publishing manually.

All in all, it’s been a long, strange trip, but the reception has been amazing.  The new site is worlds better than the previous one, and it’s given the staff at External Affairs a much easier way to update their changing information than they had before.

Go Live: Wharton Blog Network

This site actually went live around a month ago, but I’m just getting around to the write-up.  I’m not sure what took me so long, considering I now have something to show to the public that has the Wharton name on it!

Wharton Magazine Blog Network

The Wharton Magazine site itself is running RedDot CMS, but the blog segment has been running on WordPress for around two years. In its previous incarnation, it was a point of contact for the editorial staff. This concept was expanded to include relevant non-magazine article updates from faculty and alumni.

In the initial concept phase, I suggested the possibility of using WordPress MU to create a new blog for each user and then having the main blog page aggregate the posts. Within a few days of that proposal, WordPress 3.0 was released, and after a review of the features, I decided that the robust multi-user setup was actually too much bang for the buck and scaled back my proposal to a simpler WordPress installation with multiple contributing users.

Most of the functionality comes straight from the proverbial box. I developed a simple plugin for the sidebar in order to display the editor’s most recent post in a styled box.  There is also a custom work-around to allow a specific author’s most recent posts and user profile to be two separate pages.  User profile pages is one of the things that I wish WordPress did a bit better, but the solution I came up with is fairly simple to use but not very intuitive, so I wouldn’t recommend it as a good solution.

Going forward, I’d love to spend some time playing with the Contributors section on the sidebar.  As it stands, it’s simply a text widget that I’ve hard coded.  I’d like to expand that into an automated widget that the administrator (which at the moment is me) can control from the back end.

New WordPress Widgets

Having been kicking around the exciting world of installing and customizing WordPress, I felt it was high time I launched myself into the even more exciting world of developing for WordPress.  And here’s what I’ve come up with:

Recent User Posts

Recent Category Posts

Both of these are widgets that do basically the same thing, so I’ll describe them together here.

In developing the new Wharton Magazine blog, we needed a widget to display the Editor’s most recent post.  I poked around for a bit, and realized that there really wasn’t a plugin to handle this, so the need for one was obvious.  After getting the basics down, I decided that it actually had more applications than just a single post, and started adding features.

So, the end result is two widgets.  Enter a title, select the user/category you want to display, enter the number of posts to display, and select if you want to display a link to the user/category and the time and date.  Not complicated to use and does just what it says it does.

Before I release it to the WordPress Plugins Codex, I’d like to see if anyone wants a shot at debugging or can offer any tips or suggestions.  Files are at the links above, and thanks in advance!