A New W3Counter, Again

About a week ago, I started working on a rewrite of W3Counter from scratch, with a new data model and a new business model. These are going to be the key changes:

  • Silex instead of Symfony 1.x frontend (it’s that old…)
  • All the data collection’s moved to Node.js, not just the real-time stuff
  • No more requirement of displaying a badge or counter on a site to get free stats
  • No more ads on reports, even for free accounts
  • Rather than a 15,000 pageview log per website, it’s 30 days (free) or 12 months (paid) of data retention
  • Upgrades are available per-website instead of per-account
  • New “business” plan adds campaign and conversion tracking to the reports

I’m enjoying tossing lots of almost 10-year-old code. Coming soon.

The Most Valuable Lifecycle E-mail

At Improvely, there are a variety of e-mails customers receive depending on how far along our relationship is. For example, new users receive a welcome mail outlining how to get started and introducing me, trial accounts that aren’t set up get gentle nudges towards the next step, and users that haven’t logged in recently get occasional educational mails showing them how to get the most value from their accounts.

One thing some companies forget is that the customer lifecycle doesn’t end when a customer cancels their service. Customers that cancel are not lost forever. People cancel subscriptions for all kinds of reasons including not having enough time, temporary financial issues, organizational changes, testing alternatives, to personal issues. Many, if not most cancellations aren’t because the customer didn’t like the product!

The most valuable lifecycle e-mail I send is responsible for over $10,000 in added recurring revenue, and I only started sending it this year. Here it is:

Why does it work? People that have used Improvely in the past are my most valuable leads: they already know what Improvely is, know how to use it, have seen the benefits, and cost nothing to acquire. They’re sitting in the customer database already.

Reaching out occasionally makes sure they don’t forget about Improvely when they’re ready to use the service again. I keep the template updated with the latest and greatest features past customers may not have tried, along with occasional discounts to tempt those users that are price-sensitive or need that discount to nudge them over the edge to activate their subscriptions again.

If you’re not already reaching out to past customers, start doing so and you’re virtually guaranteed a boost to revenue and customer lifetime value.

A New Date Range Picker for Bootstrap

3 years ago, along with Improvely, I released an open source Date Range Picker JavaScript component designed to work with the Bootstrap CSS framework. Tens of thousands of downloads, 4000 stars, 1200 forks, 482 commits, and 288 pull requests later, it became … a mess. With so many overlapping pieces of code shoved in a hundred different places to support this new setting or that, it became impossible to add anything else, or to track down and fix bugs without causing new ones elsewhere.

Today I pushed version 2 to GitHub. This was a near complete rewrite I spent the past few afternoons doing. It’s not perfect, but it’s better. I fixed a lot of bugs, added a bunch of sanity checks to help reduce future ones, and generally built a better base to work from going forward. With a new major version came a few breaking changes for current users: some options were renamed or moved, and methods renamed or removed. The documentation’s all been updated.

I pulled all the easily merged pull requests into v1 and made one last release earlier in the week. All other pull requests and issues, some of them years old, have been closed. A blank slate. If you had an open PR or issue and it’s still an issue in the new code, I’m sorry for the inconvenience, and you’re welcome to try again.

Please go download, test, and tell me how it’s broken.

Thinking About Starting a Tech Business?

A recommended reading list, as someone requested of me today —

PNC Bank

This is a rant: Apparently 10 years as a customer and over $1000/day in deposits doesn’t make me valuable enough to hold an ATM card at PNC Bank.

The debit card that came with my business checking account expired in March. I realized that when I tried to deposit a check at a drive-up ATM and it spit the card back out at me saying that it was expired. I figured I must have accidentally thrown out the replacement card as junk mail at some point, and called the number on the back of the card for the business support line.

The friendly CSR on the other end couldn’t find a debit card attached to my account. He eventually found the expired one, and a note that it was not reissued because there were no charges on the card in the last few months.

I guess that’s the standard now. Not what the contract says. Not what PNC’s website continues to say (“Free PNC Bank Visa Business Debit Card” as a feature of every business checking account). Don’t charge expenses to the card? You don’t get to use ATMs. Not worth the $1.11 in plastic and $0.49 in postage every 3-5 years.

Tomorrow, when I can visit a branch, as they all close at 5PM and it’s already 5:30, I’m supposed to beg a manager to personally order a card for my account. I’m tempted to close it instead.

“Smart Home”

I have a 10 inch tablet mounted on a wall near the entryway of my house that controls the first floor lights, doors, garage and temperature. It monitors motion sensors to automatically lock up for the night when I head to sleep.


How to build your own? Belkin WeMo, Nest, MyQ, Nexia and Vera.

A little node.js server runs on the tablet to talk to the Vera’s API to poll and control all the various devices.

It’s fun stuff to play with if you can afford all the pieces. The other colored buttons along the bottom switch views to various business dashboards.

Refreshing Improvely’s Design

Improvely‘s growing up. It’s now lovingly used by hundreds of marketing agencies and small businesses, with subscription revenue doubling every few months. Billions of website visits, ad clicks, leads and sales have been tracked. Dozens of new features have been added over the nearly two years since its launch.

The design, however, has remained the same since summer 2012. Over the long holiday weekend, I decided to tackle a design refresh of the entire app, with a few simple goals:

  • Upgrade from Bootstrap 2 to 3
  • Upgrade from Font Awesome 3 to 4
  • Switch from writing straight CSS to Less
  • Increase the default width of the site to accomodate a few extra columns in important reports
  • Reduce common confusion points by rearranging and rewriting some key screens
  • Add a notification area for in-app updates and alerts, like new features or billing issues
  • Make the project list, the first screen heavy users see upon logging in, clearer and re-orderable via drag-and-drop

I managed to get everything done and tested in 4 afternoons, including a trip to Best Buy to steal a few minutes on their iPads for testing the responsive breakpoints. While there’s still room for improvement, everything looks a bit cleaner, brighter, and more consistent now, as well as adding room for a few new metrics on the overview and traffic performance reports.



P.S. A customer sent along this great link describing why revenue per person is a great metric for companies to keep an eye on. Improvely keeps track of it automatically for every single ad and other traffic source.

10 Years of W3Counter

W3Counter is turning 10 years old.

Of the dozens of sites I put together in 2004 and 2005 from my college dorm, W3Counter’s the only one still around aside from this blog. It’s rather popular still — with around 70,000 users acquired completely organically and billions of page views being tracked — despite the explosion of competitors in the now enormous analytics industry. I’m sometimes asked why Google Analytics didn’t kill it — I think that has a lot to do with the fact that “easy” and “fun” are rarely used to describe GA, but I hear them used to describe W3Counter all the time. There’s a high school teacher that has his entire class sign up for accounts every year after creating their own webpages — they get a kick out of seeing the counters, and it’s easy enough to set up that it takes most people just a minute or two.

Every 2-3 years I’ve given the site some needed attention to keep up with the times. The architecture’s gone through several major revisions — from running on a single VPS to several servers, to a short stint running in Amazon’s Elastic Compute Cloud, then back to bare metal servers at SoftLayer. 2014’s users demand two things, at least if I care to keep some portion of them upgrading for the paid perks — real-time dashboards, and a mobile site.

Tracking Active Visitors in Real-Time


Handling even a few thousand concurrent visitors pinging the service every few seconds with their current activity to run these dashboards necessitates something a little more efficient than the way W3Counter was originally programmed — a traditional PHP MVC application, with the Symfony framework on one or more frontend servers, talking to one or more backend database servers that store data about page loads from which the reports are generated. All that framework overhead and database communication can take 40-50ms to finish.

The code that collects data for the dashboards cuts that down to under one millisecond. It’s a node.js application, which bypasses all the overhead of the PHP framework. Redis, an in-memory key-value store is the first thing that code talks to. Redis caches information I’d otherwise need a database lookup to get. While MySQL has its own query cache, using it would still require a round-trip to the remote database server, and having the spare RAM on the database servers to dedicate to that.

The information on what all those active visitors are doing still sits in a MySQL database, but an entirely in-memory one on the front-end servers using the MEMORY storage engine. Unlike the database servers, my front-end web servers typically use less than 25% of their available RAM — they’re CPU-limited rather than memory-limited in their capacity — so keeping the ephemeral data for these dashboards there is just using otherwise unused resources.

By keeping the code efficient and only storing data in memory, one relatively low-end server can serve several thousand concurrent active visitors with negligible load. The only problem I actually ran into was the raw number of TCP connections. They came in faster than nginx was accepting them — I needed to increase its worker_rlimit_nofile and worker_connections parameters to handle more. There were still more than the OS was happy to handle, complaining through the messages log that I was under a SYN flood attack — no, it’s not an attack — until I increased the available local port range and SYN backlog size. I quickly became friends with the sysctl command.

I’m a fan of dashboards myself. W3Counter’s Pulse Dashboard for Improvely runs in a rotation on a screen in my living room along with dashboards from Geckoboard, New Relic and my self-built home automation system for controlling lights, locks and temperature in my home. I’ll have to write about building that some day.

Mobile Web Design

I was also, a bit reluctantly, forced by increasing mobile use to finally learn responsive web design. I still haven’t got it quite perfect, but W3Counter’s now usable on any screen size between your 4″ smart phone and 30″ monitor without half the screen being whitespace, like some vertical equivalent of the black bars on a 4:3 TV watching a letterboxed movie.


Various reports switch from multi-column to single-column layouts at smaller screen sizes, and menus disappear into a touch-friendly button-activated dropdown at the top of the page.

Most of the credit goes to Bootstrap 3’s responsive grid and “collapsible” plugin, along with a smattering of hand-written media queries that even work on IE8 thanks to Respond.js. Nobody’s running IE8 on their phones, but without that library, it shows the mobile version of the site which doesn’t look so great on a 20″ monitor.

A Minimal Website

I also redesigned the marketing site for W3Counter to match the new look — responsive, mostly flat aesthetic, using the same two shades of blue (#c1deef and #e1f3fd) as I’ve used with W3Counter since around 2006.

I found that most pages of the old site were rarely if ever viewed, so why have them at all? I trimmed it down to just 3 — a homepage with a giant image showing off the reports and signup button, the monthly browser & OS market share report that gets quoted in news at least a few times a month, and a signup form.

So far so good — I published the new design three days ago. Only one user wrote in with a note that they didn’t like something I changed. The daily signup rate has doubled. Several of them upgraded to paid accounts within minutes of signing up. 2014 should be another good year for W3Counter.

Excuses for Lazy Coders

When Walker put the objects, along with their accompanying stories, up for sale on eBay, the results were astonishing. On average, the value of the objects rose 2,700%. That’s not a typo: 2,700%. A miniature jar of mayonnaise he had purchased for less than a dollar sold for $51.00. A cracked ceramic horse head purchased for $1.29 sold for $46.00. The value of these formerly abandoned or forsaken objects suddenly and mysteriously skyrocketed when they were accompanied by a story.

If You Want to Raise Prices, Tell a Better Story