Elisp: HTML Amazon URL Linkify

By Xah Lee. Date: . Last updated: .

This page shows a example of turning a amazon product url into a customized link.

Problem

Given a URL of any of the following form:

Change it into this form:

<a class="amz" href="http://www.amazon.com/dp/B01KR1C5PY/?tag=xahh-20" title="Kinesis Advantage2 Ergonomic Keyboard KB600">Buy at amazon</a>

Solution

(defvar xah-html-amazon-asso-id nil "A string, amazon associate tracking id, used by `xah-html-amazon-url-to-link'.
It can be empty string, if none.")
(setq xah-html-amazon-asso-id "xahh-20")

(defun xah-html-amazon-get-asin-id (Url)
  "Return the amazon ASIN product id.
If cannot find, return nil.
Version: 2023-07-16"
  (let ((xurl Url))
    (cond
     ((string-match "/dp/\\([[:alnum:]]\\{10\\}\\)/?" xurl) (match-string 1 xurl))
     ((string-match "/dp/\\([[:alnum:]]\\{10\\}\\)\\?tag=" xurl) (match-string 1 xurl))
     ((string-match "/gp/product/\\([[:alnum:]]\\{10\\}\\)" xurl) (match-string 1 xurl))
     ((string-match "/ASIN/\\([[:alnum:]]\\{10\\}\\)" xurl) (match-string 1 xurl))
     ((string-match "/tg/detail/-/\\([[:alnum:]]\\{10\\}\\)/" xurl) (match-string 1 xurl))
     ((string-match "/\\([[:alnum:]]\\{10\\}\\)/" xurl) (match-string 1 xurl))
     ((and
       (equal 10 (length xurl))
       (string-match "\\`\\([[:alnum:]]\\{10\\}\\)\\'" xurl))
      xurl)
     (t nil))))

(defun xah-html-amazon-url-to-link (&optional Begin End)
  "Make the current amazon URL or selection into a link.

When called interactively, `xah-html-amazon-asso-id' is added to the link for amazon affliates.

Examples of amazon product URL formats
https://www.amazon.com/Cyborg-R-T-Gaming-Mouse/dp/B003CP0BHM/ref=pd_sim_e_1
https://www.amazon.com/gp/product/B003CP0BHM
https://www.amazon.com/exec/obidos/ASIN/B003CP0BHM/xahh-20
https://www.amazon.com/exec/obidos/tg/detail/-/B003CP0BHM/
https://www.amazon.com/dp/B003CP0BHM?tag=xahhome-20
https://amzn.to/1F5M1hA

Example output:
<a href=\"https://www.amazon.com/dp/B003CP0BHM/?tag=xahh-20\" title=\"Cyborg R T Gaming Mouse\">amazon</a>

ASIN is a 10 character string that's a product id.

URL `http://xahlee.info/emacs/emacs/elisp_amazon-linkify.html'
Created: 2020-01-15
Version: 2023-07-16"
  (interactive
   (let (xp1 xp2)
     (if (region-active-p)
         (setq xp1 (region-beginning) xp2 (region-end))
       (save-excursion
         (progn
           (skip-chars-backward "^ \t\n")
           (setq xp1 (point))
           (skip-chars-forward "^ \t\n")
           (setq xp2 (point)))))
     (list xp1 xp2)))
  (let (xp1 xp2 xurl xasin xprodName xoutput
            (xassId xah-html-amazon-asso-id))
    (if (and Begin End)
        (setq xp1 Begin  xp2 End)
      (if (region-active-p)
          (setq xp1 (region-beginning) xp2 (region-end))
        (progn
          (skip-chars-backward "^ \t\n")
          (setq xp1 (point))
          (skip-chars-forward "^ \t\n")
          (setq xp2 (point)))))
    (setq xurl (buffer-substring-no-properties xp1 xp2))
    ;; (print (format "xurl %s" xurl))
    (if (string-match "www\.amazon\.com/\\|//amzn\.to/" xurl)
        (if (string-match "//amzn.to/" xurl)
            (progn
              (delete-region xp1 xp2)
              (setq xoutput (format "<a class=\"amz_search\" href=\"%s\" target=\"_blank\">amazon</a>" xurl))
              (insert xoutput)
              xoutput)
          (progn
            (setq xasin (xah-html-amazon-get-asin-id xurl))
            (when (or (not xasin) (string-equal "" xasin)) (error "no amazon ASIN found in url %s" xurl))
            (setq
             xprodName
             (replace-regexp-in-string
              "-" " "
              (if (string-match "amazon\.com/\\([^/]+?\\)/dp/" xurl)
                  (match-string 1 xurl)
                (progn (message "no product name found") ""))))
            (delete-region xp1 xp2)
            (setq xoutput (format "<a class=\"amz\" href=\"https://www.amazon.com/dp/%s/?tag=%s\" title=\"%s\" target=\"_blank\">Buy at amazon</a>" xasin xassId xprodName))
            (insert xoutput)
            (if (search-backward "title=\"\"" nil t)
                (progn
                  (goto-char (match-end 0))
                  (backward-char)
                  (push-mark (point)))
              nil
              ))
          xoutput)
      nil)))