FusionDrupalThemes.com case study: Packaging & selling code with Project, Ubercart, and Organic Groups
In mid-2009, TopNotchThemes started building Fusion, a theme system that would pave new ground for Drupal themes. Along with this new technology, we started dreaming of our ideal website where products could be deployed automatically, customers had access to a much more friendly account area, and of course a brand new look and feel for this new line of themes.
Our current Drupal 5 website at TopNotchThemes.com (to remain active until remaining themes are ported to Fusion) is showing its age and does not have the control we need in order to be able to adapt content and features as our visitors demand.
Launched this spring, FusionDrupalThemes.com is not only a showcase for our products, but a wonderful showcase of community and commercial synergy. It integrates Ubercart, Organic Groups, and the Project module suite to create a feature rich platform for selling code-based products.
Team
TopNotchThemes -- design, theming, site building, contentGrowing Venture Solutions -- development, server administration3281d Consulting -- Project module integration, release packaging
Goals
- A new look and feel for our updated line of Fusion-based themes
- Enhanced community features to build a ecosphere for people using and developing with Fusion
- User dashboard for improved customer experience and communication
- Streamline checkout and improve conversion rates
- Easier updating and release of themes
- Better display of theme downloads and related files
- On-site customer ticket system
Major features
- Ubercart for e-commerce
- Project module & friends for release management
- Organic Groups for access control
- Panels, Views, & Fusion for display and theming
Design
The original design was created by TopNotchThemes. Co-founder Stephanie Pakrul (stephthegeek) created the branding and initial site design concepts, which were completed by an outside designer. Approximately 20 Photoshop mockups were created for different sections of the site following a series of wireframes.
Based on feedback from our previous site, we knew we wanted to go with a light background for any text-heavy pages, but use a dark background for theme pages and other main landing pages to better highlight the themes themselves. The bright light blue is used as an accent to bring some strong color to the otherwise monochromatic design. The heading fonts are Helvetica Neue Extended Light, and most icons are from the lovely Coquette icon set.
Special attention has been paid to the checkout section of the site. Font sizes on the Ubercart checkout page are increased, with large buttons, and a row of "checkout reassurance" blocks along the top. Stephanie has previously presented on the topic of increasing ROI in Ubercart at Drupal events, but the book Web Design for ROI has been very influential and is a must-read for anyone designing or running e-commerce or lead generation sites.
Several pages, such as the home page and "What is Fusion?" page, went through numerous iterations before settling on what you see now. In particular, it became important for us to immediately communicate the steps involved with fully taking advantage of a premium Drupal theme, an area of frequent confusion for our customers new to web site management or coming from other CMSes.
Theming
The site was themed mainly by Jeremy (eternalistic), one of our full time themers. The base theme is Fusion (duh!), using the 12 column grid option. In addition to the width settings already in Fusion, block/panel pane styles are set up via Skinr, so it is trivial to add the same rounded corner grey block style to a new block that is created. The dark pages are defined as page styles in Skinr, which adds a .dark-page class. Cufon is used for dynamic text replacement of the heading fonts.
An often neglected aspect of Drupal sites, the user/login and user/register pages have much of their content themed away (like the wordy descriptions below form fields), font sizes increased for better usability, text fields shortened, and a custom block floated right to highlight the benefits of registration.
Theming Ubercart is something we've become experienced with over the years. Product pages aren't really recognizable, between the Panels reconstruction and theming used here. UC Cart Links (included in Ubercart) is used to place an additional purchase link at the bottom of each theme page.
Theming the discounts section of checkout was a pain, because the additional lines from the UC Discounts Alt module are themselves added on the fly. We ended up using some advanced CSS selectors and jQuery to target this section in order to differentiate the styling of the last line from all the others.
We were aiming for very solid cross-browser support, but have used browser-native CSS properties in some cases -- so you won't see pretty rounded buttons in IE ;) Thanks to Fusion Core, the site is solid across browsers, with only some graceful styling degradation in IE6 where it was deemed unnecessary to fully support this oh-so-aging browser. The same tool we use for much of our internal theme browser testing was used here, a custom interface to LitmusApp.com's API.
Navigation & search
You'll also notice there are no local task tabs seen anywhere on the site. This was intentional, in order to streamline the user experience and get away from the pile of tabs seen on many Drupal sites (especially on user profiles when you add all the modules we've got). The Tab Tamer module hides these where it was not feasible through permissions alone.
Of course this means you need to provide a way for users to perform functions no longer available through tabs, but we did this by adding a "Forgot password?" link block to the user/* pages when not logged in, and an "Update your account details" and "Orders" link to the user dashboard.
Breadcrumbs are also not present, except in forum/*. Again for the sake of streamlining, we added a faux breadcrumb throughout the entire user and post-purchase section which simply directs the user back to the central location -- their dashboard.
Fusion integrates the Superfish dropdown menu script, so this was just styled with CSS per the design. We also use the Special Menu Items module in order to have top level menu items without links. Based on our experience with this here on our own site, we were also able to add Special Menu Items support to Fusion itself so that unlinked menu items retain their styling in your subtheme.
Taxonomy Menu is used for the documentation section. The FAQ and Documentation sections are both nodes of type "Documentation", but tagged under different vocabularies. We did it this way because it was important for us to make the docs very searchable and not siloed into different sections. For anyone who's ever had a question about a piece of technology, only to visit the company site and be presented with options for "FAQ", "Knowledge Base", and "Handbook" and have no idea what the heck section your question falls under -- this one's for you!
Using the FAQ module also gives us a page of categorized FAQ items with anchor links, and a completely painless way to pull in expanding question links from a specific section as needed, like on the Fusion PRO page.
Nodequeue & Taxonomy Smartqueue (included with Nodequeue) are also used to create the top level pages under each documentation section. It was important to have topics broken up into small chunks per node rather than one long page with tons of headings, so Nodequeue allowed us to curate the nodes and order of those top level pages. The rest of the documentation nodes in each category are linked with nodereference fields from relevant parent topics.
The site uses Apache Solr through Acquia Search. This makes search a breeze on a site with lots of text content where finding the right page to answer your question is critical. Solr also gives you "More like this" blocks which we use on blog posts and documentation nodes to cross-link resources.
Site building / development
With the exception of sections discussed below, this site mainly involved designers/front end developers running the show -- look out world! We had the excellent assistance of Greg and Ezra from Growing Venture Solutions, who we have a monthly support contract with for site/server maintenance and development. They really stepped up and helped us out with some additional hours, especially in the final stages of site building for tricky problems and custom development, so our team was able to focus on the theming, site building, and creating content.
But in the grand scheme of things, there is very little custom code on the site -- most is handled by configuration and CSS theming. We're happy to say that most of the module development time that was spent on this site went back into new or existing contrib modules (more on that later).
Views & Panels
The front page is powered by Panels, Quicktabs, and an embedded Views Slideshow. The user profile, product, and project nodes are overridden by Panels. Most of the content on these is straight CCK fields or views with arguments to pull in related content. The catalog page is a view with exposed filters in the right sidebar block.
User dashboards have a custom panel plugin for the "Fusion PRO" pane, which either shows promo text with a subscribe link if you do not have the Fusion PRO role, or notifies you of your expiry date if you are already a member.
One-off landing pages with unique layouts were also created with Panels, and given additional theming as necessary. For example, the What is Fusion? page is a 2-col-bricks layout that pulls in Mini Panels inside a Quicktabs block.
We use Semantic Views to make applying field-level styles much saner. For example, field views can get an h2.title applied to the node titles, and we can reuse classes for repeated styles instead of adding a huge list of view IDs and field classes to the theme.
Miscellaneous modules
- Forums are powered by Advanced Forum and custom theming
- We also use Forum Access to create a private forum, accessible only by admins and those with the Fusion PRO role
- Spam protection is by Mollom
- The Typogrify module provides typographical enhancements that add a bit of visual polish to text
- We use Mailchimp for sending an occasional updates email, the module and its Ubercart add-on make the subscription available on the registration and checkout forms
- The Notifications module was a real bear to figure out how to configure the way we wanted, but this is what powers thread and OG subscriptions (which we'll get to later)
- We're using the Path Redirect module to create our own aliases to point at for the downloads of Skinr, Fusion, and our free themes where relevant across the site. Why? Well, providing a download link that just sends a new Drupal user over to d.o/project/foo isn't particularly user friendly, but direct linking to a tarball with a release number that will always need updating isn't fun either. So we created our own /file/project-name aliases that we only have to update in one place when version numbers change.
A handful of other modules that just make life a little better in one way or another:
- Better Formats
- Redirect 403 to User Login
- Search 404
- Submit Again
- Term Display
- Vertical Tabs
- WYSIWYG / FCK Editor
- Insert
Ubercart
We process credit card payments through PayPal Website Payments Standard and Moneris, which both have payment gateways for Ubercart. Themes are set up like normal (non-shippable) products in Ubercart. The Fusion PRO membership is handled by the UC Role feature, which adds a custom role for a year to anyone who purchases the Fusion PRO product.
UC Discount Alt powers the 2-for-1 discounts for PRO members, which was also a challenge and took some wrangling (and patches) by Ezra to get working the way we needed it. We use the Ubercart Terms of Service module to show the License node on checkout, which Ezra also provided patches for.
Also the following modules:
UC Webform Checkout Panes for extra fields in checkoutUC Followup for reminders to In Checkout orders / for post-sales "how's it going?" type stuffUC MailChimp for product-level MailChimp integration
Tying it all together: Ubercart + Organic Groups + Project
Ok, this is where it gets a little confusing. If you're still with me, you'll remember that one of our main goals was to make the post-purchase experience much better for users. But, we're selling files, right? So why not use Ubercart's built-in file purchase feature?
Well, this is what it looks like when you buy access to files through Ubercart:
And this is what we have now:
Small improvement, eh?
As our customers will kindly attest, we're not just selling a theme -- we're selling a new face for you or your client's website. That's more than just a tarball, it's multiple file formats, documentation, release notes, a support community, Photoshop files, stock images and icons, info about the styles in the theme, and a reliable way to get help if you run into any problems. These files also update regularly as we upgrade themes, and we needed a way to add new releases and tell customers about them! Manually zipping up files, FTPing them to the server, and BCCing a list of customers pulled from PHPMyAdmin really wasn't cutting it anymore -- we were spending too much time dealing with theme updates, which discouraged us from doing them in the first place and made the task unpleasant and error prone.
After we brought him on board to help us with the Project side of things, Derek Wright had the brilliant idea to use Organic Groups for access control and organizing theme releases. Roles weren't feasible because we'd soon have dozens of them. OG enabled us to have much more complex landing pages for purchased products and leverage all the things that came with it.
Michael Prasuhn wrote the UC OG Subscribe module for us, which ties together Ubercart product purchases with Organic Groups memberships, powering access to purchased themes. Then OG Project provides a bit of glue for Projects as Groups.
So...
Nodes of type Product = regular Ubercart product node, connected to OG through UC OG Subscribe feature
Nodes of type Project = Organic Group node (ie. the theme name), landing page for a theme.
Nodes of type Project Release = allowed to be posted to OGs (these are theme releases with file downloads and release notes)
Nodes of type Project Issue = can be created by customers, live outside of groups, and are accessible to admins and node author only using the Private module.
Here's the main Project issues view our team uses to manage customer tickets.
All groups are private and closed, so only members can access them. The Notifications module provides update emails to members automatically when new content is posted to group (ie. new theme releases are published).
The nodereference between the Product and Project node also allows us to pull in related content through that relationship. For example, there is an imagefield for "theme styles" on the product node, which is the screenshots of Skinr styles available in that theme. This field displays as text links on product nodes, which open into a lightbox gallery (using a little Views field rewriting magic with the title="" value). These same theme skin images from the Product node are pulled in to the Project area for customers, as documentation to show them all the styles in their theme.
Automatic release packaging with Project
All theme code lives in our own SVN server. Each theme project points to a specific SVN directory. Just like on drupal.org, each release node represents the state of the code for a particular directory and a fixed point in time (instead of CVS tags, we can just use SVN revision numbers). A script runs as another user (outside of the web root) every 5 minutes, looking for unpublished release nodes without files.
This automates a lot of tasks that we used to do manually (both tedious and error-prone), creates release package files, attaches the files to the release nodes, and publishes them.
It works like this:
- Check out the code from a specific SVN revision & directory
- Remove any files checked in which shouldn't be released (*~, *.bak, *.psd, thumbs.db, etc)
- Modify the .info file(s) included in the theme:Provide accurate version and core settingsInclude metadata required by Update status
- Checkout a shared documentation directory
- Write the release notes (body of the release node) to a file
- Convert all text files to UNIX line endings
- Create a .tar.gz package
- Convert all text files to DOS line endings
- Create a .zip package
- Update the release node with all the data about these two files (name, size, md5 hash, datestamp, etc)
- Publish the release node
Integration with Update Status
All .info files include metadata that Update Status needs to provide update notifications alongside a user's other modules and themes. Derek's efforts also improved the script we use on drupal.org to create the release history XML files to support only generating history for a single project at a time, triggered at the end of the packaging script (fixed a long-standing drupal.org bug: #184418: "update(_status) results stale for up to 6 hours").
We can also turn on the project_usage module and installed the script to serve the release history XML files and record anonymous data. A cron job runs periodically to process the usage stats and provide usage data listings, just like drupal.org/project/usage
Public vs. private file downloads
Generally, we wanted public files for performance and simplicity, but obviously need to protect the release files that people purchase. Thus, all release files live completely outside the webroot. Derek wrote a small script that bootstraps Drupal, checks the URL query string for a filename, sees if the current user has access to view the release node the file is attached to, and if so, serves the file to the user (using XSendFile if supported by Apache).
There's already a setting in project_release to rewrite all download links to use a different prefix (e.g. for ftp.drupal.org), so we just re-used that to point the downloads to this script.
Release Views
This project made it possible to expose a bunch of complicated things to Views with a combination of cleverness and data denormalization. Views2 makes it so easy (if you know what you're doing) to accomplish very complex tasks with only a few lines of code.
Derek has these tips:
- Really understanding relationships is key to so many things
- Views field rewrite and token system is amazing
- Handlers are a perfect example of why Object Oriented Programming (OOP) makes sense in a lot of cases
He also started converting all the hard-coded stuff like the "Releases" table on drupal.org project nodes to use Views, instead (which will help with the drupal.org redesign).
Improving community plumbing
This project had a number of benefits for drupal.org and the community, some of which have already been deployed on drupal.org:
- Fleshed out support for both .tar.gz and .zip files:
Multiple files attached to each release node
Much better Views support in project_release
Packaging script logic for UNIX vs. DOS line endings - Lots of fixes for the og_project module to pave the way for drupal.org project nodes to be Organic Groups
- Fixed the update status XML script to avoid stale results
- Improved token support in Project* to play more nicely with pathauto and friends
- Lots of smaller bug fixes, clean-ups, and improvements to help get closer to the 6.x-1.0 official releases of Project*
SEO
We use the basic modules for SEO that pretty much any site should be using: Global Redirect, Pathauto, Page Titles, Meta Tags, XML Sitemap, Path Redirect.
We learned a lot about Drupal SEO from Volacci, who we worked with on TopNotchThemes.com, and we were able to apply a lot of these techniques here on FDT.com.
Documentation is split up amongst many nodes, rather than putting a lot of subheadings on a single page. This allows a longer tail of more targeted pages, and they're interlinked with the "More like this" links. We've tried to make good use of subheadings, keywords in page titles, internal and external link keywords (notice the "Drupal themes" linked in the footer), and for related nodes. We are members at seomoz.org (highly recommended!) and use their tools to evaluate and tweak the site.
When we launched FusionDrupalThemes.com, we took steps to keep it and TopNotchThemes.com separated so search engines don't treat them as from the same company. Separate hosts, domain registrars, and limited interlinking between the two helps. We hope eventually to rank on page 1 for both sites for "drupal themes".
But when you've got the basic technical details down, really it's all about creating awesome content :) We've tried to do this with our blog and lots of great documentation, but also guest posts on other blogs, and more specifically projects like DrupalIpsum.com.
UX/CRO
This is an ongoing struggle we're currently focused on -- improving our conversion rate, especially focused on usability through the checkout. Some initial steps include stripping out all extra blocks in the checkout process, providing callouts of key "customer reassurance" text at the top of the checkout, removing unnecessary fields, and increasing the form/text size and buttons.
We're now working on landing pages, topic-specific pages on things like Ubercart, SEO, etc. Then we can target these in search engines and link campaigns, and do some email autoresponders to provide a steady stream of helpful info.
Performance
The site is hosted on a 1GB CentOS slice at Slicehost. We use Total Server Solutions to manage our VPS -- they're awesome and for $75/mo handle random server tasks for folks like us who aren't hardcore devs or sysadmins.
We use Drupal's built-in aggregation features, as well as Authcache. We ended up with quite a list of paths that needed to be excluded from Authcache to prevent various errors (XML Sitemap, PDFs, etc) and incompatibilities (like with Forum Access), so I've pasted these paths to exclude here in case it helps someone else. We use a static shopping cart block in the header right now, but will update this with the necessary code to make it dynamic at some point.
We also use sprites for all the icons, corners, etc. on the site to reduce the number of page requests. Another tip is to use ImageCache Actions to convert PNG thumbnails to JPG, which drastically decreases file sizes for smaller images. That alone cut our page sizes nearly in half.
Future goals
Most of our future goals for the site involve more themes and more content :) But on the site building side, there are a few things we're looking ahead to working on:
- A/B testing for front page, key landing pages
- A better UI for users to manage notification subscriptions/newsletters
- Allow anonymous issue posting, so we can use Project to manage all incoming queries
- Improve checkout validation -- we may switch CC processors to have less trouble with international transactions, and see what we can do to have better inline error handling, form field validation, messages, etc. during checkout
Lessons learned
Here are some of the top things we learned during this project:
- Detailed IA is time consuming, but worth it! It has made expanding the site content so much easier over time, without feeling like bandaids
- Multiple node access modules is tricky, test as much as you can and it is really helpful to have a developer who is proficient at debugging
- Don't assume that modules work the way you think they will out of the box. We ran into this so many times, especially with user-facing stuff like discounts, notifications. Module descriptions are helpful but often the developer's idea of a feature is pretty different from what you have in mind...
- It always pays to learn more about Views
- Don't try to build a site while continuously rebuilding its base theme :) We were building this site during the pre-alpha stages of Fusion and re-implemented things a few times... not fun and I'm sure we have much messier CSS than we could.
- Drupal is amazing for non-programmers but small bits of custom code can go a long way. Those little bits of glue can bridge big gaps.
- Whenever possible, go with the option that makes the site easier for you to maintain later. Your future self will thank you for it and you'll be able to adapt and react as needed.
- Contribute back to the modules you use. It's not just good community karma, it's good business sense so you don't have to maintain custom code, it gets extra testing, and Drupal as a whole improves.
- Leave lots of time for testing (especially for browsers, performance, and when you have payment and access control schemes to consider)
Presentation / video
I also presented this case study last week at the San Francisco Drupal User Group meeting. Video and slides from this meetup are posted on our blog.
Drupal version: Drupal 6.x