Adam Howitt's Blog

Jan 19
2010

Run your ass off this year!

After another 200 hour programming marathon spread over 4 months I'm thrilled to announce the release of version 3 of WalkJogRun's iPhone App "WalkJogRun Running Routes".

What does it do?

The most significant change version 2 was the addition of 23 training plans created by Coach Jenny Hadfield of Runners World fame. Once you sign up for a training plan and pick a start date you'll get alerts every morning at 6am (silent so they don't wake you) to tell you how far to run, how fast and give you motivation. Tap the find routes button to find a training route in your neighborhood from the 600,000 routes at WalkJogRun.net

What if I've never run before?

We've got plans for beginners, intermediate and advanced runners including one called "Run your first 5k" designed to take you from the sofa to being able to run a 5k race in 10 weeks. We've also got 10k training plans, half marathon training plans and full marathon training plans.

Gimme the nerdy stuff

The programs themselves are delivered as in-app purchases using the StoreKit framework on the device to process payments and then send receipts to the ColdFusion server to register the subscription and begin delivery of the alerts.

The alerts are delivered as Apple Push Notifications generated by ColdFusion. No mean feat I can tell you using Java in ColdFusion to connect to a streaming data socket to send and receive the bytes and then drop the encoded JSON packets off on your phone. The phone gets the alert, opens the app and takes you to the training session for the day to show you your training tip.

Download a copy of "WalkJogRun Running Routes" before it gets too late!

Dec 31
2009

Affiliate Link Shortening for Profit

Coupon Cabin just launched their latest offering yesterday in the world of affiliate marketing called Dealfer.com so you make commissions on the sales you generate at participating merchants. It's a clever idea and leverages their relationships with affiliate merchants to help you make money.

Why would I need a short URL?

If you're not hip to the URL shortening jive yet it has a couple of benefits. The first is that shorter URLs are easier for people to type in and they fit on business cards, in books or promotional materials nicely. Dealfer.com links become http://dlfr.me/xxx where xxx represents a string of characters used to find your link and expand it when someone clicks. Being so short they also use less characters on a webpage or the most common use in twitter where you're limited to just 140 characters.

The second big reason for URL shortening is that marketers can track how many clicks a link in a certain place received. For example if you tweet a link using dealfer you'll be able to see how many clicks it got on twitter. Some URL shortening services, like bit.ly, even offer stats so that even if your link get's copied and repurposed anywhere like on someone's blog you'll know about it.

Online marketing is easier to monitor than offline marketing traditionally because when someone types in your home page URL into their browser you have no idea where they saw it or heard it, be it on the side of a bus or on the radio but by using a link shortening service you bring traditional marketing back into the ring. The downside is that you're marketing a link that doesn't look like your home page - dlfr.me - but at least it's memorable "deal for me", with the exception of the string part that follows!

Why not use bit.ly?

True, the links are one character shorter and the stats breakout the referral sources but Dealfer wins out in my mind because if I'm linking to a merchant they support I'll get a commission for a sale vs bit.ly links where I won't. Commissions range up to 15% which could help turn a hobby blog into a paying venture.

How does it work?

Just like every other URL shortening service but you get paid! The first way to use it is that any time you want to shorten a URL just go to Dealfer.com and paste in the URL. If you're not logged in it will ask you to login, create an account or if you just need a short URL you can skip registration and get the short URL.

When you register you give them a PayPal account to receive funds for any commissions you make. Not every link is going to result in commissions but their list of merchants broken out by commission level could inspire you to promote products in the 15% tier! If you link to a merchant not on the list or a site that doesn't monetize you'll get your short URL and can track the number of clicks but the real magic happens when you link to a supported merchant. Chances are if you get 100 clicks to a merchant you'll end up with a sale, especially if it's something your peers would be interested. You can either link to the top level domain name or deep link to a specific product.

Any top tips?

They have a bookmarklet you can drag onto your bookmarks to make it easier to generate links while you shop. Basically if you're on a product page for something you think your friends would like you can hit the bookmarklet and it pops up a window to give you a dealfer link to use when you're done shopping. You don't have to worry about whether it's on the participating merchant list or not - you'll still get a link you can share. If it is, it's a bonus.

I would recommend looking at the merchant list shown by commission percentage to see what to expect from each merchant. Some only offer 1% of a sale and others offer 15%. Familiarize yourself with the sites so you know that if you have a choice between linking to something at site A vs site B (a participating merchant) you don't miss any opportunities.

Lastly, think about where you are sharing your links. If your blog is about Adobe products then linking to Adobe makes perfect sense. Try to put your readers one click away from the purchase instead of just linking to the merchant home page. For example a long blog post about Adobe ColdFusion would deserve a link write down to the ColdFusion product info/purchasing/trial page.

Until the stats are broken out at Dealfer by referrer you can at least create different links for the different places where you wish to use a link to a site. For example in an ad in the newspaper you might use one link and for a twitter promotion another. Even though they both point at the same place you get to see how many people "clicked" each. (The quotes because if they type it in after seeing it offline they are still tracked as a click).

Think about opportunities to promote specific products as you wander around the web. If you're in a forum about the latest nike running shoe and you know one of the featured merchants has a sale on that product or is the cheapest, "dealfer a link" instead of just linking to the store directly and you'll still get commissions on whatever sells. Even on facebook or linked in where people are asking for product recommendations. If it's truly a great product you believe in and a reputable store it will sell and you'll get the credit.

Future developments

I'd like to see this service incorporated into some of the big twitter applications like cotweet.com and Twitterific or Tweet Deck. The advantage for developers is that until the account holder enters their own login for Dealfer into the application, the developers would be credited with commissions generated by links. I shudder to think how many links per day the average twitter app sends!

Another feature I'd like to see is a list of the merchants listed by the highest conversion rates and/or revenue generated per click. This type of breakout could help potential linkers find the stores that, while they may offer excellent commissions, rarely convert visitors into sales. Dodging the dogs could lead to a really profitable linking hobby!

Conclusion

Go create an account at Dealfer.com, grab the bookmarklet or their toolbar and stop before you think about recommending a product next time and "deafer a link" instead.

Sep 08
2009

Testing iPhone StoreKit purchases

I spent a significant amount of time troubleshooting the iPhone StoreKit framework for our WalkJogRun iPhone app this weekend. I finally discovered that the documentation was slightly misleading after discovering a post on the Apple developer forums.

I had followed the StoreKit developer guide for testing which instructs you to 1. Create an account in iTunes Connect 2. Go to the Store Settings app and sign out 3. Sign in as your test account 4. Go to your app and test the purchase process

The problem comes at step 3 when you sign in. You are typically (but not consistently) told that the login has never been used in the App Store before so you'll need to review your details, which begins an account mini-interview to pick a country and enter credit card details. If you go anywhere near this process, you'll not be able to use the account when you go to your app and finally login with a series of different alerts, mainly "Your Password has Changed" or confirm your billing info.

The solution, I discovered from an Apple forum post by "Kuga", is NOT to sign in once you logout of your real account - instead just go straight to your app after you sign out in the Store Settings and use the in-app login.

Note that if you ran into the "your password has changed" error you'll find that it's damn near impossible (I couldn't work it out) how to turn an account you completed an interview for back into an account you can use for testing.

Country Specific Testing Notes

Instead of hard coding pricing into your app, if you've followed the store kit programming guide you'll pull the pricing and descriptions from iTunes Connect but initially pricing is shown in the country you were using before you logged out in the store settings.

Ben Gottlieb, author of the awesome Crosswords and Satchel iphone apps, gave me a great tip at the last NSCoder night here in Chicago for in app purchase accounts - if you use gmail you can create "throwaway aliases" to use when creating users, since each email account you use must be a unique email address that has never been used for testing and not an existing apple id. So, for example, if your email address was aardvark@gmail.com you can create fake aliases with the "+ syntax" so I would create a test user "aardvark+itcUS@gmail.com" for a US iTunes Connect test user account. The +itcUS gets ignored by Google and the email related to that account still goes into gmail for the aardvark@gmail.com account. It saves you creating a ton of email accounts for testing.

If you've created a test user for the same country as your regular account you'll have no trouble finalizing your purchase. If you've chosen a store in another country for your test user you'll be told initially that your account is only valid for that country store and you're unable to finish your purchase. This is a good thing!

Close your application and go to the store settings and you should see that you are actually logged in with that new test account for a different country. Close the store settings and reopen your app. At the point where pricing info is shown you should now see it localized to the test user country and you can complete the purchase in that language. Just be aware that the dialogs will all be in your target language so before you test the Japan store you might want to memorize the order of the buttons :-)

Verifying Receipts

I threw a simple alert in my "provide content" function to give a visual confirmation initially:

- (void) provideContent:(NSString *)productId {
    /* This is where I download the product based on the product Id to store on their phone */
    UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Purchase complete" message:@"Thanks for buying, sucka" delegate:self cancelButtonTitle:@"Done" otherButtonTitles:nil];
    [av show];
    [av release];
}

This is where I'll pull down the actual content if my purchase was successful. Since you should have your server validate receipts before delivering content you need to send the encoded receipt data over http. This piece isn't well documented but a great post on StackOverflow from JDAndrea provides the code necessary to pass the signed receipt by URL to your own server, in that case a PHP box. Since I'm a ColdFusion developer I wrote the following snippet to handle the work:


<cfset stcReceiptSend = structNew() />
<cfset stcReceiptSend["receipt-data"] = url.receipt />
<cfset receipt = serializeJSON(stcReceiptSend)>
<cfhttp method="POST" url="https://sandbox.itunes.apple.com/verifyReceipt">
    <cfhttpparam value="#receipt#" type="XML" />
</cfhttp>
<cftry>
<cfset result = deserializeJSON(cfhttp.filecontent)>
<cfmail from="mytestemail@example.com" to="mytestemail@example.com" subject="iPhone in-app Receipt Verification" type="html">
<cfdump var="#result#">
</cfmail>
<cfif result.status eq "0">
<cfcontent reset="yes"><cfoutput>0</cfoutput>
<cfelse>
<cfcontent reset="yes"><cfoutput>1</cfoutput>
</cfif>
<cfcatch>
<cfcontent reset="yes"><cfoutput>1</cfoutput>
</cfcatch>
</cftry>
It's very simple and just turns the encoded receipt data from your app into a serialized JSON packet which is posted to the itunes sandbox. Note for production releases you'll need to change that url to be the real itunes URL. If the result is a 0 you have a valid itunes transaction and I send an email dumping out the transaction keys to my email for reference before returning a 0 (success) to the code in my iPhone app. Anything other than a 0 in the result.status means something isn't right and you should pass back something other than a 0 to the iPhone app so you don't deliver the content they "unlocked".

That's it for my StoreKit testing summary - hope it helps remove some obstacles I encountered along the way. If you're looking for tips on this stuff I strongly recommend three sites which have proven critical to my forward motion: iPhoneSDK, Apple Discussions and StackOverflow. The iPhone Reference Library is a fourth but that *should* go without saying. I've found it particular useful searching for exact classnames to find the detailed API overview of properties and methods I need.

Sep 03
2009

Patch the box and upgrade CF8 JRE for stability

When I signed up for a VPS pre-installed with CF8 Enterprise I made the assumption it would be patched for me. Hmph. After a month and a bit of tolerating instability I finally nailed the problem.

[More]

Aug 11
2009

CF8 Server Monitoring alerts oddity

Has anyone used CF8 Server monitoring and seen negative values in the app scope in terms of memory size? I'm getting some peculiar alerts ever few days related to my site adamhowitt.com and don't know where to start. My google foo is weak so I thought I'd throw it out to the crowd.

The server hosts a few sites of mine including this blog and after seeing it hang every now and then I decided to start monitoring alerts (since it's an enterprise box). The alerts that are triggering are that the JVM Memory exceeds 450 MB and the server starts to slow down. When I look at the snapshot it produces and sends me everything looks normal except:

Application Scope Memory Used - -22033448 bytes
[Application Name : Memory Used]
   adamhowitt_site : -22600792 bytes
      [Variable Type : Variable Name : Size]
      CFC : ham : 113168 bytes
      STRUCT : stcservice : 8976 bytes
      STRUCT : stcresource : 6584 bytes
      ARRAY : restypesorted : 448 bytes
      STRUCT : stcresourcetypes : 216 bytes
      STRUCT : stcservicemap : 176 bytes
      68FB39AB-1CBF-0773-47DEBE569016FA50 : strresources : 112 bytes
      68FA822E-1CBF-0773-47CA40FAA0CD3F5A : strportfolio : 112 bytes
      68FABC5A-1CBF-0773-47FF8F2DE5691EB2 : strservices : 112 bytes
      C:\xxx\xxxx\xxx\xx\ : hamroot : 112 bytes

The part that concerns me is the -22,033,448 bytes (or -22 MB) of app scope memory. It's consistently this app and I've looked over my code without success.

I realize the topic narrows my potential audience down to a few people that use alerts but I'd love to work this out. It seems like the continued growth of the JVM memory used on the box is directly tied to this app and the incorrect memory report. Is it a leak? Any help GREATLY appreciated!

Jun 26
2009

WalkJogRun TV Interview

I'm thrilled to announce that I recorded a TV interview in New York last weekend for Better TV and a sneak peak has appeared on YouTube. I was interviewed by Ereka Vetrini who you may remember from season 1 of the Apprentice.

May 06
2009

WalkJogRun iPhone Application v1 is live!

After over 200 hours of development, sweat, tears and late nights after work, Apple finally approved our app. It's available in the App Store today and I'd love to hear your feedback.

Under the hood it connects to WalkJogRun.net built on ColdFusion and MySQL, hosted at Amazon, to pull routes from our database. We've grown to over 400,000 routes in over 200 countries and growing every day.

Learn more here or download a copy here.

Jan 17
2009

BlogCFC 5.9.2.002 Live and Kicking

I've finally upgraded WebDevRef to use BlogCFC 5.9.2.002 so hopefully any commenters or readers who have suffered from the spammers attacking my blog lately will have an extra line of defense.

This was quite painful as a move because I've skipped about 3 major versions and 6 point releases and the database changed drastically. Not to mention the fact that I have a custom design from Jeff that took the best part of today to reintegrate. I hope this is as much use to everyone else as it will be to me.

I've also decided to remove the $5 archive fee - it was a useful experiment and drew some very passionate responses. In 3 months I sold 3 blog entries but it wasn't really about that.

As I've been working for myself this past year I've been struggling to make the time to blog about my CF adventures and justify the time. I felt like I needed a sign that someone thought it was worth the effort I put in. I thought $5 per article would give me that validation but it seems I was a little misguided :-) I've spent a lot of time soul searching and realized that I get a lot of satisfaction just from taking the time to write. So I'm back and ready to blog with some brand spanking new blog features. Thanks to Ray Camden as ever for continuing to lead the development of BlogCFC.

Jan 05
2009

Three finds

I was waiting for a server to reboot earlier today and grabbed my copy of CF8 WACK Volume 2 to read Chapter 31 on improving performance and was glad to find two new tips.  CFCache helps you serve popular pages faster and blockfactor on queries is supposed to make your queries return data faster.

CFCache

I'm not sure how I missed this tag in 9 years of CF usage but it rocks.  Add it to a page bfore anything is outputted to the screen and CF adds both client and server side caching mechanisms!

<cfcache action="cache" timespan="#createTimeSpan(0,1,0,0)#">

Using "Cache" as the action attribute turns on both server and client side caching or you can turn on just one or the other.  

In the example above CF saves the output to your server in the cache directory under your CF installation as an MD5 hash of the script name and query parameters.  Subsequent requests within the hour will be served from this file.  

The client side portion tells the visitor browser the update time of the page such that when a subsequent request is sent, the browser passes that date for CF to compare against it's timespan.  If it has expired, it sends a new copy, otherwise it tells the browser to serve the copy it has.

The book points out that pages using session, client or cookie scopes shouldn't use cfcache because the browser won't cache a copy for each session and your cache will contain data tied to just one session - leading to the wrong info being served to different visitors.

Blockfactor

The second find was the blockfactor attribute for CFQUERY.  The theory is that adding blockfactor to queries returning over 100 rows at a time will be improved but from my tests, I found very little improvement, if any.   I'm connecting CF8 to a remote MySQL 5.1 server.  A little googling revealed Ben Nadel's post from 2006 showing similar results.  One commenter pointed out that Oracle is really the only DBMS that can really use this instruction whereas another poster said that it depends on the datasize of the rows you work with.  If anyone has an update on this, I'd love to get some additional perspective.

CFCache revisited

Just for the sake of committing this to memory, I ran into trouble with CFCache returning Connection failure.  CFCache uses CFHTTP under the hood so a little googling took me to a technote about troubleshooting cfhttp.  I vaguely recalled looking at this before on the server and came across Stephen Erat's post on compression.  If you are running CF7 on Windows 2003 and IIS with compression turned on, chances are your CF Scheduled Tasks appear to be failing when you try to run them in a browser and CFHTTP calls against the box fail.  To fix it, I disabled DEFLATE as a compression option, leaving GZIP and everything started working again.  For a guide on how to enable compression on IIS see AhpHosting's guide or look at your IIS documentation.

My change based on the AHP Hosting guide was to remove CF from the scriptfileextensions list:

cscript.exe adsutil.vbs set W3Svc/Filters/Compression/DEFLATE/HcScriptFileExtensions "asp""dll""exe""aspx"
iisreset.exe /restart

Nov 21
2008

CFHttp Connection Failure on IIS compressed content

I was having trouble calling CFHTTP against one of my CF Servers with a cfhttp connection failure.  It has been causing my scheduled tasks to fail in a peculiar way too.  Whenever you manually click to execute a scheduled task it would report a failure but the task still runs.  For my cfhttp call, I kept getting connection failure status code unavailable.

A quick chat with Patrick at Webapper and a pointed question "is this Windows Server 2003" got me excited but he dashed away to take a call.  I googled around and came across Mark Kruger's post about troubleshooting CFHTTP.  As soon as  I saw the word compression I sat upright in my seat.  He provides two cfhttpparam lines to use to tell IIS not to compress the output and sure enough my problem went away.  Nice post Mark.