Marketing: A Clever Example Of Counterprogramming – How To Own The Internet News Cycle

Yesterday, November 18 2020, was Mickey Mouse’s 92nd birthday. You may have seen it on your local news; I saw it mentioned on my local ABC station (ABC is owned by Disney).

Here’s a screenshot of a news-anchor from my local ABC affiliate commenting on Mickey’s birthday:

Extracted from

Unfortunately for Disney, Mickey’s 92nd birthday was not a major topic of conversation on Twitter and other social media locations. You may have seen another story about Disney bubble up yesterday, and this story is much less flattering to Disney: SFWA – #DisneyMustPay Alan Dean Foster. In short, Disney is accused of not paying royalties to Alan Dean Foster, who wrote a number of Star Wars and Aliens novels that Disney acquired the rights to when it purchased LucasFilm and Fox.

This story (and the hashtag #disneymustpay) was a trending item on Twitter for most of yesterday; this tweet summarizes the situation very well:

Extracted from

I’m not here to litigate which side is correct, but I did want to point out the beauty of how this story was marketed: it was set up as counterprogramming against the story of Mickey Mouse’s 92nd birthday.

Yesterday’s news started with Mickey Mouse’s 92nd birthday on the news cycle: that “primed the pump” for more Disney related stories. By publishing the article #DisneyMustPay Alan Dean Foster on the same day, the article received much bigger growth and coverage than it would have if published on any other day. It inflicted reputational damage on Disney (which hurts more because Disney is a consumer-focused company) and cost Disney the chance to use Mickey’s 92nd birthday to drive more sales (because on November 18th consumers were thinking of Alan’s story, not Mickey Mouse). All in all, the SFWA managed to get Disney’s attention in a big way, and I’m sure Alan’s story is now being considered in the executive level of Disney’s management.

This case is a great example for any guerilla marketing campaigns: set up your marketing as counterprogramming to a bigger rival’s work; you’ll get far more reach out of your campaigns and your rival’s marketing will be much less successful.

Redirecting From Tumblr To WordPress

I’ve been setting up redirects from my old Tumblr blog to WordPress; here is documentation how I handled it.

Netlify offers static web page hosting, and more importantly, supports redirects and rewrites. It can deploy a static web site from a git repository, or by uploading a folder from your local computer. What I did was set up a git repo with a file named “_redirects” (no quotation marks) and connected it with a Netlify deployment; instructions to do this are available here: .

The redirects file should look like this:

/                                                  301
/tagged/*                                          301
/post/49459687975/*                                301

This works by:

  1. Mapping the root to forward to
  2. Remaps Tumblr tags, which would look like “/tagged/exampletag” to “” – the :splat is replaced with any text after /tagged/
  3. Remaps a test post to the real location.

Obviously, all of these redirects are 301 Moved Permanently links. You’ll also need to remap your old domain to point to the Netlify deployment target: .

Transitioning To WordPress

Hi all,

I’m transitioning this site from Tumblr to WordPress. I dropped a bunch of posts after 2014 which covered a wide array of App Engine topics – I want to redo those with updated information in 2019, as much has changed with the Google Cloud Platform.

If you have any questions, feel free to contact me using the About page (link above).


Extract And Process XML Using Apps Script

Here’s a short code snippet demonstrating how to retrieve and parse a XML file using Apps Script. First, here’s how to download and parse the file:

var url = "URL to XML";
var xml = UrlFetchApp.fetch(url).getContentText();
var xml_document = XmlService.parse(xml);
var xml_root = xml_document.getRootElement();

Once the file is downloaded, you can retrieve child elements by calling getChild/getChildren. GetChild returns the first instance of the named element, and getChildren returns an array listing every element instance:

var xml_items = xml_root.getChild("channel").getChildren("item");

And finally, here’s how to retrieve the text content of an element:

var title = new String(xml_item.getChild("title").getContent(0));

Downloading The Contents Of A MediaWiki Install

Here’s an useful wget command: it downloads a static copy of a MediaWiki installation while skipping unimportant pages, such as the talk sections. Downloading large sites can take a long time, so the nohupinstruction lets this command continue even when the user exits from the shell.

nohup wget --recursive --page-requisites --html-extension \
    --convert-links --no-parent -R "*Special*" -R "*action=*" \
    -R "*printable=*" -R "*title=Talk:*" \

You can use this command to archive old wiki installs, or keep a local copy for quick reference.

Using Javascript To Forward A User (And Keeping Track Of The Forward)

URL hashes (the part after the # sign) are useful for keeping track of application state. Here’s a short example of how they can be used.

The below code fragment forwards the user to a Google search for the value held in the variable q . The useful part is that this code also sets a hash to mark that the forward has taken place. This allows the page to keep track of the forwarding status, and to prevent reissuing the forward – for instance, if the user presses the back button after being forwarded.

if (location.hash != "#forwarder") {
    location.hash = "forwarder";
    var search_url = "" + escape(q);
    //Set the timeout to 10 seconds.

To see how this works, consider the below example. The first alert will show that there’s no hash recorded in the URL (the alert will be blank). The second line sets a hash of forwarder and the third line shows the value of the current hash (which will be the value we set on the second line). This will cause the if statement to evaluate to false, preventing the forwarding from taking place. The same process (recognizing the hash and blocking the forward) happens when the user clicks the back button on the above forwarding code.

location.hash = "forwarder";
if (location.hash != "#forwarder") {
    location.hash = "forwarder";
    var search_url = "" + escape(q);
    //Set the timeout to 10 seconds.