Archive for category ASP.Net

Post-mortem report of my free online dating service; Part 2 of 2

My free online dating site launch in May of 2009 after a little under 2 years of work. Now I just need to get people to come to or write about the site and the real work has begun. I post it up to all the social networks at the time telling people to come check out my site. “SPAMMER!” I hear. Crap, how can I tell you about the site but not tell you about the site?

I thought my solution to organic marketing would be to get other people to write about it. I searched for and made lists of blogs and sites that wrote about online dating or dating in general and started crafting individual emails for each site. For hundreds of sites I found I spent a few hours each night trying to first find a method to contact them via form or email. If I was able to find a contact method I wrote up an email about how awesome my new site was and the work I put into it and they should take a look or write about it. After a few months of this I was completely burnt out. I had gotten next to no responses from all my work, less than 1% feels generous. No one responding to me after the hundreds of communications I sent out was crushing.

I tried a couple of paid per post services but that investment didn’t pan out. The services themselves were OK, the posts went up pretty quick but the types of sites doing this weren’t exactly well respected. With all their other pay per posts it was like trying to hold a quiet conversation at a concert. A worthless avenue for marketing.

The only reliable method to get new visitors from day one that I used was online advertising through Google AdSense and Facebook Ads. I setup accounts for both services and right away I was getting click throughs and new members. Everyday I was checking my cost per registration from both services and quickly found Facebook Ads just wasn’t performing well. With just Google AdSense to focus on I created a dozen campaigns with different keywords targeting states, cities and the different sexes. I spent a good amount of money here and it was extremely addictive. I would not recommend pay per click campaigns for anyone without extremely deep pockets or free services to use. Without this service I would not have gotten any users and with it I ended up hating the project more and more. I was spending money everyday and making a little money but it was never increasing over time.

One of my biggest mistakes was not developing a proper site administration system. I underestimated the amount of profile removals I would need to make per day. I spent about 30-45 minutes on some days just cleaning up bad profiles. I finally setup a rudimentary system but even then I sometimes had to resort to my set of SQL scripts to do some tasks.

My largest problem I never resolved was spam. The only people that actually wanted to seek out and use my site were spammers. Mostly from Nigeria and it’s surrounding countries but also from Russia for mail order brides. I had ReCAPTCHA in place but they didn’t care. These weren’t robots I was keeping out but tons of people that sent out hundreds of messages a day. My final attempt was a manual message and user approval process. That meant that before any new users messages were sent I had to approve them. This was just too much work and something I never considered before launching but could never solve afterwards. They ruined the site for me and the legit users that signed up.

I’m going to shut down the service this year and will be open sourcing my code, I need to clean out any S3 key stuff. There was a lot of important lessons I learned during this experience. My product didn’t have an interesting angle. I didn’t solve any new problems or solve an existing problem so well people wanted to talk about it. My marketing was underbudget to compete against the larger players. I under developed my application and failed to think through the spam factors.

I’m happy to have done the project but I’d be lying to say I’m not even happier to have it in the past.

Check out Post-mortem report of my free online dating service; Part 1 of 2 if you didn’t see the ramp up to launch

No Comments

Post-mortem report of my free online dating service; Part 1 of 2

I registered the domain for my free online dating service, DiveIntoThePool.com, in October of 2007. I decided that along with making my first real startup that I would invest money in that it would be a good idea to do in a language I didn’t already know (ASP.NET), with a database I wasn’t familiar with (MSSQL) and on a platform I had not deployed anything on before (IIS6).  My thinking was that along with creating this sure fire website that I could make money though advertising off of I would try and learn as many things along the way as possible. I worked on this project in my evening times while also supporting a medium-core World of Warcraft habit. When I say something took days of research it’s real time passed after work, WoW and a little life.

I had modest goals to measure the success of the site. My first goal after launching was to make more money than I spent in hosting and advertising. After that I wanted to invest all actual profits back into the site so it would continue to grow. I pictured a power point graphic of exponential growth and with a little patience I would be rich!

I broke the site down into smaller and smaller chunks and for every small milestone or functionality I completed I patted myself on the back. Milestones such as getting Visual Studio Web Express to pre-compile DLLs so I didn’t have to place source files on my webserver, which I had none setup at the time, or migrating my new found zip code database from MySQL to MSSQL. Every step I took involved several days of thinking and research.

I swear it wasn’t intentional but I felt like I put as many technical obstacles in between myself and launching the site as possible. I vividly remember spending several evenings, days I felt like, trying to decide on which source control solution I should use. I kept hearing Git this and Git that at the time but it took me a while still to figure out there was no easy way to run a Git server on my home Windows machine. I finally settled into VisualSVN and celebrated when I checked a file in from my laptop and got latest from my desktop! I was on my way.

I stressed over membership and security for a long time as well. Don’t store passwords in plain text, watch out for all user input and SQL injection worries. I had created a pretty full registration and login web of pages before I even thought about creating a admin interface for my users. That’s no problem I thought at first, Visual Studio Web Express came with this very helpful ASP.NET Web Site Administration Tool that I found out, after several more nights, couldn’t be installed remotely on my newly acquired shared hosting environment. Screw it! At that point I had a text file of SQL scripts I was running to do development work that ended up being my “admin” interface to the site.

I had been using my free time since registering the domain working on the site and learning C# but by December 2008 I still seemed far away from launching anything I was proud of. I was doubting my plans and if I didn’t do something drastic soon I would never launch the site. In January 2009 I quit playing World of Warcraft, I disbanded the guild I had put together, transferred onto another server and kept no ties to anyone I knew. Even my real life friends didn’t know where my characters went. Shortly there after I actually canceled my accounts. Suddenly I had all the time in the world during my evenings to work.

Within 5 months of cutting out video games I was able to launch the site in May of 2009. I actually did a soft launch first, running through all of my test cases a few times just to check for any obvious bugs. All of my testing, research, learning and code was live. It took me far to long to get here I told myself and I knew that the hardest hurdles were still to come. No one knows me, I have no track record of success, how on Earth am I going to get people to sign up or even visit my freshly unwrapped free online dating service.

Continued in Post-mortem report of my free online dating service; Part 2 of 2 to read about the end of DiveIntoThePool

No Comments

Blocking IP addresses by country on IIS shared hosting

On a shared hosting environment you often won’t have access to ban IP addresses on the IIS level and my shared host didn’t offer the Firewall module for Plesk so I had to come up with a programmatic way of blocking large blocks of IPs. You can setup in your web.config file something called a HTTPModule that works before the page is delivered to the client computer. For this sample I added a key and value to my web.config file that holds my comma separated IP list that I want to block. Since I’m running a site that is focused on the United States there isn’t much overlap on the /24 block area 255.255.255.* so I am only checking the first 3 digit blocks for matches. When a request comes in IpTwentyFourBlockingModule will check the users IP address against the key value blockiptwentyfour to see if there is a match and if it is a match will return 403 forbidden to the client browser, banned!

Coming up with a IP list is another problem. I found IP Location Tools that gives out an API that generates a updated list of IPs for a given country. The problem is the list gets broken out into IP blocks other than /24, you’ll see all ranges of IP blocks that get very complicated very fast and more than I wanted to try and pull off in a days work. I wrote a Flash ActionScript 3 application to consume this data and give me a list of unique IPs 255.255.255 that I could then drop in as the value for blockiptwentyfour. I then added IP tracking for new users and have had to ban some rogue /24 blocks that escaped this list but its kept them at bay and more manageable for now. I’ve already had a colleague suggest that this is still only a stopgap at best and I should develop some kind of throttling system to help prevent spam when I’m not around to watch the site like a hawk.

web.config

1
2
3
4
5
6
7
8
9
10
<configuration>
  <appSettings>
    <add key="blockiptwentyfour" value="41.210.29,41.210.28" />
  </appSettings>
  <system.web>
    <httpModules>
      <add name="IpTwentyFourBlockingModule" type="IpTwentyFourBlockingModule" />
    </httpModules>
  </system.web>
</configuration>

IpTwentyFourBlockingModule.cs – put this is in your App_Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#region Using
 
using System;
using System.Web;
using System.Configuration;
using System.Collections.Specialized;
 
#endregion
 
/// <summary>
/// Block the response to certain IP addresses
/// </summary>
public class IpTwentyFourBlockingModule : IHttpModule
{
 
    #region IHttpModule Members
 
    void IHttpModule.Dispose()
    {
        // Nothing to dispose; 
    }
 
    void IHttpModule.Init(HttpApplication context)
    {
        context.BeginRequest += new EventHandler(context_BeginRequest);
    }
 
    #endregion
 
    /// <summary>
    /// Checks the requesting IP address in the collection
    /// and block the response if it's on the list.
    /// </summary>
    private void context_BeginRequest(object sender, EventArgs e)
    {
        string ip = HttpContext.Current.Request.UserHostAddress;
        string[] tempIpArray = ip.Split('.');
        string iptwentyfour = tempIpArray[0] + "." + tempIpArray[1] + "." + tempIpArray[2];
 
        if (_IpAdresses.Contains(iptwentyfour))
        {
            HttpContext.Current.Response.StatusCode = 403;
            HttpContext.Current.Response.End();
        }
    }
 
    private static StringCollection _IpAdresses = FillBlockedIps();
 
    /// <summary>
    /// Retrieves the IP addresses from the web.config
    /// and adds them to a StringCollection.
    /// </summary>
    /// <returns>A StringCollection of IP addresses.</returns>
    private static StringCollection FillBlockedIps()
    {
        StringCollection col = new StringCollection();
        string raw = ConfigurationManager.AppSettings.Get("blockiptwentyfour");
 
        foreach (string ip in raw.Split(','))
        {
            col.Add(ip.Trim());
        }
 
        return col;
    }
}

collectipaddresses.as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import flash.events.*;
import flash.net.*;
 
var myRequest:URLRequest = new URLRequest("http://iplocationtools.com/country_query.php?country=CI,SN,GH,NA,NG")
var loader:URLLoader = new URLLoader();
 
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.addEventListener(Event.COMPLETE, handleComplete);
loader.load(myRequest);
 
function handleComplete(event:Event):void
{
	var loader:URLLoader = URLLoader(event.target);
	//trace(loader.data.replace(/\n/g, "|"));
	var ipArray:Array = loader.data.replace(/\n/g, "|").split("|");
	trace(ipArray.length);
	setTwentyFourBlock(ipArray);
}
 
function setTwentyFourBlock(ipArray:Array)
{
    var	shortIpArray:Array = new Array();
 
	var	lastUniqueIp:String = "";
 
	for each(var ip:String in ipArray)
	{
		var tempIpArray:Array = ip.split(".");
		var stringCurrentIp:String = tempIpArray[0]+"."+tempIpArray[1]+"."+tempIpArray[2]+".0";
		if(stringCurrentIp != lastUniqueIp)
		{
			lastUniqueIp = stringCurrentIp;
			shortIpArray.push(stringCurrentIp);
		}
	}
 
	trace(shortIpArray.length);
	trace(shortIpArray.join(','));
}

All of this work has really kept my free online dating site almost spam free for now but I’m adding IP blocks I’ve missed from time to time.

, , , , ,

No Comments