The Cook Political Report is a Web site devoted to providing subscribers with political analysis of U.S. presidential, House, Senate and governor elections and campaigns. The site relaunched recently in Drupal, drastically improving the workflow for content publishers and improving usability for readers.

http://cookpolitical.com

About the Project

The Cook Political Report is a Washington DC-based institution with a 24-year history. It began as a printed newsletter for subscribers and moved online in 2004. Cook Political’s niche is in rating political races on a 7-point scale and by keeping track of all data related to each election. This includes names and parties of candidates, fundraising numbers, filing and election dates, partisanship of a state or district, and more. The principal, Charlie Cook, is widely regarded as one of the nation’s leading authorities on U.S. elections and political trends.

Until the Drupal-based site was launched, Cook Political staff published their reports and analyses as PDF files. This caused major headaches for them because many files had to be updated even if only one piece of data changed. When approaching the redesign of the site, the client’s number one requirement was a Content Management System that allowed content editors to make global changes to data and text.

Home Front Communications began the development process in December 2007 and most of the Drupal development occurred between March and May 2008.

The core development team included:

  • Sarah Jancich (HFC Production Director), Drupal dev, theming
  • Jason Socha (HFC Senior Developer), Drupal dev
  • Ryan Dudek (HFC Browser Slave), HTML/CSS and theming
  • Emily Coven (Flax Media), Web design and Flash dev

With contributions from Phillip Lamb, Derek Walker, and several long-suffering data entry helpers.

Why Drupal

We selected Drupal after using it for another project in late 2007. The main reasons behind the selection were excellent support for multiple content types with CCK, a flexible API for adding custom functionality, and the variety of quality contributed modules.

Data Architecture

The site employs 10 different content types, many of which are linked through node references. For example, we created a node type, "state," which has fields for filing and election deadlines, number of Electoral College votes, current senators and governor, and which presidential candidate the state supported in 2000 and 2004. The "congressional district" node type has fields for current representative, geographic description of the district, and an image field for a district map.

We also created a "person" node type that holds information about all current officeholders and candidates. This node type has fields for party and biography, and each state and congressional district references a “person” node for incumbent information.

The most important data are stored in race nodes, including the race rating and background analysis. This node also has a number of node reference fields to person (for candidate listings), state and congressional district nodes.

When content editors post additional analysis, it is related to a specific race. The "article" content type includes a node reference field so that this update can be added to the race node using hook_nodeapi.

This architecture puts all information related to a political race on one page, a client requirement.

Data Migration

The data migration process was a bit painful. We were responsible for migrating data back to the start of the 2008 election cycle, which was quite a task. Nearly all of this data was stored in QuarkXpress and/or PDF files. We hoped to find a way to migrate through a script but gave up and ended up rekeying nearly everything. We were able to migrate easily FEC financial reports, as they were available as a CSV from http://www.fec.gov.

Flash Integration

The Cook Political Report site includes five data-driven Flash maps. One is on the homepage and the rest live on the section fronts (Presidential, Senate, House and Governors). The Flash applications show a limited amount of data about each race as users mouseover or click states and districts.

We added custom functionality to write and store XML files with the necessary data for each map. The processes for regenerating the XML are quite intense, requiring many complex queries across many core and CCK tables. To minimize this hit on the server, we relied on several early morning cron runs to regenerate each file every 24 hours. There is also an "emergency" switch inside the administration section that allows content editors to regenerate the map XML on the fly.

Printable charts

The client's previous site linked to a number of PDF files that formatted a tremendous amount of data into more than a dozen tables, which they termed "printable charts." These data are essentially the same as the information included on each race page.

After the relaunch of the site, the client wanted to keep these charts while allowing users to browse through the same data in the Flash maps and Drupal nodes. The goal was to provide multiple "views" of the same material, allowing users to choose how they consumed the information.

We had hoped to use the Views module to generate the printable charts. Because of the complexity involved, the need for an archive of all charts, and performance concerns, we ended up scripting a custom solution. Our module re-uses the XML files generated for the Flash maps to write static HTML files that are stored on the server. We also added a small administrative interface that allows staff to generate, preview, publish and delete charts.

An example of a printable chart is here: http://cookpolitical.com/charts/president/ev_scorecard.php

Subscriptions

The site provides some content to the public but the bulk of it is restricted to subscribers. We used the content_access module to block access to anonymous users by node type as well as on a node-by-node basis.

On the client's previous site, the financial transaction took place offline. With the relaunch, the client wanted a system in place to accept and process credit cards, as well as subscription terms and renewals.

The client had several requirements for the subscription system that didn't fit into any of the traditional commerce/cart packages, so we coded a custom module to smoothly handle subscriptions and renewals according to the desired transaction flow. It includes a "group subscription" that allows one Group Manager to purchase, give and revoke subscriptions to other people, automatic renewal reminder emails and expirations, and integrates with Drupal's native Roles system to give and revoke access to restricted content. Payments are processed through Google Checkout, the client's preferred solution, with the subscription module taking full advantage of the Google Checkout API to send and receive messages about transaction status.

Right before the re-launch the client had roughly 1,000 subscribers that needed to be migrated over to the new system. They previously used aMember, so this migration was a snap.

Contrib Modules

We are using the following contributed modules. Many thanks to the Drupal community!

  • BUEditor
  • Content Access
  • CCK
  • Custom Breadcrumbs
  • Devel
  • Forward
  • Google Analytics
  • ImageCache
  • NodeQueue
  • Panels
  • Printer-friendly pages
  • Scheduler
  • Views

Comments

alexsdc2’s picture

Just curious what you used for navigation. Yours seems to work perfectly and I haven't been able to find a navigation like that which doesn't have a flaw in it.

thanks

sjancich’s picture

Hi there,

We used the Nice Menus module for the navigation bar.

http://drupal.org/project/nice_menus

After we installed the module, we had to tweak the CSS to position the elements correctly. We also had to use some hacks (eeps!) to get IE to behave.

Here's a snippet of the CSS we used:


.menuparent ul li {
	background-color: #054E7A;
	border: 1px solid #376FA8;
	border-top: none;
	width: 210px;
	padding: auto;
	vertical-align: middle;
	margin: 0px;
	padding: 5px 0;
}

.block-nice_menus li#menu-90 { /*Presidential label*/
	margin-left: 0px;
	padding-left: 40px;
}

ul#nice-menu-1 /* Entire dropdown*/ {
	margin-left: 0px;
}

ul#nice-menu-1 li.menu-path-governors { /*Governors label */
  padding-right: 10px;
}

li.menu-path-presidential ul /*Pres dropdown */ {
   margin-left: 0;
   	_margin: 0px auto auto -40px; /* IE 6 HACK */
	.padding-top: 6px;
}

li.menu-path-senate ul /*Senate dropdown */{
	margin-left: -31px;
   	_margin: 0px auto auto -77px; /* IE 6 HACK */
	.padding-top: 6px;
}

li.menu-path-house ul /*House dropdown */{
	margin-left: -35px;
   	_margin: 0px auto auto -81px; /* IE 6 HACK */
	.padding-top: 6px;
}

li.menu-path-governors ul /*Gov dropdown*/ {
	margin-left: -15px;
   	_margin: 0px auto auto -61px; /* IE 6 HACK */
	.padding-top: 6px;
}

ul#parent-103 /*Poll dropdown*/ {
	margin-left: -10px;
   	_margin: 0px auto auto -55px; /* IE 6 HACK */
	.padding-top: 6px;
}

ul#parent-137 /*About dropdown */ {
	margin-left: 35px;
   	_margin: 0px auto auto -5px; /* IE 6 HACK */
	.padding-top: 6px;
}
alexsdc2’s picture

Thanks for the quick reply. Also I got ahead of myself and forgot to tell you what a great site it is. I love hte colors and design and everything. Great work!

Anonymous’s picture

This is an awesome work, a handcraft art!

The use of CCK node reference fields to make content relationship in your site is so effective!

Do you have any thoughts about performance to share?

Congrats!
Erik

---
Drupal rocks!
Read the case: 4Linux, a FLOSS company, goes Drupal: http://drupal.org/node/285603

gnosis’s picture

Actually, cookpolitical.com is running with very little performance optimization. Aggregate and compress CSS is enabled and that's about it! Believe it or not, even the normal page cache is disabled due to a bug in the Accessibility module (http://drupal.org/node/270785). Of course this made me squirm quite a bit when we discovered it, but Drupal has held up very well with it turned off.

Much of the site's traffic is from paid subscribers who are logged in and wouldn't benefit from the page cache anyway. We do, however, want to move towards a better solution; I'm planning to do some testing with the Boost module to see if that will work for us. The day will come when this URL is flashed on CNN and we get traffic x10 for half an hour, so we need to be at least a little prepared. Overall I've been very happy with the way Drupal handles requests right out of the box.