Skip to content

Instantly share code, notes, and snippets.

@daniil4udo
Created June 7, 2019 16:57
Show Gist options
  • Save daniil4udo/71cc12f2bd23c8af438f43e111dec823 to your computer and use it in GitHub Desktop.
Save daniil4udo/71cc12f2bd23c8af438f43e111dec823 to your computer and use it in GitHub Desktop.
Script to update the price and control the availability of the product in Adwords

The script to update the price in the ad and check the availability of the item in Adwords

Many website owners or PPC experts have faced the need to automate contextual advertising.

After all, automation will make boring work for you, and will allow you to engage in more interesting business.

What does the script do?

  • Enable / disable the notification about the availability status of the item on the site.

  • Parsing the price of a product from a page and put it into an ad.

  • Parsing any other information (variable) and put it into an ad.

For what kind of websites this script can be used:

  • There is a price on the product page

  • There is an identifier on the product page (in essence, you need to catch only the absence of the goods)

  • It is possible to advertise a unique product.


var URL_LEVEL = 'Ad'; // Ad or Keyword
var ONLY_ACTIVE = false; // set to false for all ads or keywords
var CAMPAIGN_LABEL = ''; // set this if you want to only check campaigns with this label
var STRIP_QUERY_STRING = true; // set this to false if the stuff that comes after the question mark is important
var WRAPPED_URLS = true; // set this to true if you use a 3rd party like Marin or Kenshoo for managing you account
// This is the specific text to search for 
// on the page that indicates the item 
// is out of stock.
var LABEL_NAMES = ['"test"'];
var OUT_OF_STOCK_TEXT = 'Out of stock';
var PRICE_TEXT_BEGIN = '<span class="price-oth">';
var PRICE_TEXT_END = ' usd</span>'; //currency
var keywords = {};

function setKeywordPrice(keyword, price) {
    var keywordId = keyword.getId();
    if (keywords[keywordId]) { } else {
        Logger.log('Keyword: ' + keyword + ', Price: ' + price);
        keyword.setAdParam(1, price);
        keywords[keywordId] = true;
    }
}

function setAdPrice(ad, price) {
    var keywords = ad.getAdGroup().keywords().get();
    while (keywords.hasNext()) {
        var keyword = keywords.next();
        setKeywordPrice(keyword, price);
        //Logger.log('Ad: '+ad+'; Price: '+price+'; Keyword: '+keyword);
    }
}

function main() {
    var alreadyCheckedUrls = {};
    var prices = {};
    var campIter = AdWordsApp.campaigns().get();
    while (campIter.hasNext()) {
        var camp = campIter.next();
        var adIter = buildSelector(camp, 'Ad');
        adIter = adIter.withCondition('LabelNames CONTAINS_ANY [' + LABEL_NAMES.join(',') + ']');
        adIter = adIter.get();
        //Logger.log(iter.totalNumEntities());
        while (adIter.hasNext()) {
            var entity = adIter.next();
            var url = entity.urls().getFinalUrl();
            if (url === null)
                continue;
            url = cleanUrl(url);
            if (prices[url]) {
                setAdPrice(entity, prices[url]);
                //Logger.log('Url: '+url+'; Price: '+prices[url]+'; Entity: '+entity);
            } else {
                var htmlCode;
                try {
                    htmlCode = UrlFetchApp.fetch(url).getContentText();
                } catch (e) {
                    Logger.log('There was an issue checking:' + url + ', Skipping.');
                    continue;
                }
                var priceStart = htmlCode.indexOf(PRICE_TEXT_BEGIN) + PRICE_TEXT_BEGIN.length;
                if (priceStart >= 0) {
                    var priceEnd = htmlCode.indexOf(PRICE_TEXT_END, priceStart);
                    prices[url] = htmlCode.substr(priceStart, priceEnd - priceStart).replace(/\D/, '');
                    //setKeywordPrice(keyword, prices[url]);
                    setAdPrice(entity, prices[url]);
                    //Logger.log('Url: '+url+'; Price: '+prices[url]+'; Entity: '+entity);
                }
            }
            //Logger.log('Url: '+url+' price is '+prices[url]);

            if (alreadyCheckedUrls[url]) {
                if (alreadyCheckedUrls[url] === 'out of stock') {
                    entity.pause();
                    //keyword.pause();
                } else {
                    entity.enable();
                    //keyword.enable();
                }
            } else {
                var htmlCode;
                try {
                    htmlCode = UrlFetchApp.fetch(url).getContentText();
                } catch (e) {
                    Logger.log('There was an issue checking:' + url + ', Skipping.');
                    continue;
                }
                if (htmlCode.indexOf(OUT_OF_STOCK_TEXT) >= 0) {
                    alreadyCheckedUrls[url] = 'out of stock';
                    entity.pause();
                } else {
                    alreadyCheckedUrls[url] = 'in stock';
                    entity.enable();
                }
                Logger.log('Url: ' + url + ' is ' + alreadyCheckedUrls[url] + '; price: ' + prices[url]);
            }
        }
    }
}

function cleanUrl(url) {
    if (WRAPPED_URLS) {
        url = url.substr(url.lastIndexOf('http'));
        if (decodeURIComponent(url) !== url) {
            url = decodeURIComponent(url);
        }
    }
    if (STRIP_QUERY_STRING) {
        if (url.indexOf('?') >= 0) {
            url = url.split('?')[0];
        }
    }
    if (url.indexOf('{') >= 0) {
        //Let's remove the value track parameters
        url = url.replace(/\{[0-9a-zA-Z]+\}/g, '');
    }
    return url;
}

function buildSelector(camp, url_level) {
    var selector = (url_level === 'Ad') ? camp.ads() : camp.keywords();
    return selector;
}

Let's figure out how to connect a script, in steps:

  • Mark the ads with labels;

  • Set on / off the availability if aplicable;

  • Modify the ads to pass the price parameter;

  • Set up parsing and transferring prices to the ad

  • Run the script

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment