Apple affiliate links via TextExpander

This is a relatively simple way to get affiliate links to Apple’s digital offerings: Mac apps, iOS apps, songs, albums, ebooks, audiobooks, movies, TV shows—anything Apple sells through iTunes or the Mac App Store. It’s a bottom-up rewrite of a workflow I described last week that’s more accurate and more flexible.

Affiliate link primer

Let’s start by describing what an affiliate link is. Like Amazon and many other online retailers, Apple has an affiliates program whereby you can get a commission on products Apple sells if you steer someone to its online store to buy them. It does this through something called an affiliate link, a special URL which, when followed, both takes the user to the proper page on the store and tells Apple that you sent them there.

In the US, Apple’s affiliate program is administered through LinkShare. If you want to be an affiliate, you’ll have to establish an account with them. Certain unique parts of your affiliate URL will be tied to your account. There are affiliate programs for people in other countries, but what I’m describing here works only for LinkShare accounts. It could be adapted to other programs, but I haven’t done that.

The standard way to get an affiliate link is to use Apple’s Link Maker tool, a web page that lets you search for items in the Stores and generates links for them.

Apple's Link Maker page

It’s not a bad service, but there are two things I don’t like about it:

  1. I have to go to the Link Maker page in my browser. I’d rather work directly from the product page in iTunes or the App Store.
  2. There’s a little too much busy work. I have to enter a search term, choose the product type from a popup, click the Search button to do the search, pick the product from the list of search results—sometimes it’s at the top; often it isn’t—and, finally, copy the link URL.

The TextExpander workflow

With my TextExpander snippet, the workflow is much faster. Here are the steps:

I start on a product page in Safari (on the Preview page), iTunes, or the Mac App Store. If I’m in Safari, I copy the page’s URL. If I’m in iTunes or the Mac App Store, I click the little popup menu and choose Copy Link.

PCalc link in the App Store

What I now have on the clipboard is not an affiliate link, but it contains the information necessary to make one. I switch to wherever I want the affiliate link to go (typically TextMate) and type ;store. This is the abbreviation for my TextExpander shell script snippet (a Python script, actually) that transforms the link on the clipboard into an affiliate link and replaces ;store with it.

Done. No searching, no choosing of item type, no extra clicking of any kind. I’d like to get rid of the initial copying of the link, but I’m not sure how to extract the product link from iTunes or the Mac App Store through a script.

The affiliate URL will look something like this

http://click.linksynergy.com/fs-bin/stat?id=L4JhWyGwYTM&offerid=146261&
type=3&subid=0&tmpid=1826&RD_PARM1=http%253A%252F%252Fitunes.apple.com
%252Fus%252Fapp%252Fpcalc-rpn-calculator%252Fid284666222%253Fmt
%253D8%2526uo%253D4%253FpartnerId%253D30

but without the line breaks. Some of this is boilerplate, some is specific to my affiliate account, and some is specific to the item.

The Python internals

Here’s the script that makes the affiliate link from the contents of the clipboard:

python:
 1:  #!/usr/bin/python
 2:  
 3:  from subprocess import check_output
 4:  from urllib import quote, urlopen
 5:  from re import search
 6:  from json import load
 7:  from sys import stdout
 8:  
 9:  # The procedure followed here is taken from Apple's instructions for searching:
10:  # http://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html
11:  # and for linking:
12:  # http://www.apple.com/itunes/affiliates/resources/documentation/linking-to-the-itunes-music-store.html
13:  
14:  # The LinkShare boilerplate for all my affiliate links.
15:  prefix ='http://click.linksynergy.com/fs-bin/stat?id=put&your&stuff&in &here&up&through&RD_PARM1='
16:  
17:  # Get the URL from the clipboard.
18:  clipURL = check_output('pbpaste')
19:  
20:  try:
21:    # Extract the ID .
22:    m = search(r'(/id|\?id=)(\d+)', clipURL)
23:    itemID = m.group(2)
24:    
25:    # Look up the canonical URL for the item.
26:    json = load(urlopen('http://itunes.apple.com/lookup?id=%s' % itemID))
27:    item = json['results'][0]
28:    if 'collectionViewUrl' in item:
29:      itemURL = item['collectionViewUrl']
30:    else:
31:      itemURL = item['trackViewUrl']
32:    
33:    # Add the partnerId parameter to the URL. If there are already queries,
34:    # add it as an additional one; if not, add it as the only one.
35:    if '?' in itemURL:
36:      itemURL += '&partnerId=30'
37:    else:
38:      itemURL += '?partnerId=30'
39:    
40:    # Percent-encode the URL twice.
41:    encodedURL = quote(quote(itemURL, ''), '')
42:    
43:    # Prefix it with the boilerplate.
44:    stdout.write(prefix + encodedURL)
45:  
46:  except:
47:    stdout.write('Wrong type of data on clipboard')

Update 1/5/12
Not sure how I managed this, but I had Lines 36 and 38 switched when I first posted this. Even weirder, it seemed to work. Anyway, it’s fixed now.

It’s the content of a TextExpander shell script snippet with an abbreviation of ;store.

TextExpander Apple affiliate snippet

The script follows the advice given by Apple on its Search API and Advanced Affiliate Linking pages. Line 15 defines the first part of the affiliate URL, with the boilerplate and account-specific information. What you see there is dummy text; if you want to use this script, you’ll have to put your own information in this line. The best way to get it is to make an affiliate link for your account with the Link Maker tool (any product will do) and copy everything through &RD_PARM1=.

Line 18 gets the content of the clipboard, and Lines 22-23 pull out from it the ID number associated with the item. This number is the key to everything that follows. For reasons I can’t fathom, there can be many URLs that link to an item. The one thing they all have in common is the ID number.

Line 26 sends an inquiry to Apple using the ID number. It returns a chunk of information about the item in JSON format. Lines 27-31 get the one part of that chunk we want: a URL for the product in the form necessary to construct an affiliate link.1

Lines 35-38 add a short, boilerplate suffix to the product URL, and Line 41 percent-encodes it twice. Why twice? Ask Apple. I just do what they say.

Finally, Line 44 sticks the prefix and the double-encoded URL together into a single URL and prints it to standard output.

All of this stuff is wrapped in a try/except structure to catch any of the multitude of errors that could arise. If an error is found, Line 47 prints a message to that effect.

Remembrance of things past

This snippet is, you may have noticed, a ground-up rewrite of the affiliate link generating system I wrote about last week. That earlier version, which I adapted from Gabe Weatherhead’s original, used Fake and AppleScript to search for Mac or iOS apps and return their affiliate link on the clipboard. After reading my post and Gabe’s, Brett Terpstra pointed out the two aforelinked Apple pages and suggested the information in them could be used to make the workflow more efficient. He was right.

The problems with the Fake/AppleScript system were:

  1. It left Fake running after it had done its job.
  2. It returned the affiliate URL of the top search result, which was not necessarily the product I wanted to link to. For example, searching for “elements” would never return a link to Elements because the search results were long and the note-taking app was always way down the list.
  3. It was limited to Mac and iOS apps.

I could have solved the first problem by including a quit command in the AppleScript, but I needed to keep Fake open so I could see at a glance whether the top search result was the link I wanted.

The new system avoids these problems by starting from the item you want to link to and using API calls instead of Fake’s web automation.

I’m not so self assured

As I said earlier, I’d really like to cut that “copy link” step out of the workflow, but I don’t know how to do it. I’ve looked through the AppleScript dictionaries of iTunes and App Store and haven’t found any way to snag the link of the product currently on display (possibly because those apps don’t always have a product on display). If you have any ideas—other than GUI scripting, which I already know about—I’d be happy to hear them.

Update 1/5/12
This morning I got an email from David Smith,2 who pointed me to this post of his from just last week. David obviously spent more time reading Apple’s Advanced Affiliate Linking page than I did. Further down the page, in a section entitled “Using Affiliate Links Inside Apps,” Apple explains how you can make a shorter affiliate link that starts with http://itunes.apple.com instead of the more inscrutable http://click.linksynergy.com. David’s post gives a clear set of instructions for implementing these shorter affiliate links and discusses the advantages and disadvantages of using them.

I like this solution. Not only is the link shorter and easier to read, but as David points out, it avoids the LinkShare two-step, in which you first jump to an apple.com page in your browser, and then jump to the product page in iTunes or the App Store.

This gain comes with a cost. Your LinkShare reports will no longer have any information on how many times your links were clicked—the Clicks column in the reports will always show zero. Sales and commissions will still be reported, of course.

I’ll probably be writing another TextExpander snippet in next day or two to automate the creation of these shorter, easy-to-read links. [Done] Tracking click counts doesn’t matter much to me.


  1. It’s possible that other forms of the product URL will work, but since Link Maker uses the one from the JSON chunk, that’s what I wanted to use, too. Seemed safer that way. 

  2. Yes, it’s the same David Smith of FiveLive, the Dan Benjamin-approved 5by5 live feed listening app.