TwentyTen CRM

This theme is here for archival purposes only. My CRM that’s actively developed is Genesis CRM.

Download the theme on GitHub

by Bill Erickson, Andrew Norcross, Jared Atchison


TwentyTen CRM is a child theme for TwentyTen specifically designed as a Customer Relationship Management tool. It creates a series of taxonomies and custom meta boxes to collect relevant data, displays the data in a useful Dashboard page template, features a Download page template that can be used to copy/paste all the data to Excel for more advanced analysis, and is easily customized to your specific needs. Oh, and it’s free.


About six months ago I started to become overwhelmed by the number of prospective client inquiries I received. It’s a great problem to have, but a lot of prospects were falling through the cracks. I tried Salesforce for about a week, and SugarCRM for about 3 weeks (I must thank Schipul for spending an afternoon walking me through how their company manages their contacts with Sugar).

The two problems I had with all of these CRMs were that it was difficult to put the information I wanted in the system (and leave out the information I didn’t care about), and it was difficult to analyze that data. I wanted a tool that I could customize to my own needs and modify as time went on. As a WordPress developer, I chose the tool I’m most comfortable with.

This theme isn’t perfect for everyone, but it can easily be customized to your specific needs using standard WordPress code, which is exactly what I wanted. I recommend you see this as a starting point, not an end point.


First, due to the type of content we’re putting in this site, I highly recommend you either run it locally, or use a plugin like Registered Users Only to ensure it isn’t public.

  1. Download the theme
  2. Add it to your themes directory and activate. Since it is a child theme of TwentyTen, you must have TwentyTen in your themes directory as well.
  3. I recommend you fill in the Categories, Points of Contact, and Sources taxonomies first.
    1. Categories must contain Prospect (slug “prospect”), Active Project (slug “active-project”) and Closed (slug “closed”) to function correctly. Alternatively  you could modify the theme files to use different categories for the sections of the Dashboard.
    2. I use Point of Contact as the method the client initially contacted me (Email form, Email, Phone…). I’d recommend you only use one POC per project as it will mess up the stats in the dashboard if you use multiple.
    3. I use Sources as the person or website that sent the prospect to me. Mine include CodePoet, StudioPress, DIYThemes, Google, Other Referral (you can specify the Other Referral in the custom meta boxes), Unknown…
  4. Go to Appearances > Widgets and populate the three homepage widget areas with widgets. I recommend “Old Prospects” in Column 1, “Active Projects” in Column 2, and everything else in Column 3.
  5. Start collecting data! Just go to Posts > Add New to add a new prospect.


While my default setup might work fine for you, one of the best features of this theme (and WordPress in general) is how easy you can customize it.

There’s two features you should attempt customizing: Taxonomies and Custom Meta Boxes. Note: I’m assuming you are a web developer and are already comfortable coding these types of things. If not, you might want to hire someone to do it.

Taxonomies – Go to twentyten-crm/functions.php. On line 93 you see // Register Taxonomies. This is the code I’m using to create the taxonomies. You can modify the two default taxonomies here, or create additional ones. See the Codex for more information. And of course you can add additional taxonomy terms using the appropriate section of the backend (ex: Posts > Sources).

Custom Meta Boxes – I’m using a wonderful piece of code that Andrew Norcross recently contributed to generate the meta boxes. To see all the meta box options you have, go to /twentyten-crm/lib/metabox/example-functions.php. To modify the existing metaboxes or add more, go to /twentyten-crm/functions.php on line 165.

Once you’ve modified the data you collect on the backend, you’ll want to modify the frontend display of that data. Here’s the three files you should edit:

  • home.php – This is the Dashboard page template.
  • download.php – This is the Download page template.
  • single.php – This is the Single page template

Looking through the code on those pages, you should be able to figure out how to add what you want.

More Customization Tips

  • We’ve added a “Top Panel” to the top that gives you two menus, both editable from Appearance > Menus. If you’d like to replace this with the admin bar (assuming you’re running WP 3.1), uncomment lines 523-525 (look for “Top Panel instead of Admin Bar”).
  • The post editor has been moved into a meta box so you can drag it around and put it wherever you like. If you don’t want to use it, click Screen Options and uncheck “Notes”.
  • I’ve created a bunch of useful widgets for the homepage. If you’d like to create your own, just put them in the /lib/widgets folder. I also added two hooks that some of the widgets use: crm_pre_stat_loop and crm_stat_loop. This loop goes through all the posts in the site and is used to calculate statistics. If your widget needs to loop through them as well, I’d recommend using this instead of doing your own loop in your widget. This way there’s only one loop rather than one for each widget. Look into a widget like widget-other-stats.php for an example on how to use this.


  • 1.3 (2/21/11) A large release with many changes. Here’s a few notable ones:
    • Made the dashboard the homepage (so you don’t need to create a page, set page template, then set as homepage). Widgetized the homepage so you can control what boxes show up where.
    • Lots of tweaks to the backend. Moved post editor into meta box, renamed “Post” to “Contact”, reordered/removed admin menu items, removed dashboard widgets (will create some in a future release), and customized the Contacts column view to include Status, Point of Contact, and Source.
    • Cleaned up the code so it runs better. It should work with debug mode on now! (Thanks Mark Jaquith for the tips)
  • 1.2 (2/5/11)
    • Added isset() to variables in /metabox/init.php and improved method of hiding post editor, based on recommendations by Mark Jaquith
    • Used global variable $prefix to be used in generating custom fields in meta box as well as in the page templates. If you want to use a different prefix, change it once without editing a bunch of files.
  • 1.1 (2/3/11) – Updated the metabox code based on improvements by Jared Atchinson
  • 1.0 (1/31/11) – Initial release

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson


  1. Josh says

    I spent some time and I’m really digging this tool – thanks so much again Bill. One thing I might mention for a release for the future is that I ended up adding a “Clients” widget. I thought maybe you were bouncing between prospects and active projects so I wasn’t quite sure if I was interpreting how that workflow would happen.

    So instead I have “Prospects” which are just strictly leads. Once I convert them they turn into Active Projects, and then when I’m done they become Clients.

    May or may not be helpful for anyone but I thought I’d mention it.

    Thanks again for all your great work!

  2. Christine Green says

    How can I get the Prospects to show up either immediately or in 3 days rather than 10 days?

    • Bill Erickson says

      You’ll need to edit the widget (/twentyten-crm/lib/widgets/widget-old-prospects.php ).

      For the last 3 days, on line 34 change strtotime(‘-10 days’) to strtotime(‘-3 days’). For all prospects, just remove or comment out that whole line.

  3. Jim MacDonald says

    Thank-you bill for TwentyTen CRM. All is working fine but can’t seem to get search, archives and results showing up on 2 pages. Active Prospects and Prospects. How do I fix?

    Error if search is done. And same error message if clicked on Archives.

    Parse error: syntax error, unexpected T_ISSET, expecting ‘(‘ in /xxxx/xxxxx/public_html/prospects/wp-content/themes/twentyten-crm/loop.php on line 21

    Here is line 21 & 22 from loop.php

    The pages: To get the download link to show results a download page was created. However if a page is created for Active Prospects, Prospects, Results still no prospects show up on the pages.

    10 day & older Prospects and Active Prospects do show on on the “home data/stats page”, just not listing on their separate pages.

    Thank you.

    • Bill Erickson says

      isset is throwing an error? That’s really strange. Try deleting lines 21-25 (it’s basically a notification that the current post is in the trash).

      You’ll need to create custom page templates for those as well. I’ve built the page template for Downloads but not any others. You can use category archives for things like Prospects and Active Projects (/category/prospects) but if you want to do any custom query like prospects that are 10 days or older you’ll need to do a custom page template for that. Take a look at /lib/widgets/widget-old-prospects.php to see what the query for that page should look like. First you’ll do a query for all prospects, then you’ll skip ones that are not 10 days or older: if ($post->post_date > date(‘Y-m-d’, strtotime(‘-10 days’))) continue;

      • Jim MacDonald says

        Thanks for your speedy help bill. Search is working like a charm. Removed lines 21-25 as suggested plus 2 26 &27.

        Gotcha with the pages understanding. Thanks.

        • Jim MacDonald says

          Wow. Got it looking pretty using Meta Box’s and widgets after mucking around with it. Getting a simple, easy to mold into your own prospect processing system. Yet a powerful prospect flow by answering status, summary, reason and action. Cool.

          Then I blew it up – it’s when all is going fine but it’s been a long day and you get lax on making back ups of changes. And all I was doing was putting in text.

          After blowing it up, it had changed back into a regular wordpress dash board.

          Up loading a fresh copy functions.php from download brought it back. But when clicked on widgets it says it “Isn’t Widget Aware – No sidebars defined. Browsing to home page and there are three column text but no links. No links in drop down box either. (Functions.php has the links and stuff about set up, so I though a fresh up load would fix.)

          All my “Status Categories” and and (testing) contacts entered into twentyten-crm are there but are unable to show because widgets don’t show up to set up.

          I’ve ftp new fresh php pages from download functions, single page even loop and header and footer even styles. What file should I ftp to get widgets showing back up?.

          Thanks Bill – Can’t wait to get TwentyTen-CRM purring again.



          • Bill Erickson says

            Hmm that’s strange. The sidebars are defined in functions.php so I’d start there. Look at a blank copy of twentyten-crm and ensure you have the same code for sidebars. If that doesn’t work, I’d install a new copy of twentyten-crm and slowly copy/paste your changes from the original. When something breaks you’ll know that’s where the error is.

  4. Christopher Ross says

    Wonderful Bill, I’ve been using this off and on for a couple months now and can’t tell you what a pleasure it’s been.

  5. Alex says

    This is great! It’s a bit limited for what I need personally, but that you’ve done it is fantastic. Any thoughts on having a capability of tying in a contact form functionality in here so that when someone submits a request, it auto populates the data in the CRM?

    • Bill Erickson says

      I’m actually doing that right now with my contact form 🙂 When I get back from vacation I might write another post on how to do it, but here’s a quick summary:

      – Install “Gravity Forms” and “Gravity Forms + Custom Post Types” on your CRM site
      – Create a form with all the fields of your contact form you’d like filled out. You’ll want to make most of them post meta or taxonomies. You can also have hidden fields (I’m using that for Date of Inquiry)
      – Create a page called Form and add the contact form to it
      – Create a page template called template-form.php and remove all style from it (we’ll be embedding this page)
      – If you’re using Registered Users plugin to prevent others from logging in, use a filter to exclude the form page from the login restriction (or else your iframe will have a login box). See code below
      – Either drop an iFrame into your contact page or create a page template on your real site linking to your form page on the CRM site.

      // Exclude Form from login
      add_filter('registered-users-only_exclusions', 'crm_form_exclusion');
      function crm_form_exclusion($exclusion) {
      $exclusion[] = 'form';
      return $exclusion;

  6. Greg Turner says

    I am just now discovering this theme. Thank you very much. I am considering a couple of modifications that I’d like to have to make it more useful to me. I am not sure I have the time to implement, nor how difficult it would be, having not yet looked at the code.

    I’d like to have:
    1. Every prospect/client has available to them a page(s), password protected, that allows them to view info about their project, as well as allowing them to communicate to me instead of using email.
    2. Being able to have multiple projects per client.

    I welcome any comments on my desired modifications. Doable? Feasible? What do you all think?

    • Bill Erickson says

      It’s doable, but would require such heavy modification that your best bet would be to build it from scratch. I’d recommend building that on top of BuddyPress, since BP has private messaging, groups, and extended profiles built-in. Instead of having a custom post type called Contacts, you would create a new user and have all the client data associated with that profile. You could then create a custom post type called Projects, or repurpose something already in BP like Groups for it.

  7. Vijay Sharma says

    Excellent Theme Bill. I just started playing with this child theme and the experience is completely delightful. I will post more comments once I try more hands on this theme.

  8. kate says

    Is there anyway that this can be used by multiple users where contacts are ‘owned’ and only seen by the owner?

    • Bill Erickson says

      It’s not currently designed that way, but it shouldn’t be difficult to implement since all the posts have an author associated with them. You can probably just modify the default WP Query to only show posts by the current user.

        • Iñaki says

          Hello I would like to download your CRM, but the link is broken. Is there any way you can get it.
          Thank you for your contribution and a greeting.

          • Bill Erickson says

            I’ve updated the post with the correct URL. Note that this theme is no longer developed, and I recommend you use the more recent CRM theme – Genesis CRM.