in Game tech

URL Shorteners In Under Two Minutes

This morning I added the goo.gl URL shortener to Flower Garden, so I thought a quick post with sample code might be helpful for other developers looking to do something similar.

I use the URL shortener in Flower Garden to send bouquets through SMS. Space is limited in a text message, so the message just contains some text explaining what is it and the URL pointing to the bouquet image. (Yes, I would much rather send them through MMS, but Apple isn’t exposing that yet to developers).

Sms

In this case, the full URL is http://flowers.snappytouch.com/sms.php?id=949618b4b3c6f3d76e32b45446e238a0 which gets thankfully shortened to http://goo.gl/IV5cq.

Sending bouquets through SMS has been in Flower Garden for several months, but it was using bit.ly before, which is probably the most popular URL shortener out there. I like their web interface and their super-easy to use API, but unfortunately it seems that I hit some mysterious API limit during the Mother’s Day Flower Garden promotion. That limit isn’t public anywhere, and as far as I can tell, I can’t even see it myself through the web interface or through an API query.

Finding out that I reached the API limit was quite shocking, because sending bouquets through SMS isn’t a particularly popular feature. Unfortunately I don’t have good analytics hooked up to that step, but I can’t imagine there were more than a few thousand per day.

They were very nice and contacted me instead of shutting down my account since it was just a spike. They also tried to sell me their “Enterprise” account, but $995/month is a tad too expensive for me. By about $990 probably, so I had to look for other options.

After a very quick research, goo.gl was the perfect alternative. Not only is it very fast (and backed up by the giant Google no less), but they have an API limit of 1,000,000 queries/day. If I ever blow that budget, I’ll be able to afford the $995/month without a problem ๐Ÿ™‚

All URL shorteners are very easy to use. You need an API key, and figure out the exact format of the HTTP message you send and the response you get.

goo.gl

Goo.gl has a great Getting Started Guide that tells you everything you need to know. Get your private API key from here, and you’re ready to rock.

Drop this in your app and start shortening away. You’ll notice I used a synchronous HTTP request, which is usually a big no-no. Here I felt it was justified since the user is blocked waiting for the SMS to be prepared and sent. Besides, goo.gl is very, very fast, so it’s never even noticeable.

const NSString* GooGlAPIURL = @"https://www.googleapis.com/urlshortener/v1/url?key=YOUR_API_KEY_HERE";

NSString* ShortenURLWithGooGl(NSString* longURL)
{
	NSURL* apiUrl = [NSURL URLWithString:GooGlAPIURL];
	
	NSMutableURLRequest* req = [[NSMutableURLRequest alloc] initWithURL:apiUrl];
	[req setHTTPMethod:@"POST"];
	[req setTimeoutInterval:Timeout];
	[req setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
	
	NSString* body = [[NSString alloc] initWithFormat:@"{\"longUrl\": \"%@\"}", longURL];
	[req setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
	[body release];
	
	NSError* error = [[NSError alloc] init];
	NSHTTPURLResponse* urlResponse = nil;
	NSData* data = [NSURLConnection sendSynchronousRequest:req returningResponse:&urlResponse error:&error];
	[error release];
	if (data == NULL || ([urlResponse statusCode] < 200 && [urlResponse statusCode] >= 300))
		return NULL;

	NSString* response = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
	NSDictionary* responseDict = [response JSONValue];
	NSString* shortURL = [[responseDict objectForKey:@"id"] retain];
	[response release];
	return shortURL;
}

I’m using a JSON framework to parse the answer, but it’s so simple I probably wouldn’t even have to. I only used it because it’s already part of the project because of Facebook Connect.

bit.ly

Even though it’s not my favorite shortener, I’m adding it here for completeness (and because I had the code already written).

The one thing that bit.ly has going for it is that it’s even easier to use than goo.gl. No JSON involved, and you don’t even need to send a body with your request. As usual, get your API key by signing up with bit.ly.

const NSString* BITLYAPIURL = @"http://api.bit.ly/v3/shorten?login=%@&apiKey=%@&format=txt&";

NSString* ShortenURLWithBitLy(NSString* longURL)
{
	NSString* urlWithoutParams = [NSString stringWithFormat:BITLYAPIURL, LoginName, APIKey];	
	CFStringRef encodedParamCF = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
															 (CFStringRef) longURL, 
															 nil, (CFStringRef) @"&+", kCFStringEncodingUTF8); 
	NSString* encodedURL = (NSString*)encodedParamCF;
	NSString* parameters = [NSString stringWithFormat:@"longUrl=%@", [encodedURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
	NSString* finalURL = [urlWithoutParams stringByAppendingString:parameters];
	
	NSURL* url = [NSURL URLWithString:finalURL];
	
	NSMutableURLRequest* req = [[NSMutableURLRequest alloc] initWithURL:url];
	[req setTimeoutInterval:Timeout];
	
	NSHTTPURLResponse* urlResponse = nil;  
	NSData* data = [NSURLConnection sendSynchronousRequest:req returningResponse:&urlResponse error:NULL];
	if (data == NULL || ([urlResponse statusCode] < 200 && [urlResponse statusCode] >= 300))
		return NULL;

	NSString* response = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
	return response;
}

That’s it. You should be able to drop in either one of those snippets in your project and spend your time working on the things that really matter in your games.

  • Nice code, but you might want to remove the XSS hole in the sms.php script. Exploitable (in browsers != ‘chrome’, ‘safari’) like so:
    http://flowers.snappytouch.com/sms.php?id=949618b4b3c6f3d76e32b45446e238a%22%3E%3Cscript%3Ealert%28%27XSS%27%29%3C/script%3E%3C!–

    • Thanks! Fixed it. I barely know what I’m doing with PHP and MySQL, so that heads up was much appreciated ๐Ÿ™‚

  • Olie

    Thanks for the code! A quick comment about this:

    “[synchronous HTTP requests are] usually a big no-no. Here I felt it was justified […] goo.gl is very, very fast, so itโ€™s never even noticeable.”

    The bad experience that your customers will have isn’t that goo.gl is slow, it will be when they’re in a poor network environment that takes 30 seconds to time out. While staring at your phone screen not quite sure what’s going on, 30 seconds is a LONG time!

    IMO, anyway.

    • Sure, but it’s not like I designed the app to do anything else while that’s going on. And they still need to approve and send out the SMS from the standard iOS view after the URL is shortened. So doing an asynchronous request wouldn’t help me any. Or am I missing something?

  • 98520

    ้€™2ๅคฉๅป็œ‹ไธๅˆฐๅœ–็‰‡

  • Teresa

    Sending bouquets through SMS has been in Flower Garden for several months, but it was using bit.ly before, which is probably the most popular URL shortener out there. I like their web interface and their super-easy to use API, but unfortunately it seems that I hit some mysterious API limit during the Motherโ€™s Day Flower Garden promotion.