Day 16: I don't know how to prevent fraud

A week ago on Day 9, I assessed the different paid plans that I could adopt for Hide Feed and decided to go with a feature-based model. Here’s how it would work:

  • There are two plans: Basic (free) and Pro (paid)

    • Limited feature set on Basic (can only hide the feed on a single site, no image replacement, etc.)
    • All features are available on Pro
  • Upon installation, new users get a 7-day free trial of the Pro plan so that they get to see all that Hide Feed has to offer

  • When their trial ends, users are downgraded to the Basic plan until they upgrade

Simple and clean. But there’s a fatal flaw. Can you spot it?

Fraud. After 7 days, users can just uninstall Hide Feed and reinstall it to get the Pro features again. And they can do this as many times as they want. (Side note: “Fraud” feels too strong of a word to describe this behavior, but I can’t think of anything better.)

I intentionally designed Hide Feed to collect as little information as possible about the user. I currently don’t transmit any data from the extension. No Google Analytics. No Mixpanel. What happens in your browser stays in your browser. And I really want to keep it this way. I like the idea of being able to provide a valuable service without having to collect users’ usage data, even anonymously. I’m going to dive deeper into the topic of privacy in a future post because everything I said above would be heresy in pretty much every tech company today, and I’ve had developer friends be completely baffled because the idea of running a service without collecting data to understand user behavior sounds completely absurd to them.

The point is that I don’t want to identify users or force them to create accounts to use Hide Feed, especially if they don’t benefit in any way. But I also don’t want to leave such a huge loophole such that it’d be trivial for anyone, not even just the tech-savvy, to get all the features for free, forever.

This wouldn’t be as big of a problem if uninstalling Hide Feed incurred a cost. For example, think about your social media accounts or something like Google Photos. Deleting those accounts would mean losing all the posts, messages, photos, etc. that you’ve invested into the service. Even if there was some benefit to having a new account (e.g. a free trial of some sort), the cost of losing or having to re-upload all your data would make deleting your account seem extremely unattractive.

Hide Feed, on the other hand, is more like a toothbrush. If someone swapped out your toothbrush for an identical one, you probably wouldn’t mind at all. In the same way, a new installation of Hide Feed acts just like a previous installation of Hide Feed. You wouldn’t lose any data that’s painful to replace.

To summarize, Hide Feed is especially susceptible to fraud because it:

  1. Is a Chrome extension, which makes it trivial to uninstall and reinstall
  2. Doesn’t require signing in
  3. Doesn’t keep any data that’s difficult to replace

Here are some potential approaches to address the loophole:

\1. Require registration to use Hide Feed

I strongly dislike this option because users (at least currently) wouldn’t benefit at all from creating an account. It would be purely to help me prevent the loophole. I also think I’d lose a lot of people at the registration step because it wouldn’t be clear why they’d need to register and they wouldn’t be invested in the extension because they haven’t tried it.

\2. Require registration to unlock the Pro trial

This is a better version of the approach above. Users can start off with a Basic plan and then register to unlock the Pro trial. Also, registration doesn’t necessarily have to mean creating an account — I can send a license to the user’s email address and then make sure that a license can’t be issued to that email address again. The attack vector here would be that someone could create a new email account every week to get a new license, but that seems more annoying than simply uninstalling and reinstalling the extension. The downside is that many users might not bother trying out the Pro trial due to the additional friction.

\3. Register users without user action

(This can also be read “Automatically register users for a seamless experience” or “Register users without their knowledge or consent” depending on your views on privacy.)

A common practice for extensions is to automatically register you based on the data they have access to. For example, many Gmail-based extensions will find and save your email address when you open Gmail. They then use your email address to prevent you from using the free trial multiple times or to send follow-up emails. I’m personally not a fan of this practice because I’ve never enjoyed being on the receiving end of it. It makes me wonder what else they’re collecting without my knowledge and erodes the trust that I have in the extension. Maybe most people don’t care about this, but I’d like to avoid it if possible.

\4. Switch to a usage-based model

Having a usage-based model would pretty much close the loophole. Say, for example, that the Basic plan provided all the features but limited hiding feeds to 50 times a day. If someone hits the limit sometime during the day, they can uninstall and reinstall the extension, but they’d probably run into the hurdle the following day. Having to uninstall and reinstall the extension on a daily basis is significantly more annoying than doing it just once a week. Note that if the usage-based model had a usage limit of longer duration (e.g. “Hide feeds 350 times in a week”), the loophole would remain the same.

\5. Shorten the Pro trial period

Shortening the trial period would require reinstalling the extension more frequently, which would make the loophole more annoying. But this would also mean that people would only be able to try the Pro features for a shorter amount of time before they have to make a decision to upgrade or not. I don’t think a time period shorter than 7 days would be quite long enough to have people really appreciate the benefit of hiding all the distractions.

\6. Add features that make it unattractive to uninstall

I initially implemented showing usage data in the place where the feed is hidden with comparisons to your historical usage. For example, it would show that you’ve viewed your Facebook feed 5 times today for a total of 39 minutes, which is higher than your daily average of 3 views for 20 minutes. I took this feature out once I decided to make Hide Feed more about just hiding distractions and make Intention (the other Chrome extension I’m working on — currently on hold due to Hide Feed) more about self-control and time management, but this is an example of something that would make Hide Feed more unattractive to uninstall and reinstall because you’d lose all your historical usage data.

I honestly don’t know what the best thing to do here is. Of all the approaches, switching to a usage-based model (#4) seems the most appealing with requiring registration to unlock the Pro trial (#2) being my second choice. Maybe I shouldn’t worry about this at this stage. I think for now, I’ll just go ahead with my current plan of providing a 7-day Pro trial with a feature-based model and look into implementing one of the above approaches if I find that a nontrivial number of people are taking advantage of the loophole.

Update (Day 17)

Francesco commented that he would create an anonymous device ID, and that made me think of variations within approach #3 that would allow me to prevent multiple pro trials while not transmitting any of the user’s personal data (email address, Facebook ID, etc.):

  • Browser fingerprints

    • Browser fingerprints have always sounded yucky because they’re typically used for ad-tracking services, but it’d work as a fraud deterrent here
  • Hashed versions of identifiers

    • I can hash identifiers like email addresses, etc. and use that to compare trial activations without transmitting personal data. I think I like this approach the best because it doesn’t compromise user privacy (I wouldn’t be able to figure out the user’s identity from the hash) but still provides a unique ID for that user

Thanks Francesco!