486 Unique Landing Pages in 21 Days

My senior year of high school, I made extensive use of my Google Docs knowledge of the command-option-M hotkey — spending hours sitting at Coupa Cafe editing articles for the school newspaper. Now, after programmatically creating hundreds of landing pages using Google Apps Script, I can comfortably say I know a bit more than how to add a comment on a doc.

I joined Breakout Mentors in early 2017 as a Java mentor for a 10 year-old Nueva student. Soon after starting Brian, the founder of Breakout Mentors, asked me about the prospect of a summer internship. I would have two main focuses: leading in-home coding camps and programmatically creating custom landing pages. The first, while very fun for me as a coding mentor and previous camp counselor, is a story for another day. The second, is the subject of this article.

I hope to provide a case study for any business looking to target landing pages for a highly personalized service.

The Unique Challenge

Breakout Mentors provides long-term one-on-one mentorship for kids ages 8 to 15 learning to code. It is highly personalized to challenge each student at the right difficulty and allow them to be creative. This proves challenging from a marketing perspective to represent all the unique services we provide (any coding language, age, Bay Area city).

The issue was quite apparent in some test searches before this summer. Search terms that closely match what we offer (ex. “kids java coding tutors” or “Berkeley kids coding”) were poorly ranked and led to a generic page.

The challenge was to create unique pages that more accurately describe Breakout Mentors many personalized services.

Selecting the Strategy

For a little inspiration, we looked to Casey Winters and the pioneering success of his marketing for Grubhub.

Grubhub’s food delivery service offered the perfect opportunity to aggregate restaurant data for cuisines in thousands of cities. At the start of the business, Grubhub had a basic homepage with a basic search tool. As a result, my search for “Palo Alto Chinese food delivery” and “San Francisco burgers” would be sent to a generic page. Grubhub was able to programmatically create a seemingly infinite set of landing pages for almost any unique food and location search. Now I am sent to a highly focused page for Palo Alto Chinese and San Francisco hamburgers.

Let’s apply the Grubhub landing page model to Breakout Mentors. If I had searched for “10 year old python coding camps” before this project was implemented, (after a lot of digging through search results) I would have been directed to our homepage.

Taking Winters’ idea, we would instead create a unique page with relevant information about 10 year old students, the Python programming language, and the camp format.

Determining the Variables of Personalized Service

To get started, think about all the variables of your customizable business.

We started by creating a spreadsheet with columns for who, description, and format. Then, we tried various combinations with some basic Google Scripts, deleted a lot of base keywords (we started out with more than 10,000), added a few more, and eventually had a comprehensive list of 486 search terms.

Selections of our finalized base keywords and complete search term combinations.

To be clear: these keywords were not being used as simple text inserts with the intent to “trick” Google into ranking us higher. Instead they allowed for the automated selection of wide-ranging content that would result in the most relevant page for a potential customer. However the result is the same — drastic improvement to search rankings!

Creating the Content

Once we saw all the combinations of keywords, we had a better idea of the type of content and data that would be directly applicable:

  • Paragraphs and GIFs to outline the typical project sequence a student takes for a given language
  • Demographics of kids we tutor (age, gender, language, and city)
  • Testimonials and videos that match the age, language, and location
  • Relevant maps for location pages
  • Text explaining how girls learning to code can thrive with Breakout Mentors

We started by gathering data from our Customer Management System Close.io. We created a Google Script to make API calls and populate a spreadsheet with the data we needed.

After this came the time consuming but ever-so-important task of writing the text for each possible component on the page. We had 11 unique paragraphs, with each page including the 2 or 3 that were relevant. Throughout we made sure to leave places for relevant phrase inserts on age, gender, or city data to make the pages as unique as possible for each search term.

The other two main sources of content, testimonials and videos, were categorized by relevant keywords so that our script could determine the most closely related media to include.

This video was categorized as Python, 12 Year-Old, 13 Year-Old, 7th grader, Middle school.

Exporting the HTML

Once we had the individual pieces, we simply had to combine them for the complete HTML of the page. For each page we populated a spreadsheet with the title, HTML content, and meta description (which was also uniquely auto-generated). This code really isn’t too hard to grind out, though Google Scripts is a little fussy with a 5 minute maximum run time. We had to make use of Google timed triggers to truly automate the landing page creation:

function runProcessDialog(){
var value = Browser.msgBox(‘Run process?’, ‘Would you like to update data?’, Browser.Buttons.YES_NO);
if (value == “yes”){
function startTrigger() {
if (ScriptApp.getProjectTriggers()[0] == “FUNC_NAME”)

var trig = ScriptApp.newTrigger(“FUNC_NAME”);

We had certain cells in our Spreadsheet designated to track the index of the data we were processing. During runtime, the index was pulled from that cell, updated continuously, and then reset once finished.

After we had the completed spreadsheet we were able to very easily generate JSON files for every page with the following snippet:

var jsonResult = ‘{“title”: “‘ + TITLE +’”, “page_data”: “‘+HTML+’”, “meta_desc”: “‘+META+ ‘“}’;
var blobJson = Utilities.newBlob(jsonResult).getDataAsString();
DIRECTORY.createFile(TITLE + “.json”, blobJson);

Going Live on the Wordpress Website

Wordpress powers 28.7% of the internet and the Breakout Mentors website is one of them. Rather than serving static HTML files, Wordpress is a Content Management System that pulls information from a database to dynamically create each page. That complicated the project a little bit as we had to get our content into the Wordpress database.

We looked around and found a couple excellent examples of similar projects. A little code from Programmatically Creating Wordpress Posts from CSV Data, a little from Programmatically Add Page from a WordPress Plugin, a few tweaks of our own, and in no time we had created a Wordpress plugin.

The plugin looks in a specific folder for the 486 JSON files (which we FTP’d to the server) and adds them to the Wordpress database. Would you want to test out a never before used plugin on your live website? Heck no!

Luckily WP Engine makes it extremely easy to make otherwise scary changes to a live Wordpress website. There is a button to copy the live website to a staging install. Make your changes and test everything out on staging, then there is a button to make staging the live website. We were glad we used this feature considering some messed up code one time broke our staging install.

Once everything was finalized, it was just the push of a button to create hundreds of unique pages!

The Results

Breakout Mentors now has 486 pages for each aspect of our personalized service. And Google better understands what we offer, boosting our search position for a significant number of relevant terms. Look at the before and after for several key searches:

Nine search terms to represent a sampling of our various types of pages.

I learned a lot about Google Apps Script through this project and believe it is an important tool for any marketer. Breakout Mentors is now able to effectively communicate our unique service to potential customers. Isn’t that what marketing is all about?

Wordpress Plugin Code

Plugin Name: Breakout Mentors JSON Page Importer
Description: A custom Breakout Mentors plugin to import JSON files into pages
Version: 1.0
Author: Brian Skinner
License: GPL2
* Create and insert page from JSON files
function import_json_data() {
// Get the data from all those JSON files!
$posts = function() {
$data = array();
$errors = array();
// Get array of JSON files (/json_data should be inside uploads folder)
$files = glob( wp_upload_dir()[“basedir”] . “/json_data/*.json” );
foreach ( $files as $file ) {
// Attempt to change permissions if not readable
if ( ! is_readable( $file ) ) {
chmod( $file, 0744 );
if ( is_readable( $file ) ) {
$post = array();
$string = file_get_contents( $file );
$json_a = json_decode(prepareJSON($string), true);
$post[“title”] = $json_a[“title”];
$post[“page_data”] = $json_a[“page_data”];
$post[“meta_desc”] = $json_a[“meta_desc”];
$data[] = $post;
} else {
$errors[] = “File ‘$file’ could not be opened. Check the file’s permissions to make sure it’s readable by your server.”;
if ( ! empty( $errors ) ) {
error_log( print_r($errors, true) );
return $data;
foreach ( $posts() as $post ) {
$page_check = get_page_by_title($post[“title”]);

//Update the post in the database
wp_update_post( array (
“ID” => $page_check->ID,
“post_title” => $post[“title”],
“post_content” => $post[“page_data”],
“post_type” => “page”,
“post_status” => “publish”
//update the meta description
update_post_meta($page_check->ID, “_yoast_wpseo_metadesc”, $post[“meta_desc”]);
} else {
// Insert the post into the database
$post[“id”] = wp_insert_post( array(
“post_title” => $post[“title”],
“post_content” => $post[“page_data”],
“post_type” => “page”,
“post_status” => “publish”

//set the meta description
add_post_meta($post[“id”], “_yoast_wpseo_metadesc”, $post[“meta_desc”]);
register_activation_hook(__FILE__, ‘import_json_data’);

This story is published in The Startup, Medium’s leading publication for entrepreneurs and startups.

Join +12,417 people who get the top stories here.