Blog from Org mode to wordpress
Emacs Lisp Makefile
Switch branches/tags
Pull request Compare This branch is even with org2blog:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Org2blog Readme


org2blog/wp is a tool to publish directly from Emacs’s org-mode to WordPress blogs. org2blog/wp is one of the two packages named org2blog. The other is org2blog/atom by Tom Breton.

org2blog/wp should, ideally, work with any platform that supports xml-rpc but some of WordPress specific features may not work.

org2blog was inspired by and based on a WordPress posting client for muse-mode written by Ashish Shukla.

org2blog is licensed under GPLv3


Download org2blog from GitHub

git clone

Add the org2blog directory to your load path and then add

(setq load-path (cons "~/.emacs.d/org2blog/" load-path))
(require 'org2blog-autoloads)

to your dot emacs.


  1. org2blog depends on
    • xml-rpc available at GitHub
    • metaweblog.el available here
    • htmlize available here

    Add them to your load-path before using org2blog.

  2. Make sure you have org-mode 8.3 or later installed.

Unicode Character Support

  1. As of <2017-06-26 Mon> if you use Unicode characters in your posts or pages then you need to use this patched version of xml-rpc
  2. Installation steps
    • Back up your local copy of xml-rpc.el
    • Copy this patched version of xml-rpc.el to the xml-rpc directory
    • Delete xml-rpc.elc
    • Restart Emacs


Defining your blog setup

Note - This setup works only for org2blog version >=0.3. For lower versions of org2blog check the README from the commit e37126e

You can (should) tell org2blog where your blogs are and optionally specify different values for some options. This is done by customising the variable org2blog/wp-blog-alist.

For example:

(setq org2blog/wp-blog-alist
         :url ""
         :username "username"
         :default-title "Hello World"
         :default-categories ("org2blog" "emacs")
         :tags-as-categories nil)
         :url ""
         :username "admin")))

This defines two blogs identified by the terms wordpress and my-blog.

The variables in the plist set for each blog over-ride the global values of the corresponding variables. url and username are mandatory variables. Others are optional. If you customize the variable org2blog/wp-blog-alist there is detail information about the meaning of each property.

You can also use .netrc or .authinfo files to save your usernames and passwords.

Your .netrc should look like this

machine myblog login myusername password myrealpassword

Then, use these details, as shown below.

(require 'auth-source) ;; or nothing if already in the load-path

(let (credentials)
  ;; only required if your auth file is not already in the list of auth-sources
  (add-to-list 'auth-sources "~/.netrc")
  (setq credentials (auth-source-user-and-password "myblog"))
  (setq org2blog/wp-blog-alist
           :url ""
           :username ,(car credentials)
           :password ,(cadr credentials)))))

To browse or customize other variables use the customize group function.

M-x customize-group org2blog/wp RET

Logging In

Use M-x org2blog/wp-login. This function ask you for the name of one of the blogs you have configured in the org2blog/wp-blog-alist variable described above and will ask for your password. The counterpart of this function is M-x org2blog/wp-logout, which will log you out of the active blog.

Writing a new post

Use M-x org2blog/wp-new-entry.

  • Tags and Categories are comma or space separated values. Completion (for both) is triggered using C-c t. If a new category is used you will be prompted before adding it.
  • The excerpt for a post can be written as #+DESCRIPTION.
  • The Permalink of a post can be set using #+PERMALINK.
  • The parent for a page can be specified using #+PARENT. C-c t again provides completion for the page name.

Using post templates

Custom post templates can be specified by modifying variables org2blog/wp-buffer-template and org2blog/wp-buffer-format-function.

For example:

(setq org2blog/wp-buffer-template
#+TITLE: %s
#+DATE: %s
(defun my-format-function (format-string)
  (format format-string
          (format-time-string "%d-%m-%Y" (current-time)))))
(setq org2blog/wp-buffer-format-function 'my-format-function)

org2blog/wp-new-entry will now create buffers begining with a default title and the current date.

Updating an existing post

To update a blog post, you can simply edit the content of the org file and republish using org2blog. The POSTID saved in the file, ensures that the same blog post is updated, and a new post is not made.


post buffer as draftC-c M-p dM-x org2blog/wp-post-buffer
publish bufferC-c M-p pC-u M-x org2blog/wp-post-buffer
post buffer as page draftC-c M-p DM-x org2blog/wp-post-buffer-as-page
publish buffer as pageC-c M-p PC-u M-x org2blog/wp-post-buffer-as-page
After Publishing Access The Metadata

Now your post or page exists both in your Org-Mode file on your computer, and also in WordPress itself. That page or post inside of WordPress contains a lot of metadata and you might be interested in some of it. Here is documentation covering all of the fields. You can easily access that data using a hook function.

After publishing your post or page, Org2Blog calls the functions in org2blog/wp-after-new-post-or-page-functions passing them the post or page metadata. Maybe you’ve never seen a hook function like this before because it takes an argument. They are still just plain old functions. Here they need to accept one argument so that Org2Blog can give you that metadata. It is pretty simple.

Here is an example that displays your post or page information in the *Messages* buffer:

(add-hook 'org2blog/wp-after-new-post-or-page-functions (lambda (p) (pp p)))

Post your existing org-files too

  • Add #+TITLE, #+OPTIONS, #+TAGS, #+CATEGORY, #+DESCRIPTION, #+DATE, to your file. (All of these are Optional)
  • Add a #+POSTID to edit an existing post.
  • Post buffer using the function names, as above.

Posting a subtree

  • Use M-x org2blog/wp-post-subtree.
  • Tags of the subtree will be used for tags.
  • Other properties can be set using a property drawer. The properties use the same names as the buffer variables.
  • POST_DATE sets the date to be used for the post. If it is not present, SCHEDULED, DEADLINE or any other active or inactive time-stamps are used.
  • The headline is used as the title of the post. But, TITLE can be used to use a different title.

Posting source code blocks

Babel source blocks or example code is automatically posted in <pre> tags. You can also ask org2blog to use WordPress’s sourcecode shortcode blocks.

To use this this feature, install a shortcode plugin. For example, SyntaxHighlighter Evolved seems to work well.

To use this, you need to set the variable org2blog/wp-use-sourcecode-shortcode to t. WordPress’s sourcecode shortcode blocks can be given various configuration parameters. These can be passed to the exported sourcecode shortcode blocks via an #+ATTR_WP line immediately preceding the #+BEGIN_SRC line, e.g.

#+ATTR_WP: :syntaxhl light=true

Delete an entry or a page

  • If you are in the buffer of the entry/page, with #+POSTID present on the page, use:

    M-x org2blog/wp-delete-entry or M-x org2blog/wp-delete-page

  • If you want to delete a particular post (whose post-id is known) from any buffer, use

    C-u post-id M-x org2blog/wp-delete-entry.

Similarly, for a page.

org2blog mode key-bindings and auto loading

  • org2blog/wp-mode defines the following key-bindings
    C-c ppublish buffer
    C-c dpost as draft
    C-c tcomplete tag or parent page name
Auto Loading org2blog Mode
  • Add org2blog/wp-org-mode-hook-fn to org-mode-hook
  • So that org2blog/wp-mode is automatically enabled when #+ORG2BLOG: is present
  • Add code like this somewhere after you load Org-Mode and org2blog
    (add-hook 'org-mode-hook #'org2blog/wp-org-mode-hook-fn)
  • Add #+ORG2BLOG: to your file
    • When you create a new entry it is automatically created

Uploading Images or Files

Only in-line images and linked images (or files) with file:// URLs are supported. They will be uploaded to the media library and the links will be updated. Information about uploaded files is added as a comment to the post itself.

Captions and attributes as defined in org-mode will be preserved, but these attributes are not saved with the image to the library itself.

“Dashboard” of all posts

org2blog makes it easy to manage your blog-posts by actually keeping track of all the posts you make from it, in a simple org-table. By default it is saved in a file in the org-directory. This is meant to be a dashboard of sorts, and is an optional feature that can be turned off.

MathJax Support

MathJax is an open-source JavaScript display engine for LaTeX, MathML, and AsciiMath notation that works in all modern browsers.”

  • Whether you use MathJax with a WordPress plugin, manual inclusion, or any other means you need to be aware of MathJax’s CDN options
    • If you want predictibility then reference a specific release number. For example, this configuration uses 2.7.1
  • Disable translation to wp-latex syntax
    • (setq org2blog/wp-use-wp-latex nil)
  • Setup the MathJax-LaTeX plugin
    • Install it
    • Configure it
      • Force Load: TRUE
      • Default [latex] syntax attribute: Inline
      • Use wp-latex syntax? TRUE
      • Use MathJax CDN Service? FALSE
      • Custom MathJax location?
      • MathJax Configuration: default
  • Test it out using these (and more) examples
    - The word LaTeX
      - $\LaTeX$
    - Inline
      - $\sum_{i=0}^n i^2 = \frac{(n^2+n)(2n+1)}{6}$
    - Equation
      - $$\sum_{i=0}^n i^2 = \frac{(n^2+n)(2n+1)}{6}$$
  • Test it locally using HTML export settings
    #+HTML_HEAD: <script type="text/javascript"
    #+HTML_HEAD:   src="">
    #+HTML_HEAD: </script>


  1. You may want to look at the Export options and HTML export sections of the org-manual.
  2. If you wish to post to blogger from org-mode, look at -
    1. org2blog/atom, a g-client extension by Tom Breton
    2. org-googlecl by Richard Riley – uses googlecl
  3. Please go through the README and the FAQ, before writing to me. Also, looking at M-x customize-group org2blog-wp might help.
  4. If you have an issue/bug/feature request, use the issue tracker on git or drop a mail to punchagan+org2blog[at]gmail[dot]com. I’d also appreciate patches/suggestions to improve the documentation. Feel free to drop in with general comments, too. I’d love to hear from you! NOTE: If you are using the package from ELPA, please try using the latest git version before filing a bug report.
  5. Feel free to add your site to the list of sites using org2blog, on the wiki at github.


  • How many blogs can I configure with org2blog?

    You can configure and use any number of blogs with org2blog/wp. Use the org2blog/wp-blog-alist variable to configure each blog. Look at the Defining your blog setup section, in the README. But, note that you can be logged in, to just one blog at a time.

  • How do I change the default title of a new post?
    (setq org2blog/wp-default-title "My New Title")
  • How do I change the default title for one blog alone?

    Set the relevant (:default-title) variable in the org2blog/wp-blog-alist variable.

  • I do not use tags. I wish to use them as categories. How?

    Setting the org2blog/wp-use-tags-as-categories variable will do that for all the blogs.

    (setq org2blog/wp-use-tags-as-categories t)

    Instead, you can set the corresponding variable for each blog that you are using.

  • Can I configure org2blog to confirm before publishing a post?
    (setq org2blog/wp-confirm-post t)
  • I wish to customize the default template of a new post. How do I do it?

    Customize the variable org2blog/wp-buffer-template.

  • New-lines are not handled properly. Why?

    The behaviour of new-lines has been working since a little before version 0.3. It is highly recommended that you use the latest git version of org2blog.

    By default, new lines are stripped off from the org buffer. To retain new-lines, unset the org2blog/wp-keep-new-lines variable.

  • Why aren’t my SRC blocks not enclosed in [sourcecode] [/sourcecode] block?

    Set the org2blog/wp-use-sourcecode-shortcode variable to turn on this behaviour. You may also set it at a per-blog level, if you choose.

  • Is wordpress the only CMS/Blog-engine that org2blog/wp supports?

    Any blog engine using the metaweblog API should work, theoretically. But, it is not tested with other blog engines.

    One happy user reports that org2blog also works with the Dotclear weblog engine.

  • Is there a way to import from WordPress or other blogs into the org2blog post format?

    I’ve a simple python script that uses pandoc to convert from WordPress export xml to org2blog posts. It could easily be tweaked to write importers for other kinds of blogs.

  • How do I split a post into an introductory paragraph and a full view.

    Just put in

    #+HTML: <!--more-->

    at the location where you wish to split the post.

Feature Request List

Use the WordPress REST API Instead Of MetaWeblog