Universal Analytics: Weather As A Custom Dimension

ShareShare on Google+350Tweet about this on Twitter215Share on LinkedIn30Share on Facebook48

[Last updated June 2014] I’ve fallen in love with Universal Analytics and Google Tag Manager. Together they form an incredibly powerful tool for marketing professionals. In most cases, I no longer need to post recommendations to my client for yet another page template revision, since with the tag manager in place, I can just add custom code via the admin panel. Add to that the power of Universal Analytics with its ultra-sensitive Measurement Protocol, and the ability to craft custom dimensions and metrics, and voila! I’m in a happy place.

In this post, I take you through a short JavaScript dev journey of utilizing weather data as a custom dimension in your site’s Analytics. You only need to have Universal Analytics and Google Tag Manager installed on your site.

The end result

This is what you get:
Weather as a Custom Dimension
As you can see, I’ve created a custom report which shows visits, pageviews and conversion rates (Pages / Visit > 2) for various weather conditions. This report unequivocally, with a plain-as-day-without-a-doubt display of causality, proves that when it rains, people are more likely to convert. I should do more targeting to British audiences…

Create a new tag in GTM

1. Name the tag “Weather API”
2. Choose Custom HTML Tag as the tag type
3. Enter the following code into the HTML field (Note! You need to load jQuery for this to work! See here for more information):

  var lat = geoplugin_latitude();
  var lon = geoplugin_longitude();
  var weather = "";
  var weatherAPI = "http://api.openweathermap.org/data/2.5/weather?lat="+lat+"&lon="+lon;

    type : "POST",
    dataType : "jsonp",
    url : weatherAPI+"&units=metric&callback=?",
    async : true,
    success : function(data) {
      weather = data.weather[0].main;
      dataLayer.push({"weather": weather});
    error : function(errorData) {
      console.log("Error while getting weather data :: "+errorData.status);
    complete : function() {
      dataLayer.push({"event": "weatherDone"});

4. Add rule to fire tag on every page ({{url}} matches RegEx .*)

Here’s what’s going on.

First, a couple of external JavaScript functions are called to retrieve the longitude and latitude of the visitor by using their IP addresses. I’m using the free geoPlugin service. You can load it on your site by adding <script src=”http://www.geoplugin.net/javascript.gp”></script> in your template.

Remember to load this script BEFORE the weather API runs. It’s best to put it in the <head/> of your page template. If you want, you can also put the script load as the first line of the custom HTML tag you just created.

Next, I use the API of OpenWeatherMap to retrieve the weather data for the latitude and longitude I got in the previous step. Matt Aster modified my solution so that it works with the Weather Underground API.

In the AJAX call, I make an asynchronous call to the API, requesting the data in JSONP (since it originates from a different domain than mine). If the call is successful, I look for the /weather/main/ node, as it has a nice, short description of the weather in the area (e.g. “Clear”). I then push the string into the data layer.

Finally, whether the API call is a success or not, I push an event “weatherDone” into the data layer. This is used to make sure the API call is done before the Universal Analytics tag is fired (see below).

Create new custom dimension in GA

1. Go to the admin panel of your Google Analytics site
2. Under Property, choose Custom Definitions / Custom Dimensions
Create new Custom Dimension in Google Analytics
3. Create a new Custom Dimension with the name “Weather”
4. Scope the new dimension to Session
5. Set the dimension as Active
6. Click Save
7. Make note of the index of the new dimension

Here you create a new dimension in Google Analytics and set it active. You need to make note of the dimension index, since you will be referring to this in a short while.

Create new macro in GTM

1. In Google Tag Manager, go to your container and click New Macro
Create new macro in Google Tag Manager
2. Name the macro “Weather”
3. Set Macro Type as Data Layer Variable
4. Type “weather” in Data Layer Variable Name
5. Click Save

You create the macro to access the weather string you pushed into the data layer a couple of steps ago.

Edit your GA tag

[NOTE! I suggest you take a look at this post for details on sending the weather data using a non-interaction event instead. This way your precious pageviews will never be compromised if the weather script fails to work.]

1. Go to the tag that tracks your pageviews and sends them to GA
2. Choose More Settings
3. Choose Custom Dimensions
4. Add the index number of your new dimension in the Index field
5. In the Dimension field, click {{+macro}} and choose the macro you just created
Send Custom Dimension with the pageview
6. Edit the firing rule and add condition {{event}} equals weatherDone
Wait for weather script to run
7. Save the tag
8. Create a new container version
9. Publish the new container version

Here you send a new custom dimension with the pageview, and it gets its content from the data layer variable you pushed into the data layer during the weather API call. Since the calls are asynchronous, you’ll need to make sure the UA tag is fired only after the weather API call has been made. This is done by waiting for the event weatherDone to be pushed into the data layer.

Make sure everything works

1. Visit your site
2. Take a look at the requests your site sends by using Firebug or something similar
Use Firebug to debug your scripts


I created a new custom report in GA, with visits, pageviews and conversion rate as metrics, and my new custom dimension as the dimension.

Note that it might take some time for the new dimension to start pulling in data. If Firebug tells you that the weather data is sent along with your pageview data, you’re fine.

This could be done in so many different ways, but I chose JavaScript simply for this quick prototype. I’m pretty pleased with the result, and even though I make a couple of external calls, page load speed is not an issue. There’s always a risk with asynchronous scripting that the user is quick enough to interact with the site before the pageview is sent, but I don’t think that will be an issue with this light-weight scripting.

I can think of a number of cool applications for this weather API, but I’ll leave those to your imagination.

Google Tag Manager and Universal Analytics do a terrific job of providing high value for marketing professionals. I love the fact that you don’t need to mess with the page template, and you can test and preview your tags as much as you want before publishing them.

EDIT: I edited the firing rules so that the UA tag occurs only after the weather API call has completed.

EDIT II: Note that you need to load jQuery for this to work! The $.ajax call is a jQuery function! So either load the jQuery resource in the <head/> of your page method (so that it gets loaded before the GTM container) OR have the following as the first line of the custom HTML tag:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>

EDIT III: Be sure to check my post on how to make sure the weather API is polled just once per visit. This will improve site performance, and decrease the burden on the external API.

EDIT IV: Finally, see this post on sending custom dimensions with events rather than pageviews for the optimal version of the code above.

ShareShare on Google+350Tweet about this on Twitter215Share on LinkedIn30Share on Facebook48


  1. Craig says


    I work in retail and there is a big difference for a clear day being 30C and 10C. Does this method allow you to segment by temperature?


    • says

      Hi Craig,

      Not very well. You can add temperature data as a custom metric (the API provides temperature as well), but Google Analytics doesn’t support calculated metrics at the moment. So you’d see temperatures as sums rather than averages, for example.

      The best way would be to round the temperature to the nearest 5 degrees, for example, in the script itself. Then you’d send the data as custom dimensions like “Cloudy – 5C” or something.

      It’s a bit counter-intuitive, since temperature is a numeral value and thus better suited as a metric, but without the possibility to calculate metrics (yet), you have to compromise.

  2. says

    Hi Simo,

    i saw your prez at superweek it was great! Congratulations! My question is: i have a customer who is a large ice cream shop. I thought that it would be great to connect these data with adwords. For example: if wheather is over 30 celsius then adwords would raise my bids automatically by 30%. Is that possible to create it? How would you do this? Thanks,M.

    • says

      Hi Sebestyén,

      Thanks for your comment! Superweek was amazing.

      I’m sorry but I don’t really know that much about rule-based bid management in AdWords. Would be a good idea though. My script measures the weather at the visitor’s location. To measure a static location (such as the city where the ice cream store is located), you’d just hard-code the longitude and latitude of said location into the API call.

      • says

        Simo, one more thing — I was getting errors with the weather API call and found a small typo in your code:

        Instead of “http://api.openweather.org” should be “http://api.openweatherMAP.org” (word MAP missing in the domain name :-).

        Now it works, being called once per session. All with GTM, no source code change required by our tech team, I love this :)

      • says

        Hi Petr,

        Thanks! I can’t believe I’ve had the wrong API end point all this time :D

        I’m going to make some modifications to my post on using a session cookie, since you can skip the whole cookie validation part in code with an aptly placed GTM macro!


      • says

        Cool, looking forward to this. I have already combined your three posts together and am sending weather info together with ClientID and some other information with events ONCE per session (based on your article about the cookie – validation).

        Thanks for all the helpful stuff! :)

      • says

        One more thing — I have just found out geo-location is not working with HTTPs. Any suggestions?

  3. says

    Should this work on query 1.7.2? I’m getting this error.

    [Error] ReferenceError: Can’t find variable: geoplugin_latitude
    global code (www.anythinggreen.com, line 1)
    (anonymous function) (gtm.js, line 30)
    Rb (gtm.js, line 31)
    ma (gtm.js, line 10)
    (anonymous function) (gtm.js, line 49)
    La (gtm.js, line 51)
    Ta (gtm.js, line 15)
    push (gtm.js, line 52)
    (anonymous function) (gtm.js, line 52)
    ya (gtm.js, line 12)
    (anonymous function) (gtm.js, line 53)

    • says


      Seems like you didn’t load the geoplugin resource (it’s there in the guide). You’ll need to load

      <script type=”text/javascript” src=”http://www.geoplugin.net/javascript.gp” type=”text/javascript”></script>

      before the Custom HTML runs, so either add it to your page template in the element, or as the first line of the Custom HTML tag.

  4. Daniel says

    Hello, very nice article. I just got it working on a test site, but i have a problem.

    Since the weather implementation, my Bounce Rate is dropping from an average of 70% to 5%. Other metrics seem normal to me. What can be the reason for that?

    Maybe its because of the rule of the UA-Tag, which is waiting for weather-data?

    • says

      Did you create a new page view tag for the weather script, or did you edit your existing tag? If you created a new one, you might be counting double hits for every pageview, resulting in 0 bounce rate. My guide instructs you to edit your original page view tag to incorporate the custom dimension, so make sure you’ve done that.

      • Daniel says

        Thank you, that might be right, because my bounce rate is now at 0% and the Pages / Session value is almost twice that of the days without weather-tracking.

        Some days ago i implement the weather-tracking manually without the GTM and it worked without any problems.

        Now i tried it with the GTM and i dont understand where the second page tag might be created. i just implement the tracking like you describe it in this article and now i have an UA and Weather-API-Tag in the GTM. You can give my a hint?

      • says

        It’s difficult to say without analyzing the page itself (you can e-mail me the URL where you’re trying this and I can take a look, if you want).

        If your tag setup is like you say (just the UA page tracking and the Custom HTML for the weather API), it’s pretty surely a case of an on-page tag which is also recording page views. So if you’ve left your analytics.js code on your page template, and there’s also the container code for GTM, you might be recording double page views because of this.

        Another thing which might be causing your GTM page view tag firing multiple times is if you’ve got multiple rules on the tag.

        So is it possible that you have multiple firing rules on your page view tag? For example URL – All pages AND the {{event}} equals weatherDone?

        If you have both of these, your pageview will fire on both events (all pages and when the weather is done).

      • Daniel says

        thank you very much for the fast answer.
        i forgot to delete the All Pages Rule on the UA Tag, now it Works :)

  5. says

    Hi Simo,

    love this implementation, but I have a little trouble figuring out the “Wait for weather” firing rule.

    Whenever I use your implementation, most of my visitors aren’t tracked but if I just fire it on every visit, my visitors are back i GA and I still get the weather data in my “Weather Report” (although I suppose the weather I’m registering is from the time of the first visit?)

    I might be doing something wrong, but I’m pretty sure I did everything you’ve explain above?

    • says

      It’s better to actually not send the weather data with a pageview but rather with an event tag. I edited the post now to reflect this.

      If you’ve created a session-scope dimension, the weather data will update for that particular session with every page load, unless you implement a script to just send the weather data once per session (there’s a link to this guide at the end of the post).

      I’m not entirely sure what you mean by most visitors not being tracked (pageviews not tracked or weather event not tracked), but there shouldn’t be any problems with the script. Every now and then the API call fails, but ‘weatherDone’ should still get pushed nonetheless. It might be wise, however, to wrap the whole thing around a try…catch block, which also sends ‘weatherDone’ to ensure that even more fundamental failures would not prevent the dependent tag from firing.

  6. says

    Hi Simo,

    Thank your for this article and all detailed explanations
    Very useful and hopefully insightful :)
    just implement it on my site, I’ll see tomorrow for the results.

  7. uryah says

    Hi Simo,
    thanks for all your help, but I am unable to figure out where to put the snippet created by UA ga(‘set’, ‘dimension1′, dimensionValue); do I even need it? or is there a way to input it in GTM.
    Thank you in advance

    • says

      No, you don’t need it. The number that comes after dimension (1) is what you put into the Index field of the Custom Dimension in the GA tag under More Settings -> Custom Dimensions. For Value you put in the macro.

  8. nad says

    Hi Simo, great blog, not many resources out there on GTM.

    I managed to implement Custom Dimensions based on your instructions and am now trying to implement a Custom Metric. Do you cover this somehwere? There’s absolutely no resources at all on the internet on this!
    Basically I want a metric called “clicks” that tracks the number of pageviews that contain a specific substring (e.g. “/product/”).

  9. Alex says

    Simo, hi!
    May I insert value of the dimension without macros? For example for marking users, who is already our client (dimension, scope – user)?
    In GTM in the setting of UA tag I see 2 fields: “index” and “dimension”? Or I have to insert value using DataLayer?


Leave a Reply

Your email address will not be published. Required fields are marked *

Please do not write HTML or other formatted code in your comments!