Enable AMP Analytics using a custom WordPress plugin

I’ve recently enabled support for Facebook Instant Articles, Google AMP, and Apple News on this blog following this enlightening article.

It wasn’t exactly plain sailing; AMP needs a logo, and a featured image set for every article (both of which must be above a minimum size); the Instant Articles plugin has a feed url which my feedburner plugin breaks; Apple News needs some real tweaking, but still strips out code blocks from posts.

However, I also wanted to get my AMP plugin hooked up with my Google Analytics tracking. Luckily, the plugin from Automattic has support for this, but I needed to implement the analytics configuration using a custom theme or a custom plugin.

I’m not a PHP developer, let alone a WordPress developer, so this doesn’t come naturally to me! Please bear with me..

Continue reading

Aside #10 – Send To Kindle WordPress plugin

Whilst uber geeking it up (streaming a HD Wired.com video podcast to my TV via a raspberry pi with the world’s teeniest usb wifi and a USB battery pack – my next RPi post will cover this!) I learned that WordPress has a new plugin for sending posts straight to your Kindle!

Great idea, since I’m always wanting to read some long post but don’t have the time, so would love a “read it later” button to push it to another device.

Installing the plugin

Here’s all it took to install on this blog:

Search for "Send to Kindle” from the plugin page on your wordpress install/site.

Send To Kindle - finding plugin 1

Find the “Send To Kindle” plugin from “Amazon Inc” and click “install”

Send To Kindle - finding plugin 2

Once installed you have a couple of options

Send To Kindle - plugin installed

You can configure the basics, such as where to display it, what font to use, what text to display (you’re limited to “Kindle”, “Send to Kindle”, or nothing..), which colour scheme to use, what size icon and of which colour, what colour background, and whether to display a border or not.

Send To Kindle - plugin setup - basic

If you want to mess around with the display yourself then the Advanced controls allow this, as well as some default settings of where to pull the post details from.

Send To Kindle - plugin setup - advanced

Then this will appear wherever you’ve chosen.

Button in action

Here it is on a post

Send To Kindle - button appearing

Clicking that  button pops up a window to get you to log in to your Amazon account …

Send To Kindle - Log In

and choose which device you send it to…

Send To Kindle - Configure Settings

Then content will be loaded and processed for Kindle viewing:

Send To Kindle - Awaiting Content  

Which means it ends up looking like this:

Send To Kindle - Content Loaded

Clicking the “Send” button first gives you a quick thinky thinky image:

Send To Kindle - Uploading

Before shortly letting you know it’s all ok

Send To Kindle - Upload Complete 

 

Viewing the post on your Kindle

You can then see this post on your Kindle the next time you turn it on in a Wifi (or 3G if your Kindle has Whispernet and you selected that as the delivery mechanism) area:

Here I have a couple of posts sent to my Kindle displaying on the home screen:

Send To Kindle - Viewing post content on Kindle - Listing

Selecting the RaspberryPi Part #2 post (which you can’t tell from the two on the home screen at the moment – I can probably sort this by changing the selectors in the advanced settings on the plugin page) here we have some basic text content:

Send To Kindle - Viewing post content on Kindle

Some image content:

Send To Kindle - Viewing post content on Kindle - Image

And some code example content:

Send To Kindle - Viewing post content on Kindle - Code

The code example is rendered via the wonderful SyntaxHighlighter plugin, hence the weird “view sourceprint?” link at the top of each one.

Summary

Pretty cool concept, huh? No idea if my posts are worth doing this to, but I like the idea of it. And it’s easy too; once installed you can either say “put this everywhere on every post” or just use the [sendToKindle] smart code.

Aside #1 – EC2 WordPress Issues

Whilst I’ve been attempting to learn a new thing each month this year, I’ve been finding it really tricky to keep to the pretty loose schedule. As such, I though I’d try and note down every time a shiny new thing takes my interest, so that I have some idea why I’m incapable of completing a series of blog posts.

EC2 Issues

I’m really having problems with EC2 these days, and I’m constantly being dragged back into finding out what the problem(s) is/are..

Restarts don’t restart

Had to add entries into the rc.local to restart httpd and mysql, and also had to change the permissions on the file to allow it to be executed upon restart (sudo chmod 6755 /etc/rc.d/rc.local).

Instigator
— because the blog went down a couple of times and I didn’t notice!

Backups kill the site!

WordPress 2 DropBox – killed me. As does mysqldump in general.

DB backup

mysqldump --add-drop-table -u <username> -p <database> | bzip2 -czs > <db backup filename>.bz2

website backup

tar -cjf <site backup filename>.bz2 /var/www

Instigator
— wordpress kept telling me to upgrade to the latest version, but also had a big MAKE SURE YOU BACKUP FIRST warning; and the WordPress 2 DropBox plugin killed my EC2 microinstance.

WordPress: Alerting on high CPU usage

#!/bin/sh
#
# Script to check CPU usage and tweet me if it's over a threshold
#
if [ ` uptime | awk '{ print$10 }' | cut -d. -f1 ` -gt 50 ];
then
    sudo python /home/ec2-user/tweepy/ec2Event.py '@rposbo LOAD: ' < /tmp/load
else
    echo lo
fi

This totally doesn’t work! Uptime seems to happily report low CPU usage even when the site is dying. Maybe CPU is low and mem is high.. hmm.. may have to change that check.

Instigator
— attempting to backup wordpress keeps breaking my site, dammit!

logstash, graphite, statsd

Currently trying to get those three to work together and help me find out why the EC2 microinstance is so.. uh.. micro..

Instigator
— EC2 just keeps on dying and I need to find out why

Creating a SublimeText plugin to publish markdown to WordPress

I’ve been using SublimeText for a while now as a no-frills text editor; it has a nice Zen mode which hides all of the tabs and menus and pushes it to full screen which I’ve found perfect for taking notes during seminars:

SublimeText2 Zen mode

I have been trying to take notes using the markdown sytnax, but have found the process between taking the notes in markdown, converting them to HTML, and publishing the HTML to a blog a bit of a pain.

Given that SublimeText supports extension via plugin scripts written in Python, I’ve knocked together an extension which will

  1. convert the markdown to html
  2. push the html directly to wordpress

Before I get into the details of the script, maybe a little background would be useful:

What’s Markdown?

A lightweight markup language for writing human-readable content which can be compiled into HTML. Being able to write a lovely HTML blog post in a very basic text editor instead of the bloated Windows Live Writer is extremely refreshing.

For example, to make a line a <h1> header, prefix it with a #. For <h2>, use ##. For <h3> ###. Easy.

Want a link? Try surrounding it with square brackets and putting the url just after it in round brackets: [Something like this](which links here). It’s a really easy “language” and actually looks decent enough to just read on its own.

To include an image you just need to write ![alt text](image url)

A syntax reference page can be found here.

One problem I do have is the basic support for code highlighting within markdown is poor, obviously, since HTML only has a single <code> block. The Markdown generated HTML conflicts with my wordpress Syntaxhighlighter plugin, hence the ugly clode blocks in this post.

There is support for “fenced-code-blocks” wihtin many implementations of markdown, and with the library that I’m also using, but this is still not playing nicely with Syntaxhighlighter. I’m sure I’ll figure something out eventually – please bear with me until then.

I use the fantastic python-markdown2 library to convert markdown to HTML on the fly; I just had to copy the lib/markdown2.py file from the github repo into the sublimetext “plugins” directory – I created a Markdown subdirectory for it – and reference it from my script. i.e.,

post_content = str(markdown2.markdown(post_content,extras=["code-friendly"]))

What’s Python?

Python

A functional scripting language. I found it really quite tricky to work with and had to install PythonShell as a powershell-ish window for testing out python commands before putting them to work in the plugin script. What’s not great fun is that SublimeText2 installs a different version of Python to PythonShell to version 1 of SublimeText to any version you explicitly install yourself.

Some commands and syntax will work in one version of python and not others

One great example is setting up a proxy; the syntax for this is completely different between versions of python and whatever example code you’re reading might be using the syntax that your version of python doesn’t support.

Working with a functional language took a lot of getting used to; I’d want to return an object from a method but had to instead return a comma delimited list of base types. It’s all a little odd to me, and my messy code shows that!

What’s WordPress?

Wordpress

A popular free blog engine that’s used as a CMS for some small businesses. It has an XML RPC API which conforms to the MetaWeblog spec, and you can really dig into this by looking through the php files that make up a WordPress installation.

Since I’m using Amazon EC2 as my wordpress host I can use Kitty to SSH in and browse to /var/www/html/xmlrpc.php to see the metaweblog service api itself. That file references wp-includes/class-wp-xmlrpc-server.php which contains all of the underlying functionality for the api implementation. This is great reference material to make sure you’re passing the correct values of the correct types to the correct endpoints.

Details

The sublimemarkpress plugin is intended to:

  1. check the contents of a config file for your blog access details
  2. scan the contents of the active window to get the posts details, such as post ID (to make it an Update instead of a Create), tags, and status
  3. convert the text from Markdown to HTML
  4. Push the HTML to the metaweblog endpoint with the correct blog/post details

1. Getting the Blog setup details from a config file

The plugin relies on a settings file called “sublimemarkpress.sublime-settings” using the structure:

{
    "xmlrpcurl": <URL to xml rpc endpoint>,
    "username": <username>,
    "password": <password>
}

to read it:

s = sublime.load_settings("sublimemarkpress.sublime-settings")
mbURL = s.get("xmlrpcurl")
mbUsername = s.get("username")
mbPassword = s.get("password")

2. Get the text and strip out the blog post data

The plugin expects the top of your text file/active window to have optional tags to define blog post details:

<!-- 
#post_id:<id of existing post - optional>
#tags:<comma delimited list of post tags - optional>
#status:<draft or publish - optional>
-->

To get the entire contents of the active window:

all_lines_in_page = self.view.lines(sublime.Region(0, self.view.size()))

Then to extract the header details:

post_id, tags, status, has_header_content = self.GetHeaderContent(all_lines_in_page, header_lines)

where GetHeaderContent is the hack-y:

def GetHeaderContent(self, all_lines_in_page, header_lines):
    page_info = {"has_header_content":False,"post_id":None, "tags":"", "status":""}

    if self.view.substr(all_lines_in_page[0]).startswith("<!--"):
        page_info["has_header_content"] = True
        self.MoveCurrentLineToHeader(header_lines, all_lines_in_page)

        # post_id
        if self.view.substr(all_lines_in_page[0]).startswith("#post_id"):
            page_info["post_id"] = self.view.substr(all_lines_in_page[0]).split(":")[1]
            self.MoveCurrentLineToHeader(header_lines, all_lines_in_page)

        #post tags
        if self.view.substr(all_lines_in_page[0]).startswith("#tags"):
            page_info["tags"] = self.view.substr(all_lines_in_page[0]).split(":")[1]
            self.MoveCurrentLineToHeader(header_lines, all_lines_in_page)

        #post status
        if self.view.substr(all_lines_in_page[0]).startswith("#status"):
            page_info["status"] = self.view.substr(all_lines_in_page[0]).split(":")[1]
            self.MoveCurrentLineToHeader(header_lines, all_lines_in_page)

        self.MoveCurrentLineToHeader(header_lines, all_lines_in_page) # removes the closing comment tag
    return page_info["post_id"],page_info["tags"],page_info["status"],page_info["has_header_content"]

def MoveCurrentLineToHeader(self, header_lines, all_lines_in_page):
        header_lines.insert(len(header_lines),all_lines_in_page[0])
        all_lines_in_page.remove(all_lines_in_page[0])

3. Convert the rest from Markdown to HTML

As mentioned earlier, thanks to the great python-markdown2 library, this is simply a case of calling the “markdown” method, passing in the content to process:

post_content = str(markdown2.markdown(post_content,extras=["code-friendly"]))

I actually do a test to see if the markdown library can be imported first, then if it fails I don’t even try to convert from markdown to HTML:

can_markdown = False
try: 
    import markdown2 # markdown
    can_markdown = True
except ImportError:
    can_markdown = False

4. Post to metaweblog api

Build up the request using the blog details, post details, and HTML content:

content = self.BuildPostContent(self.view, {"content": post_content, "title": title, "tags": tags, "status": status})

def BuildPostContent(self, view, page_data):        
    return {"description": page_data["content"], "post_content": page_data["content"], "title": page_data["title"], "mt_keywords": page_data["tags"], "post_status": page_data["status"]}

Then submit it to the api:

proxy = xmlrpclib.ServerProxy(mbURL)

if post_id == None:
    post_id = proxy.metaWeblog.newPost(blog_id, mbUsername, mbPassword, content)
else:
    proxy.metaWeblog.editPost(post_id, mbUsername, mbPassword, content)

Extra bits and making it all work

To execute a command from a plugin within SublimeText, firstly you need to import the sublimetext library at the top:

import sublime, sublime_plugin # sublime

then name your class “something<command>” and have it take the “sublime_plugin.TextCommand” parameter:

class PublishCommand(sublime_plugin.TextCommand):

Then to run it you need to hit ctrl+’ to bring up the command window and type:

view.run_command("<name of the class minus the 'Command' suffix>")

e.g. for my plugin:

view.run_command("publish")

You can try this out with loads of the plugins included with a SublimeText install

That’s about it

All of this is in a small github repo. I’d appreciate it if you want to fork the repo and help show me how python should actually be structured. And written.

Known Issues

Categories

These need to be requested, looped through and matched against those associated with a post, added if those specified don’t exist, and the IDs associated with the post. Couldn’t be arsed.

As such, when you post to your blog you’ll see the entry is “uncategorised” and you’ll have to manually edit this.

Images

Since I’m just fooling around with a text editor, uploading images is still a little out of scope.

Random reference material

  • pyblog – for helping to work out the guts of how python interacts with the metaweblog api
  • I used Fiddler & Windows Live Writer for investigating traffic and finding out what the actual parameter being used to specify “tags” is within the metaweblog api: mt_keywords