When I started looking for a licensing solution for my Windows desktop application, Text2Go, I came up with the following requirements.
- Must not be hardware-locked. I didn’t want a support call every time someone upgraded their PC and they needed a new license issued for their new hardware.
- Must be simple to activate a license. Entering a 32 character alpha-numeric license key always seemed very tedious and error prone.
- The license should contain some personal information, such as the customer name and address. This would hopefully discourage customers from ‘sharing’ their license with others if it could easily be traced back to them.
- Must be a .NET solution as my app is written in C#.
- Being a microISV, the license system must be reasonably priced.
After lots of research I found the perfect solution in .Net Reactor. Instead of using license keys, it used a license file. You could embed all sorts of arbitrary customer information in the license file which could be extracted and displayed in your application. Not only did .Net Reactor provide a licensing system, including support for trial periods, but it also offered quite sophisticated code obfuscation and protection. It was a complete solution and it was very reasonably priced at ~$200.
In order to embed customer information into a license file, the license file had to be generated at the time of purchase. It’s obviously not possible to pre-generate licenses if each needs to contain personal information. This meant some sort of integration with the payment processor was required. Luckily .Net Reactor provides a license generator for ShareIT. As soon as an order is processed, ShareIT runs the license generator to create a personalized licensed file, which is then emailed to the customer.
Choosing the .Net Reactor licensing system meant that it made sense to choose ShareIT as a payment processor. I was quite happy to do this. Their fees were reasonable and they provided all the features I needed.
Now you may be thinking that this is a very neat solution that ticks all the boxes. For a while I believed this to be the case to. Customers purchased Text2Go and their personalized license file was emailed to them automatically. They didn’t need to enter a long license key. Instead they only needed to save the attached license file into the same directory as my application and restart it.
What could be simpler than that? Well a lot of things it turns out, including entering a 32 character alpha-numeric license key.
Early Signs There’s a Problem
I started to get the odd email from customers who couldn’t work out how to license Text2Go. Initially I just sent them a short email explaining exactly what to do and this fixed their problem.
At the time I assumed the customer simply didn’t bother to read the instructions they received in their license email. One of the problems was that although ShareIT allows you to customise the license email sent to the customer (i.e. so you can include clear instructions on how to license your application), they insist on including a huge amount of their own legal jargon both before and after the customisable section. This means the email sent to the customer ends up looking like the fine print for an insurance contract. I don’t blame anyone for taking one look at it and thinking I’m not going to read this.
I contacted ShareIT and asked if it was possible to fully customise the licensing email sent to customers. Their response was a flat no. They didn’t even promise to consider it as a future enhancement. What annoys me is that every few months they send out an email announcing new enhancements they’ve made to their system. All they ever announce are new, sleazy ways to upsell worthless services or better ways to manage affiliates. Nothing that ever improves the experience for the customer.
I should have switched payment processors at this point but because the .Net Reactor license key generator only worked with ShareIT I was effectively locked in. I still believed saving a license file to a folder was easier than entering a registration key.
I’m embarrassed to say this sad situation continued for a couple of years. It wasn’t causing me enough pain to justify completely redoing my licensing system and switching payment processors.
The Final Straw
Eventually there were three incidents that made me realize enough is enough. The first was a customer who just could not work out how to save their license file into my application folder. In the end I arranged a time and connected to his PC using the remote desktop application Copilot and licensed it for him. He was very grateful for the personal service but it was a unnecessary waste of both our time.
It was at this point I realised that some people don’t understand what an attachment is and how to save it to a location on their hard drive. Some would try to open it and then their PC would complain that it couldn’t find the associated program for this type of document (the license file had a .license extension). Matters were made worse by the increasing popularity of web mail clients and their less than friendly handling of attached files.
The second incident occurred during a recent Bits Du Jour sale. I sold a lot of licenses during this period but also had a corresponding increase in support emails from new customers asking how to frickin’ activate their license. This clearly illustrated that not only was there a useability problem but as my sales increased there would be a corresponding increase in support requests. My current solution was not going to scale.
If this wasn’t enough evidence that something needed to be done, I received two emails from a frustrated customer. They were both received on the same day and sent to different email accounts. It’s always a good indicator a customer is pissed when they send multiple emails to different accounts in a short space of time. This is doubly true when each email is uniquely worded. Copy and paste is not nearly as satisfying when you’re venting your frustration.
There’s a temptation to focus on ways to attract new customers rather than improving the experience for existing users. It’s also very easy to adopt an attitude that a certain section of your users will be ‘technically challenged’ and they’ll always have problems. It’s their problem, not yours. I have to admit that in this instance I’ve been guilty of both crimes.
Once I made the decision to overhaul my licensing system, I decided to rebuild it from ground up. The overriding goal was to make it incredibly simple to license Text2Go. In fact, I felt so guilty for the needless frustration I’d inflicted on a significant percentage of my users, I not only wanted it to be incredibly simple, I also wanted it to leave the customer with a warm, fuzzy feeling. They deserve nothing less. They’ve just paid me real money.
Here is the set of requirements my new licensing system must meet.
- A simple license key based system
- Use pre-generated keys. This doesn’t mean anything to the end user but it does mean I’m now free to choose any payment processor. No more vendor lock-in. I can choose a payment processing company that provides the best experience for the customer.
- Provide a simple means for the customer to license Text2Go without needing to enter the license key.
- Don’t require a restart of Text2Go.
The New Licensing Solution
I’ve kept .Net Reactor to do my code obfuscation and protection. I’ve just turned off its licensing system and replaced it with the Infralution licensing system. I’d heard very good reports about this system and haven’t been disappointed. In addition to the key based licensing system, it also includes code to run a time-based trial period for your software. You get the C# source code for the licensing technology that you need to embed in your application. This means you don’t need to ship yet another DLL.
It also includes a sophisticated License Tracker application that allows you to track sales and customers. As its name suggests its main purpose is to keep track of each customer’s license key. It has a powerful import feature that can import sales data from all the leading payment processors, including ShareIT. It can also import sales information from emails in Outlook.
This tool means I can always reissue the same license key to a customer, should they lose their key. It also means I can trace a license key back to an individual customer, in case it appears ‘in the wild’.
The changes I’ve made to Text2Go have been relatively small. I’ve added a ‘Register…’ menu command and an associated dialog box that allows the user to enter a license key.
When the user enters a valid license key I do a couple of things to demonstrate my appreciation and hopefully leave the customer with a good feeling about purchasing Text2Go.
I display a thank you message, along with a picture of a rose. I also play a very short set of musical notes, similar in some ways to the Windows startup sound or a powerup sound effect in a game.
Small things I know but I hope it leaves the customer with a positive feeling.
One of my goals was to provide a way for the customer to avoid having to manually enter a license key. For sophisticated users this is no major burden. They just copy the license key from their purchase email and paste it into the licensing dialog.
For less sophisticated users I can see two problems with this. The first is that some people will have trouble finding the ‘Register…’ command. Like looking for the tomato sauce bottle in the pantry, sometimes you just can’t see something even when it’s right in front of you.
The second problem is some people will have no idea how to do a copy and paste. They’ll have to manually enter each character. It will be tedious and error prone but unlike the licensing file, they will eventually manage it.
Painless License Key Registration
I’ve come up with a rather neat solution that will register Text2Go simply by clicking on a URL in the purchase email. No hunting for the registration dialog or entering a registration key.
In the last major release of Text2Go I built in a very simple web server. This was added to provide integration with all the major web browsers. What it allows me to do is issue a command to Text2Go through any web browser’s address bar. People have talked about the address bar being the new command line. This is quite literally the case for Text2Go.
For example, to register Text2Go I use a URL in the following form.
You can see that 61061 is the port Text2Go listens on, register is the command and it has a single key argument.
When the user clicks this link, their browser is started which will in turn send the request to Text2Go. Text2Go will validate the supplied key argument. If it’s valid, Text2Go is registered. The same registration sound is played but instead of the thank you message being display in a dialog box it’s returned as a web page. It the key is invalid, then the returned web page states this fact.
If anyone’s interested in using this technique for their own application, you may want to read the article I wrote for Code Project.
Resetting a 30-day Trial
Anyone who provides a 30 day trial for their software will know they get the occasional request to extend the trial beyond the initial 30 day trial period. This is almost never because someone’s trying to game the system. Instead it’s most often because someone has downloaded and installed your application, tried it for a couple of seconds and then got distracted. It’s not until a month later that they get some time to get back to it and give it another try. Unfortunately by this time, their 30-day trial has expired. It’s at this point you will get an email asking for an extension to their trial.
The Infralution licensing system provides a method to reset the trial period. The trick is working out a way of calling this method. You can’t just add a Reset Trial button to you UI or everyone will use it to extend their free trial period indefinitely.
I want to be able to send the customer a URL they can click to reset their trial period. However I can’t allow this URL to be used over and over to extend a customer’s trial. Therefore what I do is pass today’s date as part of the URL. When Text2Go receives the request it checks the date supplied is either today’s date or has occurred within the last 7 days and will only reset the trial if it falls within this period. This gives the customer one week to reset their trial period. After that time, the URL will no longer work. The date passed as part of the URL needs to be encrypted in some way. Otherwise the customer could easily change the date, once again giving them a way of indefinitely extending their free trial period.
To achieve this I wrote a very simple program that combines a date with a secret password and generates an MD5 hash.
It’s this hash that is passed to Text2Go. Text2Go also knows the secret password. It performs the same calculation, combining a date with the password to generate a hash code. If the two MD5 hash codes match, then it must be valid and the trial period can be reset. If it doesn’t match, it generates a hash for the previous day and checks again. It will do this for up to 7 days. Note that because MD5 is a one-way hash, it’s not possible to extract the actual date. All that can be done is to try to reproduce the hash code by trying a number of different dates. This is perfect for our situation as we only ever need to try 7 dates.
One of the other problems I had was what to do with existing customers. They are all using a version of Text2Go that uses the old file-based licensing technology. I didn’t want to support two licensing mechanisms so I decided to migrate them to the new licensing system.
This meant generating a license key for each customer and mailing them their key. Due to the number of existing customers, this needed to be automated.
The License Tracker application has a very powerful feature for importing customer and sales data from payment processors, such as ShareIT. I can export my sales data from ShareIT as an XML report and then import it into License Tracker. However none of these orders will have license keys assigned to them, as I was using the file-based licensing system at the time the orders were generated.
I needed a way of assigning a license key to each order before importing it into License Tracker. To do this I created a simple application that would take a list of license keys, scan the XML sales report and assign a license key to each order. Now when the sales data was imported into License Tracker, each order had an Infralution license key assigned to it.
I then wrote a second application that would scan the XML sales report (that now included license keys) and for each customer, extract their name, email address and license key and send them an email containing their license key. They could use this key to relicense Text2Go when they upgraded to the new version.
Finally Free to Switch Payment Processors
Once I’d switched to pre-generated keys I was free to switch payment processors. I have changed to FastSpring and couldn’t be happier. Their system allows a fully customisable email to be sent to purchasers. Now I can send just the instructions needed to license Text2Go, which are now not much more than ‘click this link and you’re done’. Their order page customisation is also very flexible, although I don’t really make full use of this as I have my own shopping cart page and just jump directly to the FastSpring checkout page.
The FastSpring administrators’ interface is a joy to use. It has a gorgeous web 2.0 look and more importantly is very responsive. It’s layout is all very logical and it has really useful context sensitive help on each page. I found this was more than adequate and didn’t have to read through their user manual at all.
FastSpring prides themselves on great support and that’s definitely been my experience. Their staff are all very knowledgeable and they respond within a few hours, even on weekends.
In summary, here are some of the lessons I’ve learnt.
- Keep your licensing system as simple as possible. It only needs to be sophisticated enough to keep honest people honest.
- Be very careful when choosing any solution that locks you into a single vendor. Work out how much effort/pain it’s going to cause you to get out.
- Work to keep your existing customers happy rather than always trying to win new customers.
- Continually work on improving useability and removing confusing areas of your application, including areas that only affect a small percentage of your user base.