Restore the WordPress.com admin bar stats sparkline

The staff at WordPress.com are at it again, removing useful features for the sake of consistency with the “unified experience” vision. This time, it’s the stats sparkline in the admin bar that was introduced in 2011. It still lives on hidden in the sidebar that appears when you click “My Sites” in the admin bar, but its usefulness is greatly reduced because it’s hidden in the sidebar and not immediately visible in the admin bar.

This was unacceptable, of course, so I wrote a script to bring it back. Unfortunately, because of certain technical limitations, this script can only run on URLs that have wordpress.com in the domain part. If you want to add support for your custom domain, you will have to extend the script’s include directives. You can add one in the script’s options in your extension. If your extension doesn’t support adding custom includes, you can add it yourself by adding a custom @include line to the script, but you won’t be able to receive automatic updates.

The sparkline restored to the admin bar

The sparkline is restored

If you’ve already installed one of my previous scripts, you’ll know how easy it is to install this one. If installing user scripts is new to you, don’t worry; it’s very simple. If you don’t already have one, install a browser extension that allows you to run user scripts. Then, install the script from Greasy Fork.

If you have any questions or experience any issues, please leave a comment.

You don’t need to know how the script works to use it, but if you’d like to know the technical details, read on. The source code is available on GitHub.

Happy blogging!


When I noticed that the sparkline was still available, I knew I had a template to work from. If you open your browser’s developer tools and inspect the Stats item in the My Sites sidebar, you’ll see something like this:

<li class="mb-icon" id="wp-admin-bar-blog-stats">
  <a href="https://wordpress.com/stats/tpenguinltg.wordpress.com" class="ab-item">
    Stats
    <img title="Showing site views per hour for the last 48 hours. Click for full Site Stats." alt="Stats" src="https://tpenguinltg.wordpress.com/wp-includes/charts/admin-bar-hours-scale-2x.php?masterbar=1" style="width: 95px; margin: 0; float: right;" />
  </a>
</li>

We see from this that the sparkline is an image, and the URL for that image in this example is https://tpenguinltg.wordpress.com/wp-includes/charts/admin-bar-hours-scale-2x.php?masterbar=1. It appears to be the site’s URL, followed by /wp-includes/charts/admin-bar-hours-scale-2x.php?masterbar=1. I played around with that URL and I discovered that the presence of the masterbar parameter, no matter what its value is, causes the server to return an image that’s blue instead of greyscale (it follows that the sidebar is internally called the Master Bar); removing it causes the server to return the greyscale image from before, along with the peak indicator. The images below show the difference against their intended background colours:

Master Bar sparkline

With ?masterbar=1

Admin bar sparkline

Without ?masterbar=1

The -scale-2x part was also a hint that there’s a smaller version. The 2x version is 48px tall, which is 16px too tall for the admin bar. Half of 48px is 24px, which should fit. I played with the URL again and discovered that removing the -2x gives us the size that we want.

Now that we have an image, what do we do with it? We have to add it to the admin bar somehow. The first step to doing that is to find the selector for the admin bar. If you inspect the bar, you’ll find something like this (the less important parts are omitted):

<ul class="ab-top-menu" id="wp-admin-bar-root-default">
  <li class="menupop my-sites" id="wp-admin-bar-blog"><a href="https://wordpress.com/stats/tpenguinltg.wordpress.com" aria-haspopup="true" class="ab-item">My Sites</a></li>
  <li id="wp-admin-bar-jumptotop-button-menu"><a href="#" class="ab-item"><div id="jumptotop" style="top: 0px;"><span class="noticon noticon-top"></span></div></a></li>
  <li class="menupop" id="wp-admin-bar-newdash"><a href="https://wordpress.com/" aria-haspopup="true" class="ab-item">Reader</a></li>
</ul>

We’re interested in adding a list item to this menu. We can access the menu using the ID wp-admin-bar-root-default. Now, it’s just creating the image, the surrounding link, and then appending the link to the list. We can create the elements using Document.createElement.

The last thing we need to take care of is to only run the script when the user is a member of the site. The first way I thought of was to use the API, but I quickly dismissed that because I still haven’t figured out how to handle authenticated API calls. Luckily, the “Master Bar” can help us out. If you open it when you’re on your blog, you’ll see the blog’s name, blavatar and domain name near the top. If you open it on someone else’s blog, it’ll be your default blog instead. This means that if you’re a member of the current blog, the site in the Master Bar will be the same as the current site. In the inspector:

<li class="has-blavatar" id="wp-admin-bar-blog-info">
  <a href="https://tpenguinltg.wordpress.com/" class="ab-item">
    <div class="ab-site-icon">
      <img alt="Current site avatar" src="https://secure.gravatar.com/blavatar/58f58f9e0dc4ec1b4218e34b6cef34d8?s=120" class="avatar" />
    </div>
    <span class="ab-site-title">`The Penguin' says..…</span><span class="ab-site-description">tpenguinltg.wordpress.com</span>
  </a>
</li>

We have the convenience of having the link to the blog given to us, so all we have to do to know if the user is a member of the current site is to check if the current URL starts with the link given. If it isn’t, then we return early.

Bringing it all together gives this script:

// ==UserScript==
// @name        WordPress.com Stats Sparkline
// @namespace   tpenguinltg
// @description Adds a stats sparkline to the WordPress.com admin bar
// @include     https://*.wordpress.com/*
// @version     1.0.0
// @updateURL   https://github.com/tpenguinltg/wpcom-stats-sparkline/raw/master/wpcom-stats-sparkline.user.js
// @homepageURL https://greasyfork.org/en/scripts/26076-wordpress-com-stats-sparkline
// @homepageURL https://github.com/tpenguinltg/wpcom-stats-sparkline
// @grant       none
// @license     MPLv2.0; http://mozilla.org/MPL/2.0/
// @copyright   2016, tPenguinLTG (https://tpenguinltg.wordpress.com/)
// ==/UserScript==

window.onload = function() {
  var blogUrlAnchor = document.querySelector("#wp-admin-bar-blog-info a.ab-item");
  if (!blogUrlAnchor) return;

  var blogUrl = blogUrlAnchor.href;

  // only act on sites where the user is a member
  if (!document.URL.startsWith(blogUrl)) return;

  var sparklineImage = document.createElement("img");
  sparklineImage.src = blogUrl + "/wp-includes/charts/admin-bar-hours-scale.php";
  sparklineImage.alt = "Stats";
  sparklineImage.title = "Showing site views per hour for the last 48 hours. Click for full Site Stats.";
  sparklineImage.style.paddingTop = "4px";
  sparklineImage.style.paddingBottom = "4px";

  var statsLink = document.createElement("a");
  statsLink.appendChild(sparklineImage);
  statsLink.href = "https://wordpress.com/stats/" + window.location.hostname;
  statsLink.className = "ab-item";

  var menuItem = document.createElement("li");
  menuItem.appendChild(statsLink);

  document.getElementById("wp-admin-bar-root-default").appendChild(menuItem);
}

The code is assigned to the “onload” event to wait for the page to completely load so that the elements we check for actually exist.

That’s all there is to it: create the elements, then append it to the admin bar. If you have any questions, feel free to ask in the comments, and if you’d like to view the source code or contribute, it’s up on GitHub.

Advertisements
36 comments
  1. I never clicked the sparkline because it didn’t take me to the page I wanted, but I always looked at it and have been known to zoom in on it to see exactly what hour got the most views. Beats me why WP would move it. There’s a whole big almost empty admin bar up there. Why remove the sparkline? Even on my cellphone there’s still room for it.

    Er, wait, I just clicked back on my blog (on laptop) and the sparkline is showing on the admin bar. I’m confused (nothing unusual about that, actually) …

    • You must have installed the script!

      According to a forum post by KokkieH, they removed it because for consistency with the Calypso (the new blue interface) admin bar.

      I linked the sparkline to the new stats page because that’s what it used to link to and because I don’t want to foce anyone to use the classic stats page. You can always use my stats redirect script if you want it to go there instead.

  2. Slightly off topic:
    A long time ago, maybe about 2014, WP had this feature where you could click on a “Random Post” icon on a given bloggers blog. Upper left corner I remember. I thought it was a useful way to get a feel for a blog and figure out if one should follow it.

    Do you remember it? What ever happened to it?

    • I do remember it, and if you look at this site’s menu, you’ll see a “Random Post” link. I guess they removed the link, but the functionality still works. Add ?random to the end of the URL and you’ll get a random post on that blog. It shouldn’t be too difficult to make it into a bookmarklet if you want it.

      • It was a good icon to have. Most people must have not used it.

  3. Dennis said:

    Funny, I knew this would be the next thing they kill. They totally gone nuts now in my opinion. You’re fast, thank you so much again for this script.

    I added “// @include https://diaryofdennis.com/*” and it seems to work. But if I visit “https://diaryofdennis.wordpress.com/wp-admin/” the “https://*.wordpress.com/*” in the script seems not to work and I don’t see the sparkline in the dashboard.

    • I had a hunch this case wasn’t going to work. I’m guessing it’s because https://diaryofdennis.wordpress.com/wp-admin/ doesn’t start with https://diaryofdennis.com/. It seems I can make a query to the API with the current page’s domain, get the URL from the reply and compare it to the URL in the Master Bar. If it matches, then the user is a member. I’ll work on a fix sometime in the next few days.

    • I have a fix but I don’t own a custom domain so I can’t test it. Do you mind testing for me? I’ve released v1.1.0-beta, but you’ll have to install it manually:
      https://github.com/tpenguinltg/wpcom-stats-sparkline/raw/v1.1.0-beta/wpcom-stats-sparkline.user.js

      Also, I realized that you don’t need to edit the script to add a custom include. You should be able to do it through the script’s options, and I think you’ll keep getting updates if you do it through there.

      Thanks!

      • Dennis said:

        I can’t get this to work, but I wouldn’t say that it has something to do with your version 1.1 because it stopped to work before I installed your fix. The previous installed script where I added the include line did stop to work just yesterday. Could it be that they changed something? I still see the “stats” link with the tooltip of “Showing site views per hour for the last 48 hours…”. But the graph is missing now. Did that happen in your case too or could this be related to my domain url?

        Ah, cool, thanks. I found the option where I can add URL’s to the script.

      • Dennis said:

        Wait, that’s strange, out of the sudden now it’s working again and the graph shows.

      • Hmm… well, from your description, it sounded like the image couldn’t be found. Might have been a one-off thing and you accidentally stopped it from loading somehow. Keep it around for another day or two, and if you don’t see anything unusual, I think it’s good enough to release. Thanks!

      • Dennis said:

        Yes, I will monitor this tomorrow. I added my domain url with the asterisk and the one with the wordpress ending and asterisk, and I wonder if that was needed or if the script does parse these information’s now on it’s own? If you answer, I take a look after the sleep, I am tired now. :)

      • The extension should merge the two, with your rules taking precedence if there are any conflicts, so no, adding the wordpress.com include yourself shouldn’t be needed. I hope you rested well!

      • Dennis said:

        I just logged out of my site, and logged back in and the graph is again not loading. I am going to try this later again after the sleep to see if I find out more.

      • Could you please give me the URL for the sparkline in the Master Bar? Open the Master Bar, right-click on the sparkline, then “Copy image location”. Let me know also if it’s different when you’re on your custom domain and when you’re on wordpress.com.

      • Dennis said:

        When I arrive in the dashboard after logging in and when the graph is not showing; I see “http://diaryofdennis.com/wp-includes/charts/admin-bar-hours-scale.php” as a source of the graph. To make the graph load everywhere I have to visit “https://diaryofdennis.com/” once, and after inspecting the element there I see it takes the graph from “https://diaryofdennis.com/wp-includes/charts/admin-bar-hours-scale.php”. It seems the only difference is http and https.

        I am going to send you a message in your private contact form because I got an idea for testing purposes…

      • Hmm, interesting. It might have to do with secure cookies not being sent over the insecure HTTP. Your proposal will certainly help me debug this.

        Also, by “Master Bar”, I meant the sidebar. I guess I can’t use the internal names for things just yet.

      • I just realized, the script doesn’t have an include for the http URL. I didn’t add one because I was under the impression that WordPress automatically redirects you to the https version. Is that not the case for you?

      • Dennis said:

        Outside of the backend as inside, in all cases I see “https” in the Firefox address bar. So, I think it redirect always to the https version. But why do they load the graph from “http://…” if I am in the dashboard? Outside it’s loaded from “”https://…” as said.

      • Got it! Since you logged out, you don’t have a cookie set for your domain, which means requests to your domain act as if you’re still logged out. I have a couple of ways to solve this. I’ll have a fix out once I figure out which way is the best, which is probably taking the current URL and modifying it.

        Also, I double-checked the https redirect by doing a HEAD request with cURL and I get a 301 redirect to the https version, so it does indeed redirect everywhere. As for why it’s http, it seems the URL in the sidebar and the API return http.

      • Dennis said:

        Adding http url via script options doesn’t change the behaviour.

      • Dennis said:

        Ah I see you got it already :)

      • Dennis said:

        This seems to work right away now everywhere in the backend. It just doesn’t work outside of it, on my blog, or on your blog. But I am not sure if this is still an issue. It works perfectly fine within the dashboard url’s.

      • Dennis said:

        Ok, if I add my domain manually in the script option, it starts to work outside of the dashboard too.

      • Sounds like it’s working as intended. You shouldn’t have access to stats for sites where you’re not a member, and you have to add custom domains manually in the options.

        I’ll make an official release shortly. Thanks again!

      • Dennis said:

        What I meant was… the original WP 48h graph showed my own 48h stats on other blogs too if I remember right. If I am logged in, I do also see “My Sites”, “Reader”, “Write” and so on in the top bar, even if I visit your blog at this moment. Logged in, even if I visit your blog right now, I could start to craft a post on my blog due to the top bar. That’s also how the 48h graph worked.
        As same as it worked on my own site, in the front end.

        But anyway, since it is working perfectly now in the dashboard, and also outside on my blog (if I add my domain to the script option), it should be all right. It’s not a big deal that it’s not shown anymore on other blogs. I am just glad that you brought this feature back :)

        I hope WP doesn’t destroy something again, I am afraid they could take out the classic-classic stats page next time, I hope they won’t.

      • Oh, is that the way it was? It’s been a while since I’ve really been on WordPress (as evident by my lack of posts). It would certainly make things simpler to implement as I wouldn’t have to do all the preliminary checking; just scrape and display. My reasoning for not including it on other blogs was that you couldn’t see the stats of that blog and having the stats of your default blog seemed a bit odd.

        What do you think, should I do it that way instead?

      • Dennis said:

        Yes, you can test this if you are logged into your own site, and then do for example open up my site. You should still see this bar on top with all the links to your personal site dashboard, reader and so on. If logged into your wp account, this main bar seems to be global across all wp.com hosted sites.

        I just tested what WordPress did with the top bar. Here is what I found out… I logged into another test blog that I created, a blog without domain that I basically use as a sandbox to test posts and things. Now switched to this blog, I visited your blog and clicked on “Write” in the top bar… and it seems this redirects me to the editor of my default blog, not the editor of the blog I switched to. That makes me think it was the same with the 48h graph, they just showed the graph of the default blog.

        But to be honest, I see it the same, I don’t really care too much about the graph shown on other blogs. I think it is totally fine now that it is shown in the dashboard automatically, and automatically shown on the own URL if it has the “.wordpress.com/” ending. I think one improvement would be if it would work for purchased domains too without adding it manually, but I guess there is no way to do that? If so, adding it manually in the options is no drama, don’t worry :)

        I think the script is fine now.

      • Ah, you’re right. It probably was that way before, but unless there’s demand for it, I agree that the script is fine for now.

        The only way I can think of for the script to run on custom domains without adding it manually is to have it run for all sites, even sites that aren’t hosted on wordpress.com. You can see how that’s not desirable.

      • Dennis said:

        Yep, very good point. Well, if someone went so far to install Grease- or Tampermonkey, and your script, he/she will probably also not have issues to add a domain manually ;)

        I am going to suggest this script too with a small guide on my blog in the new year and point them to your blog. Thanks for doing all this!

        Also in advance, I wish you a happy new year, stay healthy, enjoy the time with your family and friends… I hope 2017 will be a happy year for you.

      • You’re very welcome, and thank you. I’m sure you’ll be able to explain the process better than I can to your readers.

        All the same new year wishes to you, too. Here’s to a great 2017!

  4. You sir are a star. Fixed this issues in one hit. Bloody minded WordPress. Takes a functional, and easy to use application and then obfuscates the hell out of it. May you be bathed in wine, and live for many years.

`$name' says...

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: