Org-protocol is an extension to Org Mode that allows you to send information to Emacs from web browsers. You can use it to save a bookmark in Org Mode, save a selected text as a note, or insert a link to the current web page. This post describes how to configure org-protocol to accomplish those tasks from Chrome.

Configuring org-protocol

Org-protocol is installed as part of org layer of Spacemacs, but it is not enabled by default. To enable org-protocol, add org-protocol to org-modules variable.

Integration with the desktop

You also have to add a scheme handler to your desktop environment. This subsection describes an instruction for Cinnamon.

Add ~/.local/share/applications/emacsclient.desktop file with the following content:

[Desktop Entry]
Name=Emacsclient
Exec=emacsclient %u
Icon=emacs-icon
Type=Application
Terminal=false
MimeType=x-scheme-handler/org-protocol

Add the following entry to Default Applications section in your ~/.local/share/applications/mimeapps.list:

x-scheme-handler/org-protocol=emacsclient.desktop

Run update-desktop-database program.

I automated this process as an Ansible role. My org-protocol role consists of the following files:

For other desktop environments, follow a corresponding section in the documentation.

Org-capture templates

I configured the following org-capture templates for org-protocol:

  • A quote from the web page via org-protocol: Select text in the web page, and add it to my Org file for notes
  • A bookmark via org-protocol: Add a bookmark of the web page to an Org file

Add the following entries to org-capture-templates variable:

        ("Pn" "(Protocol quote)" entry (file+headline my/captured-notes-file "Notes from the web")
         "* %:description\nCaptured at %u\n%c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n%?")
        ("Pb" "(Protocol bookmark)" entry (file+datetree my/browser-bookmarks-file)
         "* %:description \nCaptured at %U\n[[%:link][%:description]]\n%?\n")

The file names in the templates are defined as constants:

(defconst my/captured-notes-file "~/org/todo/NotesInbox.org")
(defconst my/browser-bookmarks-file "~/org/seq/BrowserBookmarks.org")

Browser integration

To create a bookmark, add a note, or store a link, you have to somehow generate links under org-protocol scheme in your browser. In Chrome (Chromium), there are the following solutions for this task:

  • Create custom bookmarklets to invoke org-protocol
  • Use org-capture extension from the Chrome web store
  • Use a Chrome extension to run custom JavaScript

org-capture extension seems to be rather limited, so I have decided to install a Chrome extension that can run any user JavaScript. I found an extension named ShortKeys, which runs custom JavaScript with a shortcut key. For mouse operations, I also created bookmarklets for some of the operations.

Add a shortcut to ShortKeys with the following JavaScript:

location.href ='org-protocol://store-link?url=' +encodeURIComponent(location.href) + '&title=' + encodeURIComponent(document.title);

Shortcut keys configured by ShortKeys do not work on some web pages, e.g. Chrome Web Store. Even in such situations, you can still use a bookmarklet instead. Create a bookmark with the following URL:

javascript:location.href ='org-protocol://store-link?url=' + encodeURIComponent(location.href) + '&title=' + encodeURIComponent(document.title);

The default handler does not raise the Emacs frame. You probably want to insert the stored link immediately, so add the following advice to your init.el:

(defun my-org-protocol-store-link-advice (orig &rest args)
  (raise-frame)
  (apply orig args))

(advice-add 'org-protocol-store-link :around
            #'my-org-protocol-store-link-advice)

You can use either the shortcut key or the bookmarklet to store a link to the current web page via org-protocol. Then you can use org-insert-last-stored-link (C-c M-l) or helm-kill-ring to insert the stored link.

Creating a bookmark

ShortKeys:

location.href = 'org-protocol://capture?template=Pb&url='+ 
        encodeURIComponent(location.href) + '&title=' +
        encodeURIComponent(document.title)

Bookmarklet:

javascript:location.href = 'org-protocol://capture?template=Pb&url='+ 
        encodeURIComponent(location.href) + '&title=' +
        encodeURIComponent(document.title)

Quoting text as a note

ShortKeys:

var selText = getSelection().toString();
if (selText) {
    location.href = 'org-protocol://capture?template=Pn&url='+ 
        encodeURIComponent(location.href) + '&title=' +
        encodeURIComponent(document.title) + '&body=' + 
        encodeURIComponent(selText);
} else {
    alert("To add a quote, select a range in the web page.");
}

I haven’t created a bookmarklet for this task.

Wrapping up

Now you can store a link, create a bookmark, or quote a web page in Org Mode from the Chrome web browser. It is quite convenient.