Clean Amazon links with TextExpander

Yesterday, Gabe Weatherhead showed his current workflow for making iTunes and Amazon affiliate links. I realized that although I’ve written about my system for iTunes links, I haven’t written up my current TextExpander snippet for Amazon links.1 Then I realized that the new version of TextExpander, with its support of JavaScript for Automation, offers a simpler way of making the links. This post is the result.

“Workflow” may not be the right word for what Gabe’s doing. Through a clever combination of two menubar apps that automatically watch the clipboard and transform certain URLs, he doesn’t actually do any work—he just copies a product URL from his browser and then pastes it. One of the apps cleans the cruft out of URLs on the clipboard and the other adds the affiliate codes. Both work behind the scenes and require no action on his part. I won’t reveal the app combination here; you should go read his post and use his affiliate links.

Gabe used to use Keyboard Maestro to do his affiliate linking. He explains his switch this way:

I’m always happy to replace my scripts with a professionally made and supported alternative and here’s a good way to do that.

I generally prefer to maintain as much control over my workflows as possible, even if it means a little more work for myself. Gabe’s new system relies on a seemingly magical sequencing of the two apps he uses, and I distrust magic.

Here’s my TextExpander snippet for getting Amazon affiliate links:

TextExpander Amazon links with AppleScript

It’s an AppleScript snippet and is triggered by the abbreviation ;amazon. It doesn’t use the clipboard; it assumes that the product page for the item I want to link to is currently in the frontmost Safari tab. Because I’ve learned that this is pretty much always the situation when I make an Amazon link, I save myself a step of copying the URL by having AppleScript get it.

Here’s the AppleScript content of the snippet:

applescript:
1:  set myTag to "andnowitsa085-20"
2:  
3:  tell application "Safari" to set theURL to the URL of the front document
4:  
5:  set cmd to "echo '" & theURL & "' | perl -pe 's#^.*/(?:dp|gp/product)/([^/?]+).*$#$1#'"
6:  set itemID to do shell script cmd
7:  
8:  set aLink to "http://www.amazon.com/gp/product/" & itemID & "?tag=" & myTag

Line 1 puts my Amazon Associates ID into the myTag variable. Line 3 grabs the URL of the frontmost tag and puts it into the theURL variable. If you’re a Chrome user, Line 3 should be

applescript:
tell application "Chrome" to set theURL to the URL of active tab of front window

Lines 5 and 6 set up and run a short shell command that extracts the ASIN (Amazon’s product ID code) from theURL. I do this so I can clean up the URL before adding my affiliate code. Amazon links are often long and nasty, with all sorts of extraneous bits that show how you got to the page. Here’s an example:

http://www.amazon.com/Maltese-Falcon-Vintage-Crime-Lizard-ebook/dp/B004G5ZU32/ref=sr_1_1?ie=UTF8&qid=1433505888&sr=8-1&keywords=maltese+falcon+kindle

Most of that is unnecessary. The key is the ASIN: B004G5ZU32.

The guts of the extraction command is this Perl substitution one-liner:

perl:
perl -pe 's#^.*/(?:dp|gp/product)/([^/?]+).*$#$1#'

The options to perl tell it to read every line of input, apply the substitution command, and print the output.

The substitution command may look a little odd. Search and replace regexes are usually delimited by slashes, but because slashes are in the search pattern, I took advantage of a cute Perl affordance that allows you to use other characters as the delimiters (I chose hashmarks) and avoid the need to escape the slashes with backslashes.

The search pattern looks for either dp/ or gp/product/ in the URL and gets the string that comes after it—everything up to the next slash or question mark. That string is the ASIN, which is captured because of the parentheses. The replacement pattern is just the captured ASIN. There may be better ways to get the ASIN from the URL, but this has worked well for me on a variety of products over a few years. I don’t think it’s ever failed.

Line 8 constructs a simplified Amazon URL to the product and appends my affiliate tag. For the example above, the output is

http://www.amazon.com/gp/product/B004G5ZU32?tag=andnowitsa085-20

which is short and sweet.

After tweeting a screenshot of this snippet, I started thinking about TextExpander 5’s new capabilities and how this script was a good candidate to be rewritten in JavaScript. I’ve always thought the AppleScript snippet was clumsy because of the need to “shell out” to Perl to do the ASIN extraction.2 With the combination of TE5’s support for JavaScript for Automation (JSA) and JavaScript’s built-in regular expressions, the script could be made cleaner and easier to understand.

Here’s the JavaScript content that does the trick:

javascript:
1:  myTag = 'andnowitsa085-20'
2:  currentURL = Application('Safari').windows[0].currentTab.url()
3:  asin = currentURL.replace(/^.*\/(?:dp|gp\/product)\/([^/?]+).*$/, '$1')
4:  cleanedURL = 'http://www.amazon.com/gp/product/' + asin + '?tag=' + myTag

The regular expressions for the search and replace patterns are the same as before, except that I had to escape the slashes in the search pattern. As far as I know, JavaScript doesn’t have Perl’s ability to use non-slash delimiters for regexes.

The JSA syntax for accessing applications reminds me of the long-since deprecated Appscript library for Python, but it’s going to take me a while before I’m truly comfortable with it. As with AppleScript, the real problem is that each application gets to define its own commands, so you have to spend a lot of time in the Script Editor’s dictionary.

Script Editor Safari dictionary

The new JavaScript snippet works well but has one problem: it adds a newline to the end of the URL. At first I thought my script had some hidden defect, but Smile support tells me that JSA always adds a newline to the end of the return value, a bug that Smile will have a fix for in version 5.0.1 of TextExpander. JSA scripts run through the Script Editor definitely don’t have a trailing newline, but maybe the Script Editor itself is deleting it.

Script Editor Amazon snippet

I could probably figure out a way to delete the trailing newline, but I think I’ll just keep the JavaScript version of the snippet on ice until TextExpander 5.0.1 comes out. The older AppleScript version still works, even if it isn’t as elegant.

Update 6/8/15 3:54 PM
The folks at Smile are true to their word. I updated to TextExpander 5.0.1 today, and it fixes the trailing newline problem. I’ve switched from my old AppleScript snippet to the cleaner JavaScript version.


  1. There are one or two older posts that describe workflows I stopped using. 

  2. Yes, there is the Smile (unrelated to Smile Software) AppleScript library for regular expressions from Satimage, but I’ve always been leery of using it. Apple has the unfortunate habit of making internal changes AppleScript every so often, and my fear has been that one of the changes would break the library, leaving me high and dry. It’s true that changes could break other parts of my scripts, but third-party libraries just seem more vulnerable to me.