TckTckTck
TckTckTck is a GCCA campaign calling for a new fair, strong, binding, and international climate change treaty. The Global Campaign for Climate Action recently formed to build a global groundswell for a strong climate deal in Copenhagen this December. GCCA is a collaboration of International NGOs inspired by the success of the Make Poverty History campaign. GCCA's brand is TckTckTck, to indicate that "time is running out" and the web is at the core of GCCA's strategy.
With over 50 diverse and established NGO partners driving the bus, their own unique mandate as a central unifying force, GCCA had to balance two competing yet interconnected elements. First, supporting partners, ensuring they fill a unique role; adding value and always supporting, not competing with partner interests. Second, direct public engagement: providing a strong, unifying global center-point for media and world leaders; organizing new supporters who aren't reached by an existing NGO partner, and supporting new partners who have low online organizing engagement capacity.
The partner organizations are all running their own independent campaigns but using the TckTckTck brand, pointing to the website, and together, in less than a week, they aggregated nearly 1,000,000 supporters to the cause!
Advomatic built the TckTckTck site with Drupal 6 and several staple contributed modules. In general, we used CCK to build the content, Views to list the content, and Panels to arrange the lists on a page. For instance, the home page is a panel page with several Views blocks pulling in content.
Content types
There are three main content types for the site: Stories, Partners, and Events. These are pulled in various lists using Views to fill out the content as needed.
All content on the site have a required Image Field, which is used for the images of various sizes seen throughout the site (using the ImageCache module) when needed.
Stories & Events
As with most sites, Stories are the equivalent of articles, blog posts, etc. In this specific case, each story is grouped by its 'Story Type' vocabulary, such as 'Campaign Updates', 'Human Interest', or 'Climate News'. Nearly all the views accessing Stories are filtered by (or use arguments for) their taxonomy term. In addition to the required 'Image' field, Stories may optionally also be associated with a specific Partner, using a nodereference.
Events are similar to Stories in this case, with added fields for a Date and Location. They appear in their own section, and are also pulled into several Flash pieces, as described later.
Partners
TckTckTck has signed up about 50 partners (and counting), who are other organizations committed to awareness, education, and action regarding Climate Change and the Environment. Each Partner is given a User account, allowing them to directly enter Stories, Partner Campaigns, and Partner Actions (two additional minor content types) into the site. Each Partner account also has a node of the type 'Partner', which is associated with the account using the Content Profile module.
Thus, if a user of the site goes to the partner's user profile page, such as Greenpeace, they'll actually see the content displayed from the associated Partner node, which includes images, logos, and videos. Additionally, a view was created to list all Partner Campaigns (another node type that is basically a link and an image to an external site) associated with the Partner.
Several flash files on the site pull in partner content using XML files. We used the Views Datasource module to do the heavy lifting, and modified the View theme to format the XML data in the fashion expected by Flash.
Flash
Various Flash elements on the site were developed by Biro Creative. Using Views Datasource, we were able to create XML and JSON files as needed to send data to the Flash files. For instance, the Major Moments Flash piece displayed prominently on the left of the Home page is populated with data from events/xml, a listing of Events built with Views + Views Datasource.
Widgets
Another important piece of development was allowing partners to create 'Widgets' that could be embedded on their own sites, which would allow remote user sign-ups and tallying of 'Pledges' by individual people. This was further integrated with Bronto for e-mail blasts. Each partner can control some elements of the display of their individual widget, such as the size, background colors and some copy.
Taxonomy
We wanted to override the core Taxonomy listing pages with Panels and Views, and ensure the links pointed to the overridden pages, such as TckTckTck Campaign Stories. To accomplish this, we wrote a little custom module, tck_taxonomy, which implemented hook_term_path, and worked roughly like the following. Note that we had originally considered using the Taxonomy Redirect module, but in addition to it seeming a bit heavy-handed for our purposes, we actually ended up needing to override the pages for some specific terms, not shown in the code snippet below, which is not supported by that module.
<span style="color: #000000"><span style="color: #0000BB"><?php<br> </span><span style="color: #FF8000">/**<br> * Implementation of hook_term_path().<br> *<br> * Ensure that Story Type terms point to the stories view rather than the<br> * default taxonomy term page listing.<br> */<br> </span><span style="color: #007700">function </span><span style="color: #0000BB">tck_taxonomy_term_path</span><span style="color: #007700">(</span><span style="color: #0000BB">$term</span><span style="color: #007700">) {<br> if (</span><span style="color: #0000BB">$term</span><span style="color: #007700">-></span><span style="color: #0000BB">vid </span><span style="color: #007700">== </span><span style="color: #0000BB">variable_get</span><span style="color: #007700">(</span><span style="color: #DD0000">'tck_taxonomy_story_type'</span><span style="color: #007700">, </span><span style="color: #0000BB">3</span><span style="color: #007700">)) {<br> return </span><span style="color: #DD0000">'stories/'</span><span style="color: #007700">. </span><span style="color: #0000BB">str_replace</span><span style="color: #007700">(</span><span style="color: #DD0000">' '</span><span style="color: #007700">, </span><span style="color: #DD0000">'-'</span><span style="color: #007700">, </span><span style="color: #0000BB">strtolower</span><span style="color: #007700">(</span><span style="color: #0000BB">$term</span><span style="color: #007700">-></span><span style="color: #0000BB">name</span><span style="color: #007700">));<br> }<br> }<br></span><span style="color: #0000BB">?></span></span>
For that to work, we also needed to let the core Taxonomy module know that we wanted to override the path. That happened like this (in tck_taxonomy.install):
<span style="color: #000000"><span style="color: #0000BB"><?php<br> </span><span style="color: #FF8000">/**<br> * Implementation of hook_install().<br> */<br> </span><span style="color: #007700">function </span><span style="color: #0000BB">tck_taxonomy_install</span><span style="color: #007700">() {<br> </span><span style="color: #0000BB">$ret </span><span style="color: #007700">= array();<br> </span><span style="color: #FF8000">// Set the Story Type vocabulary to use this module for paths.<br> </span><span style="color: #0000BB">$ret</span><span style="color: #007700">[] = </span><span style="color: #0000BB">db_query</span><span style="color: #007700">(</span><span style="color: #DD0000">"UPDATE {vocabulary} SET module='tck_taxonomy' WHERE vid=3"</span><span style="color: #007700">);<br> return </span><span style="color: #0000BB">$ret</span><span style="color: #007700">;<br> }<br></span><span style="color: #0000BB">?></span></span>
We used the same module to also place specific Stories in a menu tree related to their taxonomy. It was more compact (and easy enough) to do it this way than using the Taxonomy Menu module. Additionally, for some content types, such as Stories, we wanted the menu to reflect the taxonomy, while others, such as Partners, needed to be placed in another tree using a view unrelated to taxonomy. We chose to handle it all with an easy-to-manage function in the custom module rather than using a hodge-podge of methods for altering a menu tree by node type.
Workflow and Flags
The Workflow module was set up to create certain states, such as "Draft", "Pending", "Published", and "Archived". To assist with control of the editorial workflow, we used the Rules module, in conjunction with several Flags (using the Flag module). When a story is first created, it is unpublished. A page created with Views, shown here, which is visible only to users with the proper role, lists all stories and events, and allows the editors to sort and filter the view based on certain criteria, such as by Story Type (a taxonomy vocabulary) or whether it's been published.
The view also displays links to flag the content, clicking on which will also publish or unpublish the content. Conversely, using Rules (as shown below), publishing the content will also set the flag.
Tertiary Menu
One of the unique needs for this site was to display a Tertiary menu. Drupal core can display a single level of depth for the Primary Links menu, effectively creating a Secondary menu which is dynamically created from the menu tree accordingly to a page's placement in the hierarchy. For this site, we needed to display the menu for two or three levels deep. Additionally, according to the site map, a new 'Floating' menu needed to be created, which could also display items in the spot otherwise reserved for the Tertiary menu.
This required the creation of a custom module, which created a block to display the second and third levels of depth of a menu in the case of a page appearing in the Primary Links menu, and the first and second levels of depth of a menu if the page appeared in the new 'Floating menu'.
Development of this menu required digging deep into Drupal's menu API, exposing some weaknesses (some of which have been fixed for Drupal 7), and requiring a rewrite of a core function included with the module to handle both the display of the proper depth and expanded links when necessary.
Views
As usual, the Views module did most of the heavy lifting for the site. Some complex queries were easily created, allowing us to, for instance, grab the top five nodes from a specific taxonomy term, extracting the term from a path argument, and sorting by a flag time stamp.
For those interested, there was a lengthy discussion within the team about the pros and cons of using Nodequeue versus Flag for featuring content. In the end there seemed to be nothing offered by either module that couldn't be achieved with the other, with the possible exception of being able to list archived featured content (which Nodequeue can't do, but wasn't needed on this site), and the easy editorial practice of changing node weights (which Flag can't do without some customization using the Flag Weights module). In the end, we chose Flag, since it had already been set up that way, and could easily handle the required Subqueues of featured content per taxonomy term, though it was pointed out later by other members on the team that Nodequeue Subqueues can also handle that.
Panels
We used Panels 3 to place various view listing blocks on pages. Using contexts based on the path, passed to the relevant views, this allows the construction of quite complex layouts in a fraction of the time to write a series of queries and creating custom page templates.
For instance, the Story Type taxonomy term link redirects to a panel page that passes the path argument to three distinct views which list content in various formats: a top 'Featured Story' with a large image and teaser, the next four 'Recent Stories', with smaller images and teasers, and then a paginated list of five 'Archived Stories', consisting of a tiny thumbnail and title. The panel contexts also offset the view count, so that the first five nodes are skipped in the last view block.
Internationalization
From the beginning, the structure was set up to allow for internationalization and translation of content. The site needed to be available not only in English, but also in Spanish, Portuguese, Japanese, French, and Chinese. To achieve this, we enabled the Internationalization (i18n) module, and set up the required languages with the core Locale module. We also ensured that the node types allowed translation, and that each view was filtered on language, which allows for each view to pull in content for its own language. To help the editors, we installed the Localization Client module, which allows translating static text elements virtually inline. At the time of this writing, the editors were still translating the site, so the translated sections may not be visible to the general public yet.
Media
To assist editors administering content on the site, we installed the Vertical Tabs module (now part of core Drupal 7), and logically grouped fields within nodes as specific tabs, such as for Media, as shown here.
Embedded Media Field provided the ability to easily add and list videos, from YouTube and Vimeo in this case. We added a Video field to several content types, so that editors could simply paste the URL from YouTube, and Views created a listing of all videos, regardless of the node type. On the listing page at http://tcktcktck.org/video, which is again a panel page, the first view block displays a large thumbnail for the most recently flagged content with a video, and listings of more videos appear below. In all of these, we used Lightbox2 to display the video in a modal popup. (Note that the module also works natively with Thickbox and Shadowbox).
Wrap-up
There were many other features built into the site, far too numerous to detail in the short space allotted for this case study. For instance, we installed the WYSIWYG module, configured with FckEditor, we created custom Events listing views to display the events happening 'This Week', and there was work done towards creating a Mobile-friendly theme and internationalization. Finally, the whole thing was tweaked for performance, using a CDN, mod_rewrite, and the Boost module.
On Advomatic's team were Aaron Winborn (aaron), who created the views, panels, and some custom development; Dave Hansen-Lange (dalin), who handled the widgets, performance, and other custom development; and Amanda Luker (mndonx) and Jack Haas (jerseycheese), who themed the site. Dylan Clear (dclear) managed the project.
Advomatic is just one of the many companies behind the success of TckTckTck.org. Communicopia did the strategy and project management. Biro Creative's team produced the beautiful designs and flash animations. Capulet Communications developed and executed the social media strategy, much of which is to credit for the over 1 million pledges in the first week. Nitobi developed the mobile smartphone application. Last but not least, Hoggan and Associates is behind the blogging strategy. Advomatic succeeds both on its own and working with international teams and experts like we did on TckTckTck.
(Cross-posted at Advomatic.com)
Drupal version: Drupal 6.x