This website uses cookies to ensure you get the best possible experience. See our Cookies Policy.

PMG Digital Made for Humans

What I learned from the Adwords Bid By Weather Script

6 MINUTE READ | March 3, 2015

What I learned from the Adwords Bid By Weather Script

I was recently given the task of setting up Adwords Bid By Weather script. The requirements were to change bids for specific campaigns, for every city in the US, based on the weather in that city. In this instance, we were increasing bids for cooler weather, and decreasing them for warmer weather. For information on how the script works, click here.

The Adwords Bid by Weather Script integrates with Open Weather Map. It lets you specify Campaigns, Weather Conditions, Locations, and Bid Modifiers in a spreadsheet. It then grabs the weather information and updates your bid modifiers based on your conditions.

I learned quite a few things, like just how big America is with around 17,000 cities/ towns. That’s a lot of data to try and process. Especially when you multiply that by how many campaigns and all the weather conditions you’ve set. Because I was working with so much data, I came across Adwords limits fast. Google Scripts has a lot of limitations, which means processing that amount of data is just not possible.

The first issue we ran into was that scripts time out after 30 minutes. Because of this, we had to break the script and spreadsheet up into many versions. We ended up with about 65 spreadsheets that we had scheduled to run over several hours. In the end, this solution wasn’t workable and so we changed our locations from cities, to counties. This reduced the amount of data we were trying to process by 2/3.

Another limitation was how many entities you could iterate over within the script:

“A single script can process at most 250,000 entities of all types. iterator.hasNext() will return false afterwards for any iterator, and a warning will be logged.”

The script originally gets all locations, and when you look at how much data we’re trying to process, it was easy to hit this limit. We changed this code, around line 352:

var locations = campaign.targeting().targetedLocations().get();

To the following:

var locations = campaign.targeting().targetedLocations().withIds(geocodes).get();

Now we’re only getting the specific location that matches the geocode we’re looking at.

This error occurs when running the script, and for us it was a fairly obvious once we looked at the error log:

An error occurred due to a conflicting change.Attempted new value: + 50%

This was because we were running multiple scripts at the same time that were trying to modify the same campaign. To resolve this we just split the spreadsheets up by campaigns, rather than location.

Open Weather Map is amazing. They have great support, and offer a free version of their API which is fantastic! Yet, we faced two issues when implementing the Bid by Weather script

As the script runs through the specified locations, it makes a call to the Open Weather Map API. Open Weather Map then returns the weather information for that location. On Open Weather Maps end, it searches for the location you’ve sent it and if it does not find a match, it returns an error. This unfortunately terminates the script. As a result, we had to preview the script a few times and match up/ rename any locations that were throwing back the error.

This is something that will be an issue with any API once in a while. We faced an issue with the API call timing out, this threw back an error and ended the script. Usually when we ran the script again it ran successfully without any issues. When we contacted Open Weather Map they said it was a known issue at the time and they were already working on implementing a fix.

We made a few other changes to the script, just to make it a bit easier to work with.

We changed the API call from around line 314:

'http://api.openweathermap.org/data/2.5/weather?APPID=%s&q=%s',

to:

'http://api.openweathermap.org/data/2.5/forecast/daily?APPID=%s&q=%s&cnt=1',

You can find more information about the Open Weather Map API here.

Because we were only dealing with the temperature, not precipitation or wind, we only changed the line of code around 201 from:

var temperature = toFahrenheit(weather.main.temp);

to:

var temperature = toFahrenheit(weather.list[0].temp.day);

This allowed us to run the scripts from 12am – 7am, which helped avoid API timeout issues by spacing the scripts out. It also ensured the campaign bid modifiers were set for that day as early as possible.

In the end, we were running seven campaigns, with five weather conditions each. The script originally requires you to specify each location per campaign. We had around 3000 counties, so you can start to see why I didn’t want to enter the locations against each campaign manually. We did a simple script modification applyRulesForCampaign method. This function now checks if the Weather Location specified against a campaign matches ‘all’. If it does, the script iterates over every location in the location tab of the spreadsheet. It ended up looking something like this:

function applyRulesForCampaign(
    campaignName, campaignRules, locationMapping,
    weatherConditionMapping, geoTargetData
) {
    for (var i = 0; i < campaignRules.length; i++) {
        var bidModifier = 1;
        var campaignRule = campaignRules[i];

        /* Start custom code to check if location = 'all' then iterate over all locations */
        if (campaignRule.location.toLowerCase() === 'all') {
            for (var int = 0; int < geoTargetData.length; int++) {
                // Get the weather for the required location.
                var currentLocation = geoTargetData[int][0];
                var locationDetails = locationMapping[currentLocation];

                var weather = getWeather(currentLocation);

                Logger.log('Weather for %s: %s', locationDetails, weather);

                // Get the weather rules to be checked.
                var weatherConditionName = campaignRule.condition;
                var weatherConditionRules = weatherConditionMapping[weatherConditionName];

                // Evaluate the weather rules.
                if (evaluateWeatherRules(weatherConditionRules, weather)) {
                    Logger.log('Matching Rule found: Campaign Name = %s, location = %s, ' +
                    'weatherName = %s,weatherRules = %s, noticed weather = %s.',
                    campaignRule.name, currentLocation,
                    weatherConditionName, weatherConditionRules, weather);
                    bidModifier = campaignRule.bidModifier;
                    adjustBids(campaignName, locationDetails.geoCodes, bidModifier);
                }
            }
        } else { /*End custon code, run as normal*/

        // Get the weather for the required location.
            var locationDetails = locationMapping[campaignRule.location];
            var weather = getWeather(campaignRule.location);
            Logger.log('Weather for %s: %s', locationDetails, weather);

            // Get the weather rules to be checked.
            var weatherConditionName = campaignRule.condition;
            var weatherConditionRules = weatherConditionMapping[weatherConditionName];

            // Evaluate the weather rules.
            if (evaluateWeatherRules(weatherConditionRules, weather)) {
                Logger.log('Matching Rule found: Campaign Name = %s, location = %s, ' +
                'weatherName = %s,weatherRules = %s, noticed weather = %s.',
                campaignRule.name, campaignRule.location,
                weatherConditionName, weatherConditionRules, weather);
                bidModifier = campaignRule.bidModifier;
                adjustBids(campaignName, locationDetails.geoCodes, bidModifier);
            }
        }
    }
    return;
}

While Adwords Scripts are powerful and have a lot of potential, I would recommend using the API if you’re dealing with a lot of data. Once you know what Adwords limitations are, however, it’s easy to work within them.

– Emily Fox

Insights meet inbox

Sign up for weekly articles & resources.


Posted by Emily Fox

Related Content

thumbnail image

Get Insights

Navigating the Amazon Ecosystem

2 MINUTES READ | September 10, 2018

Get Informed

A New Strategy for Testing Google AMP

3 MINUTES READ | July 13, 2017

Get Informed

Control your Adwords Campaigns using Amazon Echo

2 MINUTES READ | December 15, 2016

thumbnail image

Get Informed

A Simple Look At Natural Language Processing

2 MINUTES READ | November 9, 2016

Get Informed

PMG Technology Shortlisted For Two US Search Awards

2 MINUTES READ | September 13, 2016

Get Informed

Google I/O 2016 Highlights for Marketers

5 MINUTES READ | May 24, 2016

thumbnail image

Get Informed

What's New With Bing?

3 MINUTES READ | April 6, 2016

Get Informed

A list from Holiday's 2013

1 MINUTE READ | December 5, 2013

Get Informed

Blogging with Ghost

4 MINUTES READ | October 17, 2013

All POST