Portfolio

Below are some of the products I have engineered over the years. All code samples below are entirely my own work, and you may use them without attribution. As of this writing, all code is live on at least one (and probably several) of the sites I manage, so no excuses.

I mostly code in Python these days, but I cut my teeth on Perl and am fairly adept at PHP, Javascript, and SQL.

My larger projects are almost entirely in private repositories, but you can find some of my public work at gitlab and github

Passion Projects

In my spare time, I gravitate towards projects that help people connect with great content. Here are a few of the ones I’m most excited about:

Weekend Planner

What are we doing this weekend? WERA 96.7 FM in Arlington, VA recently devoted an entire show to my effort to aggregate all events in DC, along with the unique challenge of finding interesting things to do during a pandemic. I started TownCalendar.org in 2018 as a machine learning project that scraped events from area websites. I wrote a Python algorithm that categorized future events and guessed their relevance based on past ratings.

With fewer safe events to write about since the start of the pandemic, this site has evolved into more of a nature writing project as my children and I have sought out natural spaces hidden in our city. Among those places are the Virginia access points to the Potomac River, which we found by following trails off the suburban culs-de-sac of Arlington and backroads of Fairfax County.

Free Books

Why pay for books when you can get them for free? I love great stories and am always looking for ways to discover new books that match my interests. I wanted a way to discover and acquire my next read in seconds. By combining the Wikipedia ontology with Project Gutenberg, I’ve found interesting connections between books I love and those I’ve yet to discover. But Gutenberg books are a hassle to get on a kindle, so incorporated authentication and profiling that allows the site to send the book to a personal kindle in one click. So instead of paying Amazon $3 for the book Flatland, you can get it for free here.

Bonus Feature: you can track your reading progress on a bucket list of the Best. Books. Ever. I’ve read 210 of the top 1000 books. How many have you read?

Personalized Radio

What if talk radio adapted to your interests? I started toying with this problem in 2008 when, as a personal side project at work, I coded the Mix Your Own Podcast app. I quickly learned that this was too big a project to tackle on my own, so I partnered with three colleagues to build the Infinite Player, a web-app that used a machine-learning algorithm that adapted programming based on a listener’s behavior. Before long, my team realized this project was way bigger than the four of us. By shopping this concept to our network, and with the generous support of the Gates Foundation and the Knight Foundation, we were able to turn our little hustle into NPR One. Ten years later, it’s still the best way to listen to talk radio.

WordPress Snippets

I now put 100% of my custom wordpress code in a plugin called snippets, which is a wonderful way to modularize, control and cross-deploy. Because this approach does not lend itself well to version control, development is best done on local. Use a simple IDE like Sublime to edit directly in your theme’s functions.php file. Comment out the code before pushing to git and then transfer over the complete, dependency-free code to snippets when complete. Snippets does have its own IDE (which I would only use in a staging environment). Since Snippets deals with errors by automatically reverting to your last working code, debugging is most efficient by viewing errors at /wp-content/debug.log which is activated by adding these lines to your wp-config.php file:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );

Audio player

Adding scalable audio to wordpress is easy the above snippet. Simply install the ACF plugin and create a custom field for your posts called audio. From then on, you’ll simply paste the audio link into that field for the post:

…and the code will add it to your template:

My snippet also includes a shortcode that allows you to drop multiple miniplayers on your site like so:

Tracking is a little more complex, but I found this guide helpful for setting up basic tracking in GA that looks like this:

Setting up the tracking for audio plays is fairly easy in GTM.

Banner placement

Injecting a giant banner like you see at The New York Review of Books works for any wordpress template. Simply add this snippet to your site and replace the commented out section with your own adsense code:

add_action( 'wp_body_open', 'banner_ad' );

function banner_ad() {
  $ad = '';
  $ad = <<<ADHTML
    <style>
      #banner_container {
      background-color: #080f5d;
     }
      #banner_ad {
      text-align: center; 
      }
    </style>
		
<div id="banner_container">
  <!-- insert adsense code here w/id on ins like: <ins id="banner_ad" ... -->
  
</div>
ADHTML;
  echo $ad;
}

A/B Testing

After spending literally decades of my life setting up elaborate multivariate tests, I can’t get over how easy Google Optimize is to deploy. Once you’ve set up your account, simply add this snippet to your wordpress site (replacing YourCode with your own OPT code.

add_action( 'wp_head', 'load_scripts' );

function load_scripts() { ?>

<script async src="https://www.googleoptimize.com/optimize.js?id=OPT-YourCode"></script>

<?php}

The experiment set-up wizard in Google Optimize is fairly self-explanatory, and the only coding you’ll need there is the CSS or JS change you’ll make on your variants. If you wanted to test the impact of a banner ad on, say, bounce rate, you would simply add a variant with CSS that hides the banner, like so:

#storypage_banner_ad {
  display: none;
}

Custom Embeds

Did you know that wordpress comes with embeddable versions of your posts out of the box? Just add /embed to any blog post url and you’ll see something like this:

Note that the above also includes some custom assets, which can be added with a simple snippet:

function embedCallback() {?>

  <!-- inject your custom HTML here -->

<?php}

add_action( 'embed_content', 'embedCallback' );

Related Posts

Go to any one of the blog posts on this site (maybe try this one). See those three stories in the sidebar at the top of this page? Those are all taxonomically similar stories, and they’re created dynamically using the above code and by placing this shortcode in the sidebar:

[posts n=3] 

Graceful failover: If the script can’t find other stories that share the same taxonomy, it’ll fail over to other stories in the same category and, finally, the 3 most recent stories.

And while we’re on the subject of ads, isn’t it annoying that Google AdSense only allows sticky ads (anchor ads) with auto ads? You can get around it by adding this little snippet:

<div id="sc">
  <div id="sticky-ad"><!-- insert your adsense code here --></div>
  <div id="sticky-spacer"></div>
</div>
<script>
document.getElementById("sticky-spacer").style.height = +document.body.scrollHeight-3000+"px";
</script>

Microservices

PHP is hideous. Do yourself a favor and keep all your more ambitious, CMS independent integrations in a microservice, which is just a collection of endpoints. Once complete, you can embed them in wordpress or whatever CMS you use. I eschew complex IDEs and instead use Jupyter Notebooks (part of the Anaconda package), which makes it super easy to fiddle with each code segment before exporting as a dot py. Although python works out of the box on most hosting platforms, deploying python powered endpoints in a virtual environment is complex, and best handled with a framework like Flask. You can learn this on your own (I’ll see you in a year) or just use my flask starter package, which is now open-source.

Flask Starter Kit

Streamlining News Development: Over the past decade, I’ve launched a number of news projects that required a combination of an API, a CMS, and various python libraries. Base is my attempt to combine my lengthy trial and error with the foundational software we used at NPR to create a single repository that can be deployed in minutes, edited entirely in markdown, and with access limited to authenticated users.

Base is also a headless CRM, allowing simple storage and retrieval of data for any authenticated user. Adding data is as simple as creating an HTML form element with the userFormElement class and a unique id that defines the key (no javascript needed). Retrieve data outside a form element with a single command: window.userData[key]

This repo powers the book tracking and other profile data at Sourcewolf, but you can see a live example of what you get out of the box in the Sourcewolf Lab.

Progressive Profiling

The authentication I use at sourcewolf.com to help people keep track of their book readings is just a couple of wordpress snippets that then use a python microservice for authentication and storage of private user data. This authentication service comes out of the box with Base, but you’ll need to write your own code to read and update user profiles. The best method for that is to use promises (modern ajax)

Build your own Smart Radio

When I was at NPR, we came across this really cool project from a guy named Todd Treece, where he basically reverse-engineered our app requests to build his own NPR One radio. We tracked him down and chatted for hours about how he did it, his passion for NPR, and his love of DIY tech. After a few more dork sesh’s, he helped us put together an open-source strategy for attracting more developers like him to the platform. I cannot overstate the impact that Todd had on the public radio universe. He encouraged me to write a python package which allows developers to build the radio software in about 2 minutes, and he also helped us envision dev.npr.org, which now powers NPR integrations from major partners like Amazon and Samsung. No flying cars yet, but this code is probably in your car somewhere.