Tag: Google

Extending Google Analytics on CSS-Tricks with Custom Dimensions

The idea for this article sparked when Chris wrote this in Thank You (2018 Edition):

I almost wish our URLs had years in them because I still don’t have a way to scope analytic data to only show me data from content published this year. I can see the most popular stuff from the year, but that’s regardless of when it was published, and that’s dominated by the big guides we’ve had for years and keep updated.

I have been a long-time reader of CSS-Tricks, but have not yet had something to contribute with. Until now. Being a Google Analytics specialist by day, this was at last something I could contribute to CSS-Tricks. Let’s extend Google Analytics on CSS-Tricks!

Enter Google Analytics custom dimensions

Google Analytics gives you a lot of interesting insights about what visitors are doing on a website, just by adding the basic Google Analytics snippet to every page.

But Google Analytics is a one-size-fits-all tool.

In order to make it truly meaningful for a specific website like CSS-Tricks we can add additional meta information to our Google Analytics data.

The year an article was posted is an example of such meta data that Google Analytics does not have out of the box, but it’s something that is easily added to make the data much more useful. That’s where custom dimensions come in.

Create the custom dimension in Google Analytics

The first thing to do is create the new custom dimension. In the Google Analytics UI, click the gear icon, click Custom Definitions and then click Custom Dimensions.

Google Analytics admin interface

This shows a list of any existing custom dimensions. Click the red button to create a new custom dimension.

Custom dimensions overview

Let’s give the custom dimension a descriptive name. In this case, “year” seems quite appropriate since that’s what we want to measure.

The scope is important because it defines how the meta data should be applied to the existing data. In this case, the article year is related to each article the user is viewing, so we need to set it to the “hit” scope.

Another example would be meta data about the entire session, like if the user is logged in, that would be saved in a session-scoped custom dimension.

Alright, let’s save our dimension.

When the custom dimension is created, Google Analytics provides examples for how to implement it using JavaScript. We’re allowed up to 20 custom dimensions and each custom dimension is identified by an index. In this case, “year” is the first custom dimension, so it was created in Index 1 (see dimension1 in the JavaScript code below).

Custom dimension created at Index 1

If we had other custom dimensions defined, then those would live in another index. There is no way to change the index of a custom dimension, so take note of the one being used. A list of all indices can always be found in the overview:

That’s it, now it’s time to code!

Now we have to extract the article year in the code and add it to the payload so that it is sent to Google Analytics with the page view hit.

This is the code we need to execute, per the snippet we were provided when creating the custom dimension:

var dimensionValue = 'SOME_DIMENSION_VALUE'; ga('set', 'dimension1', dimensionValue);

Here is the tricky part. The ga() function is created when the Google Analytics snippet is loaded. In order to minimize the performance hit, it is placed at the bottom of the page on CSS-Tricks. This is what the basic Google Analytics snippet looks like:

<script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-12345-1', 'auto'); ga('send', 'pageview'); </script>

We need to set the custom dimension value after the snippet is parsed and before the page view hit is sent to Google Analytics. Hence, we need to set it here:

// ... ga('create', 'UA-12345-1', 'auto'); ga('set', 'dimension1', dimensionValue); // Set the custom dimension value ga('send', 'pageview');

This code is usually placed outside a WordPress Loop, but that’s where we would have access to meta information like the article year. Because of this, we need to store the article year in a JavaScript variable inside the loop, then reference that variable in the Google Analytics snippet when we get to the bottom of the page.

Save the article year within the loop

In WordPress, a standard loop starts here:

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

…and ends here:

<?php endwhile; else : ?> 	<p><?php esc_html_e( 'Sorry, no posts matched your criteria.' ); ?></p> <?php endif; ?>

Somewhere between those lines, we extract the year and save it in a JavaScript variable:

<script> 	var articleYear = "<?php the_time('Y') ?>"; </script>

Reference the article year in the Google Analytics snippet

The Google Analytics snippets is placed on all pages of the website, but the year does not make sense for all pages (e.g. the homepage). Being the good JavaScript developers that we are, we will check if the variable has been defined in order to avoid any errors.

ga('create', 'UA-68528-29', 'auto'); if (typeof articleYear !== "undefined") { 		ga('set', 'dimension1', articleYear); } ga('send', 'pageview');

That’s it! The Google Analytics page view hit will now include the article year for all pages where it is defined.

Custom dimensions do not apply to historical data

One thing to know about custom dimension — or any other modifications to your Google Analytics data — is that they only apply to new data being collected from the website. The custom dimensions described in this article was implemented in January 2019, and that means if we look at data from 2018 it will not have any data for the custom dimensions.

This is important to keep in mind for the rest of this article, when we begin to look into the data. The custom dimensions are added to all posts on CSS-Tricks, going all the way back to 2007, but we are only looking at page views that happened in 2019 — after the custom dimensions was implemented. For example, when we look at articles from 2011, we are not looking at page views in 2011 — we are looking at page views of posts from 2011 in 2019. This is important to keep in mind, when we start to look at posts from previous years.

All set? OK, let’s take a look at the new data!

Viewing the data in Google Analytics

The easiest way to see the new data is to go to Behavior → Site Content → All Pages, which will show the most viewed pages:

All Pages report

In the dropdown above the table, select “year” as a secondary dimension.

Year as secondary dimension

That gives us a table like the one below, showing the year for all articles. Notice how the homepage, which is the second most viewed page, is removed from the table because it does not have a year associated with it.

We start to get a better understanding of the website. The most viewed page (by far) is the complete guide to Flexbox which was published back in 2013. Talk about evergreen content!

Table with year as secondary dimension

Secondary is good, primary is better

OK, so the above table adds some understanding of the most viewed pages, but let’s flip the dimensions so that year is the primary dimension. There is no standard report for viewing custom dimensions as the primary dimension, so we need to create a custom report.

Custom Reports overview

Give the Custom Report a good name. Finding the metrics (blue) and dimensions (green) is easiest by searching.

Create the Custom Report

Here is what the final Custom Report should look like, with some useful metrics and dimensions. Notice how we have selected Page below Year. This will become useful in a second.

The final Custom Report

Once we hit Save, we see the aggregate numbers for all article years. 2013 is still on top, but we now see that 2011 also had some great content, which was not in the top 10 lists we previously looked at. This suggests that no single article from 2011 stood out, but in total, 2011 had some great articles that still receive a lot of views in 2019.

Aggregated numbers for article years

The percentage next to the number of page views is the percentage of the total page views. Notice how 2018 “only” accounts for 8.11% of all page views and 2019 accounts for 6.24%. This is not surprising, but shows that CSS-Tricks is partly a huge success because of the vast amount of strong reference material posted over the years, which users keep referring to.

Let’s look into 2011.

Remember how we set up the Custom Report with the Page below the Year in dimensions? This means we can now click 2011 and drill-down into that year.

It looks like a lot of almanac pages were published in 2011, which in aggregate has a lot of page views. Notice the lower-right corner where it says “1-10 of 375.” This means that 375 articles from 2011 have been viewed on the site in 2019. That is impressive!

Back to the question: Great content from 2018

Before I forget: Let’s answer that initial question from Chris.

Let’s scope the analytics data to content published this year (2018). Here are the top 10 posts:

Top 10 posts published in 2018

Understanding the two-headed beast

In Thank You (2018 Edition), Chris also wrote:

For the last few years, I’ve been trying to think of CSS-Tricks as this two-headed beast. One head is that we’re trying to produce long-lasting referential content. We want to be a site that you come to or land on to find answers to front-end questions. The other head is that we want to be able to be read like a magazine. Subscribe, pop by once a week, snag the RSS feed… whatever you like, we hope CSS-Tricks is interesting to read as a hobbyist magazine or industry rag.

Let’s dig into that with another custom dimension: Post type. CSS-Tricks uses a number of custom post types like videos, almanac entries, and snippets in addition to the built-in post types, like posts or pages.

Let’s also extract that, like we did with the article year:

<script> 	var articleYear = "<?php the_time('Y') ?>"; 	var articleType = "<?php get_post_type($ post->ID) ?>"; </script>

We’ll save it into custom dimension Index 2, which is hit-scoped just like we did with year. Now we can build a new custom report like this:

Custom post types

Now we know that blog posts account for 55% of page views, while snippets and almanac (the long-lasting referential content) account for 44%.

Now, blog posts can also be referential content, so it is safe to say that at least half of the traffic on CSS-Tricks is coming because of the referential content.

From a one-man band to a 333-author content team

When CSS-Tricks started in 2007 it was just Chris. At the time of writing, 333 authors have contributed.

Let’s see how those authors have contributed to the page views on CSS-Tricks using — you probably guessed it — another custom dimension!

<script> 	var articleYear = "<?php the_time('Y') ?>"; 	var articleAuthor = "<?php the_author() ?>"; 	var articleType = "<?php get_post_type($ post->ID) ?>"; </script>

Here are the top 10 most viewed authors in 2019.

Top 10 authors on CSS-Tricks

Let’s break this down even further by year with a secondary dimension and select 500 rows in the lower-right corner, so we get all 465 rows.

Top 10 authors and year

We can then export the data to Excel and make a pivot table of the data, counting authors per year.

Excel pivot table with count of authors per year

You like charts? We can make one with some beautiful v17 colors, showing the number of authors per year.

Authors per year

It is amazing to see the steady growth in authors contributing to CSS-Tricks per year. And given 2019 already has 33 different authors, it looks like 2019 could set a new record.

But are those new authors generating any page views?

Let’s make a new pivot chart where we compare Chris to all other authors.

Pivot table comparing page views

…and then chart that over time.

Share of page views by author per year

It definitely looks like CSS-Tricks is becoming a multi-author site. While Chris is still the #1 author, it is good to see that the constant flow of new high-quality content does not solely depend on him, which is a good trend for CSS-Tricks and makes it possible to cover a lot more topics going forward.

But what happened in 2011, you might ask? Let’s have a look. In a custom report, you can have five levels of dimensions. For now we will stick with four.

Custom report with four dimensions to drill into

Now we can click on the year 2011 and get the list of authors.

2011 authors

Hello Sara Cope! What awesome content did you write in 2011?

Sara Cope almanac pages

Looks like a lot of those almanac pages we saw earlier. Click that!

107 almanac pages by Sara Cope

Indeed, a lot of almanac pages! 107 to be exact. A lot of great content that still receives lots of page views in 2019 to boot.

Summary

Google Analytics is a powerful tool to understand what users are doing on your website, and with a little work, meta data that is specific to your website can make it extra powerful. As seen in this article, adding a few simple meta data that’s already accessible in WordPress can unlock a world of opportunities to analyze and add a whole new dimension of knowledge about the content and visitors of a site, like we did here on CSS-Tricks.


If you’re interested in another similar journey involving custom dimensions and making Google Analytics data way more useful, check out Chris Coyier and Philip Walton in Learning to Use Google Analytics More Effectively at CodePen.

The post Extending Google Analytics on CSS-Tricks with Custom Dimensions appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,

Google Fonts and font-display

The font-display descriptor in @font-face blocks is really great. It goes a long way, all by itself, for improving the perceived performance of web font loading. Loading web fonts is tricky stuff and having a tool like this that works as well as it does is a big deal for the web.

It’s such a big deal that Google’s own Pagespeed Insights / Lighthouse will ding you for not using it. A cruel irony, as their own Google Fonts (easily the most-used repository of custom fonts on the web) don’t offer any way to use font-display.

Summarized by Daniel Dudas here:

Google Developers suggests using Lighthouse -> Lighthouse warns about not using font-display on loading fonts -> Web page uses Google Fonts the way it’s suggested on Google Fonts -> Google Fonts doesn’t supports font-display -> Facepalm.

Essentially, we developers would love a way to get font-display in that @font-face block that Google serves up, like this:

@font-face {   font-family: "Open Sans Regular";   src: url("...");   font-display: swap; }

Or, some kind of alternative that is just as easy and just as effective.

Seems like query params is a possibility

When you use a Google Font, they give you a URL that coughs up a stylesheet and makes the font work. Like this:

https://fonts.googleapis.com/css?family=Roboto

They also support URL params for a variety of things, like weights:

https://fonts.googleapis.com/css?family=Open+Sans:400,700

And subsets:

http://fonts.googleapis.com/css?family=Creepster&text=TRICKS https://fonts.googleapis.com/css?family=Open+Sans:400,700&amp;subset=cyrillic

So, why not…

http://fonts.googleapis.com/css?family=Creepster&font-display=swap

The lead on the project says that caching is an issue with that (although it’s been refuted by some since they already support arbitrary text params).

Adding query params reduces x-site cache hits. If we end up with something for font-display plus a bunch of params for variable fonts that could present us with problems.

They say that again later in the thread, so it sounds unlikely that we’re going to get query params any time soon, but I’d love to be wrong.

Option: Download & Self-Host Them

All Google Fonts are open source, so we can snag a copy of them to use for whatever we want.

Once the font files are self-hosted and served, we’re essentially writing @font-face blocks to link them up ourselves and we’re free to include whatever font-display we want.

Option: Fetch & Alter

Robin Richtsfeld posted an idea to run an Ajax call from JavaScript for the font, then alter the response to include font-display and inject it.

const loadFont = (url) => {   // the 'fetch' equivalent has caching issues   var xhr = new XMLHttpRequest();   xhr.open('GET', url, true);   xhr.onreadystatechange = () => {     if (xhr.readyState == 4 && xhr.status == 200) {       let css = xhr.responseText;       css = css.replace(/}/g, 'font-display: swap; }');        const head = document.getElementsByTagName('head')[0];       const style = document.createElement('style');       style.appendChild(document.createTextNode(css));       head.appendChild(style);     }   };   xhr.send(); }  loadFont('https://fonts.googleapis.com/css?family=Rammetto+One');

Clever! Although, I’m not entirely sure how this fits into the world of font loading. Since we’re now handling loading this font in JavaScript, the loading performance is tied to when and how we’re loading the script that runs this. If we’re going to do that, maybe we ought to look into using the official webfontloader?

Option: Service Workers

Similar to above, we can fetch the font and alter it, but do it at the Service Worker level so we can cache it (perhaps more efficiently). Adam Lane wrote this:

self.addEventListener("fetch", event => {   event.respondWith(handleRequest(event)) });  async function handleRequest(event) {   const response = await fetch(event.request);   if (event.request.url.indexOf("https://fonts.googleapis.com/css") === 0 && response.status < 400) {     // Assuming you have a specific cache name setup        const cache = await caches.open("google-fonts-stylesheets");     const cacheResponse = await cache.match(event.request);     if (cacheResponse) {       return cacheResponse;   }   const css = await response.text();   const patched = css.replace(/}/g, "font-display: swap; }");   const newResponse = new Response(patched, {headers: response.headers});   cache.put(event.request, newResponse.clone());     return newResponse;   }   return response; }

Even Google agrees that using Service Workers to help Google Fonts is a good idea. Workbox, their library for abstracting service worker management, uses Google Fonts as the first demo on the homepage:

// Cache the Google Fonts stylesheets with a stale while revalidate strategy. workbox.routing.registerRoute(   /^https://fonts.googleapis.com/,   workbox.strategies.staleWhileRevalidate({     cacheName: 'google-fonts-stylesheets',   }), );  // Cache the Google Fonts webfont files with a cache first strategy for 1 year. workbox.routing.registerRoute(   /^https://fonts.gstatic.com/,   workbox.strategies.cacheFirst({     cacheName: 'google-fonts-webfonts',     plugins: [       new workbox.cacheableResponse.Plugin({         statuses: [0, 200],       }),       new workbox.expiration.Plugin({         maxAgeSeconds: 60 * 60 * 24 * 365,       }),     ],   }), );

Option: Cloudflare Workers

Pier-Luc Gendreau looked into using Cloudflare workers to handle this, but then followed up with Supercharge Google Fonts with Cloudflare and Service Workers, apparently for even better perf.

It has a repo.

Option: Wait for @font-feature-values

One of the reasons Google might be dragging its heels on this (they’ve said the same), is that there is a new CSS @rule called @font-feature-values that is designed just for this situation. Here’s the spec:

This mechanism can be used to set a default display policy for an entire font-family, and enables developers to set a display policy for @font-face rules that are not directly under their control. For example, when a font is served by a third-party font foundry, the developer does not control the @font-face rules but is still able to set a default font-display policy for the provided font-family. The ability to set a default policy for an entire font-family is also useful to avoid the ransom note effect (i.e. mismatched font faces) because the display policy is then applied to the entire font family.

There doesn’t seem to be much movement at all on this (just a little), but it doesn’t seem pretty awesome to wait on it.

The post Google Fonts and font-display appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Google Labs Web Components

I think it’s kinda cool to see Google dropping repos of interesting web components. It demonstrates the possibilities of cool new web features and allows them to ship them in a way that’s compatible with entirely web standards.

Here’s one: <two-up>

I wanted to give it a try, so I linked up their example two-up-min.js script in a Pen and used the element by itself to see how it works. They expose the component’s styling with custom properties, which I’d say is a darn nice use case for those.

<two-up&rt; by Chris Coyier (@chriscoyier) on CodePen.

The post Google Labs Web Components appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]