Let’s Build a Chrome Extension to View Story-Level Daily Medium Statistics
By: Bowei Han
Tags: Programming, Software Development, Productivity, Technology, Software Engineering

Let’s Build.

1. Setup Your Project Directory

Create your project directory with the following files. Feel free to pull the logo assets from here or create your own.

Files and Directories (source: Author)

manifest.json is a configuration file required for Chrome extensions.

is a configuration file required for Chrome extensions. background.js contains JavaScript we can execute in the background.

contains JavaScript we can execute in the background. popup is our popup HTML component (functionality, styling, and assets).

is our popup HTML component (functionality, styling, and assets). images are the image assets that represent the extension in the Chrome Web Store and browser toolbar.

2. Fill Out the Manifest

The manifest of a Chrome extension is responsible for defining project metadata, permissions, script execution, and browser executions. We’ll use it as the scaffolding for our project.

Here’s what the manifest should look like:

manifest.json

name and description are public-facing strings; feel free to change them.

and are public-facing strings; feel free to change them. version must be one to four dot-separated integers that represent the version of your application. Start small!

must be one to four dot-separated integers that represent the version of your application. Start small! manifest_version must be set to 2 . Version 1 was used for legacy extensions / hosted apps and was deprecated a few years back.

must be set to . Version was used for legacy extensions / hosted apps and was deprecated a few years back. background specifies the location of our background script. Set persistence to false so that the background script doesn’t remain permanently active and hog resources.

specifies the location of our background script. Set to so that the background script doesn’t remain permanently active and hog resources. permissions contains a list of features and host domains that our extension needs to access. We need permissions to make requests to https://medium.com .

contains a list of features and host domains that our extension needs to access. We need permissions to make requests to . browser_action tells the extension to trigger a default_popup .

3. Code the Background Script

There are a few things we need to accomplish behind the scenes.

Fetch statistics from Medium.com.

Transform the data to make it easier to render in a popup.

Set up an event listener to pass data up to the popup.

Let’s start by writing a helper method that we’ll use to make browser requests.

Base request helper for Medium.com API calls

Our helper leverages the Fetch API. There’s one particularly interesting piece of code here: text.slice(16) . This is needed because the JSON response from Medium looks like this:

{"success":true,"payload":{}}

The length of ])}while(1);</x> happens to be exactly 16 characters long and, if you read closely, it’s actually an infinite loop! That snippet exists to prevent JSON hijacking. I don’t want to spend too much time here; feel free to dive into the rabbit hole.

Moving on, let’s write our API calls.

Helpers to make Medium requests

Feel free to change limit=100 to whatever you’d like. I’m not sure how prolific you are as a blogger but pulling data for 100 stories is enough for me!

The data that gets returned from these methods follows a certain structure.

API response data structures

getStats returns all the identifiers and titles for your posts.

getStatsForPost returns a list of metrics for a single post, each containing the number of claps, reads, upvotes, and views collected in a certain timeframe.

We’ll use the identifiers from getStats to call getStatsForPost and aggregate statistics for (approximately) a 24-hour interval.

Our end goal is to have our popup display a list of top-performing posts, sorted by daily views. To do this, we’re going to need a data structure more amenable to lists.

Data structure for our popup

Let’s write out the base method for generating stats in the shape that we want.

Base method for generating stats

This method will execute helpers to [1] normalize post statistics, [2] sort by daily views, and [3] add some extra information to help us make the UI prettier.

normalizePostStats fetches post-level statistics and transforms the data.

normalizePostStats implementation

sortPostsByViews ranks our stories by popularity.

sortPostsByViews implementation

appendAdditionalStats adds an extra field to represent total daily views for all of our articles.

appendAdditionalStats implementation

Good stuff! We have our data in a form that we can use on the client-side.

For the last step, set up an event listener so that our background script can pass data to our popup.

Chrome event listener to facilitate cross-app communication

We’re done with the background script! Feel free to check your work against the source code.

4. Visualize the Data

It’s time to code our popup, head over to popup.html and paste this in.

Popup HTML markup

This HTML contains a header, body, and footer for our popup. It imports popup.js to handle our dynamic list generation and brings in styles via popup.css .

For popup.css , copy this stylesheet. If you’re feeling adventurous, create your own look and feel!

Dynamically generating our list of statistics should be straightforward now that we’ve massaged our data. Let’s kick-off our implementation of popup.js by fetching data from our background script.

Fetch data from the background script

Now we can write the render method using plain ole JavaScript DOM manipulation.

DOM manipulation with VanillaJS

DocumentFragment is used for performance to ensure that all nodes are inserted into the document at once, avoiding any unnecessary reflows and renders.

Now that we have our popup component and background script, we’re done coding!

5. Try It Out

Open up Chrome and navigate to chrome://extensions . You should see a radio button labeled “Developer mode” in the top right of the page. Turn developer mode ON to access extra functionality.

Chrome extension developer mode

Click “Load unpacked” and select the root folder of your project (the directory containing manifest.json ).

Upload your Chrome extension

It’s alive!

An icon for your new Chrome extension should have made its way onto your toolbar. Cross your fingers and click it.

It works! (for me, at least)

Voila!

If you run into problems at this step, check your work against the source code.