IT-Academy

404 stránka nenájdená

Jun 16th, 2017
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * @name Link Checker
  3.  *
  4.  * @overview The Link Checker script iterates through all the ads and keywords
  5.  *     in your account and makes sure their URLs do not produce "Page not found"
  6.  *     or other types of error responses. See
  7.  *     https://developers.google.com/adwords/scripts/docs/solutions/link-checker
  8.  *     for more details.
  9.  *
  10.  * @author AdWords Scripts Team [[email protected]]
  11.  *
  12.  * @version 1.2
  13.  */
  14.  
  15. /**
  16.  * The URL of the tracking spreadsheet. This should be a copy of
  17.  * https://goo.gl/bMrbW5
  18.  */
  19. var SPREADSHEET_URL = 'https://docs.google.com/spreadsheets/d/1CaUSdtVeRW69jW4VFfdCx35w2_Opf0Em3Pe1B8sbmRw/edit#gid=0';
  20.  
  21. /**
  22.  * Status code for items to be checked.
  23.  */
  24. var STATUSES_TO_CHECK = ['ENABLED', 'PAUSED'];
  25.  
  26. /**
  27.  * Limit the number of ad and keyword URLs checked by this script per run.
  28.  */
  29. var MAX_URLS_TO_CHECK = 800;
  30.  
  31. var LABEL_NAME = 'link_checked';
  32.  
  33. var shelper = new SHelper();
  34. var badUrls = 0;
  35. var numUrlsChecked = 0;
  36.  
  37. function main() {
  38.   var isFirstRun = isFirstRunOfTheDay();
  39.  
  40.   if (isFirstRun) {
  41.     dealWithFirstRunOfTheDay();
  42.   }
  43.  
  44.   if (shelper.config.email.length == 0 &&
  45.       shelper.config.emailPreference != 'Never') {
  46.     Logger.log('WARNING: no email specified, proceeding...');
  47.   }
  48.   if (!shelper.config.checkAds && !shelper.config.checkKeywords) {
  49.     Logger.log('WARNING: requested no keywords and no ads checking. Exiting.');
  50.     return;
  51.   }
  52.   createLinkCheckerLabel();
  53.  
  54.   var anythingChanged = shelper.config.checkKeywords &&
  55.       checkKeywordUrls(AdWordsApp.keywords(), isFirstRun);
  56.   anythingChanged = (shelper.config.checkAds &&
  57.       checkAdUrls(AdWordsApp.ads(), isFirstRun)) || anythingChanged;
  58.  
  59.   if (anythingChanged) {
  60.     shelper.flush();
  61.     if (badUrls > 0 && shelper.config.email.length > 0 &&
  62.         shelper.config.emailPreference == 'As soon as an error is discovered') {
  63.       var bad = shelper.spreadsheet.getRangeByName('bad').getValue();
  64.       var good = shelper.spreadsheet.getRangeByName('good').getValue();
  65.       sendReportWithErrors(good, bad);
  66.     }
  67.   } else {
  68.     shelper.spreadsheet.getRangeByName('finished').setValue(
  69.         'All done for the day!');
  70.   }
  71.   Logger.log('Done');
  72. }
  73.  
  74. function isFirstRunOfTheDay() {
  75.   var date = new Date();
  76.   var lastCheckDate = shelper.dataSheet.getRange(1, 3).getValue();
  77.   return lastCheckDate.length == 0 ||
  78.       date.getYear() != lastCheckDate.getYear() ||
  79.       date.getMonth() != lastCheckDate.getMonth() ||
  80.       date.getDay() != lastCheckDate.getDay();
  81. }
  82.  
  83. function dealWithFirstRunOfTheDay() {
  84.   var date = new Date();
  85.   Logger.log('The script is running for the first time today...');
  86.  
  87.   // kill the label.
  88.   var labels = AdWordsApp.labels().withCondition(
  89.       "Name='" + LABEL_NAME + "'").get();
  90.   if (labels.hasNext()) {
  91.     if (AdWordsApp.getExecutionInfo().isPreview()) {
  92.       Logger.log('WARNING: This script needs to remove a label named "%s" ' +
  93.           'to work correctly, but this action cannot be performed in ' +
  94.           'preview mode. Please run this script, or remove the label ' +
  95.           'manually if you wish to preview the script.', LABEL_NAME);
  96.     }
  97.  
  98.     labels.next().remove();
  99.   }
  100.   // send out yesterday's report
  101.   if (shelper.config.email.length > 0 &&
  102.       (shelper.config.emailPreference == 'Once a day' ||
  103.       shelper.config.emailPreference == 'Once a day if there are errors')) {
  104.     var bad = shelper.spreadsheet.getRangeByName('bad').getValue();
  105.     var good = shelper.spreadsheet.getRangeByName('good').getValue();
  106.     if (shelper.config.emailPreference == 'Once a day') {
  107.       if (bad == 0) {
  108.         MailApp.sendEmail(shelper.config.email,
  109.             'AdWords Link Checker verified ' + good +
  110.             ' URLs on account ' +
  111.             AdWordsApp.currentAccount().getCustomerId() +
  112.             ', all looking good!', '');
  113.       } else {
  114.         sendReportWithErrors(good, bad);
  115.       }
  116.     } else if (shelper.config.emailPreference ==
  117.         'Once a day if there are errors' && bad > 0) {
  118.       sendReportWithErrors(good, bad);
  119.     }
  120.   }
  121.   // reset the spreadsheet
  122.   shelper.spreadsheet.getRangeByName('account_id_dashboard').setValue(
  123.       AdWordsApp.currentAccount().getCustomerId());
  124.   shelper.spreadsheet.getRangeByName('account_id_report').setValue(
  125.       AdWordsApp.currentAccount().getCustomerId());
  126.   shelper.spreadsheet.getRangeByName('date').setValue(date);
  127.   shelper.spreadsheet.getRangeByName('finished').setValue(
  128.       'Checking links...');
  129.   shelper.dataSheet.getRange(
  130.       4, 1, shelper.dataSheet.getMaxRows() - 3, 6).clear();
  131. }
  132.  
  133. function sendReportWithErrors(good, bad) {
  134.   var emailBody = [];
  135.   emailBody.push('Summary for account ' +
  136.       AdWordsApp.currentAccount().getCustomerId() +
  137.       ': ' + good + ' good URLs, ' + bad + ' bad ones\n');
  138.   emailBody.push('Full report available at ' + shelper.spreadsheet.getUrl() +
  139.       '\n');
  140.   shelper.reset();
  141.   var row = shelper.readRow();
  142.   while (row != null && emailBody.length < 200) {
  143.     if (row[1] >= 300) {
  144.       var entityType = row[4].length > 0 ? 'Keyword: ' : 'Ad: ';
  145.       var entityText = row[4].length > 0 ? row[4] : row[5];
  146.       emailBody.push('Campaign: ' + row[2] + ', Ad Group: ' + row[3] + ', ' +
  147.           entityType + entityText);
  148.       emailBody.push(row[0] + ' - ' + row[1] + ' response code.\n');
  149.     }
  150.     row = shelper.readRow();
  151.   }
  152.   if (emailBody.length >= 200) {
  153.     emailBody.push('Further URLs omitted. Check the report at ' +
  154.         shelper.spreadsheet.getUrl());
  155.   }
  156.   shelper.reset();
  157.   MailApp.sendEmail(shelper.config.email,
  158.     'AdWords Link Checker verified found ' + bad +
  159.     ' bad URLs on account ' + AdWordsApp.currentAccount().getCustomerId() + '',
  160.     emailBody.join('\n'));
  161. }
  162.  
  163. function checkAdUrls(selector, isFirstRun) {
  164.  
  165.   var iterator = selector
  166.       .withCondition('CreativeFinalUrls STARTS_WITH_IGNORE_CASE "h"')
  167.       .withCondition('Status IN [' + STATUSES_TO_CHECK.join(',') + ']')
  168.       .withCondition('CampaignStatus IN [' + STATUSES_TO_CHECK.join(',') + ']')
  169.       .withCondition('AdGroupStatus IN [' + STATUSES_TO_CHECK.join(',') + ']')
  170.       .withCondition('LabelNames CONTAINS_NONE ["' + LABEL_NAME + '"]')
  171.       .get();
  172.   Logger.log('Checking %s ads...', iterator.totalNumEntities());
  173.  
  174.   if (iterator.totalNumEntities() == 0 && isFirstRun) {
  175.     Logger.log('WARNING: The script is not checking any ad URLs. If this is ' +
  176.         'not expected, then ensure that you have enabled ads in your ' +
  177.         'account. Also check the logs for any earlier errors.');
  178.   }
  179.  
  180.   return checkUrls(iterator);
  181. }
  182.  
  183. function checkKeywordUrls(selector, isFirstRun) {
  184.   var iterator = selector
  185.       .withCondition('FinalUrls STARTS_WITH_IGNORE_CASE "h"')
  186.       .withCondition('Status IN [' + STATUSES_TO_CHECK.join(',') + ']')
  187.       .withCondition('CampaignStatus IN [' + STATUSES_TO_CHECK.join(',') + ']')
  188.       .withCondition('AdGroupStatus IN [' + STATUSES_TO_CHECK.join(',') + ']')
  189.       .withCondition('LabelNames CONTAINS_NONE ["' + LABEL_NAME + '"]')
  190.       .get();
  191.   Logger.log('Checking %s keywords...', iterator.totalNumEntities());
  192.  
  193.   if (iterator.totalNumEntities() == 0 && isFirstRun) {
  194.     Logger.log('WARNING: The script is not checking any keyword URLs. This ' +
  195.         'may happen if none of your keywords have a final URL. If this not ' +
  196.          'expected, then ensure that you have enabled keywords in your ' +
  197.          'account. Also check the logs for any earlier errors.');
  198.   }
  199.  
  200.   return checkUrls(iterator);
  201. }
  202.  
  203. function checkUrls(iterator) {
  204.   if (!iterator.hasNext()) {
  205.     return false;
  206.   }
  207.  
  208.   var urlMap = {};
  209.  
  210.   while (iterator.hasNext()) {
  211.     var entity = iterator.next();
  212.  
  213.     if (numUrlsChecked > MAX_URLS_TO_CHECK) {
  214.       Logger.log('Checked %s urls. Will resume in next run.', numUrlsChecked);
  215.       break;
  216.     }
  217.  
  218.     var urls = [entity.urls().getFinalUrl(), entity.urls().getMobileFinalUrl()];
  219.     for (var i = 0; i < urls.length; i++) {
  220.       if (urls[i] == null) {
  221.         continue;
  222.       }
  223.       var lastUrl = encodeURI(urls[i]);
  224.       if (lastUrl in urlMap) {
  225.         continue;
  226.       }
  227.       urlMap[lastUrl] = true;
  228.  
  229.       var now = new Date().getTime();
  230.       var responseCode = 0;
  231.       try {
  232.         numUrlsChecked++;
  233.         var response = UrlFetchApp.fetch(lastUrl, {muteHttpExceptions: true});
  234.         responseCode = response.getResponseCode();
  235.       } catch (e) {
  236.         // Something went wrong. Since this a script error, let's mark it as
  237.         // 500.
  238.         Logger.log('Could not fetch %s due to an internal error : "%s". ' +
  239.             'Marking this URL as failed, with an error code 500.', lastUrl, e);
  240.         responseCode = 500;
  241.       }
  242.       var then = new Date().getTime();
  243.       Utilities.sleep(then - now);
  244.       if (responseCode < 300) {
  245.         shelper.writeRow(lastUrl, responseCode);
  246.       } else {
  247.         badUrls++;
  248.         if (typeof(entity['getHeadline']) != 'undefined') {
  249.           var adText = entity.getType() == 'TEXT_AD' ?
  250.             entity.getHeadline() + '\n' + entity.getDescription1() + '\n' +
  251.             entity.getDescription2() : entity.getType();
  252.           shelper.writeRow(lastUrl, responseCode,
  253.                            entity.getCampaign().getName(),
  254.                            entity.getAdGroup().getName(),
  255.                            null, adText);
  256.         } else {
  257.           shelper.writeRow(lastUrl, responseCode,
  258.                            entity.getCampaign().getName(),
  259.                            entity.getAdGroup().getName(),
  260.                            entity.getText());
  261.         }
  262.       }
  263.  
  264.     }
  265.     entity.applyLabel(LABEL_NAME);
  266.   }
  267.   return true;
  268. }
  269.  
  270. function createLinkCheckerLabel() {
  271.   var labels = AdWordsApp.labels().withCondition(
  272.       "Name='" + LABEL_NAME + "'").get();
  273.   if (!labels.hasNext()) {
  274.     if (AdWordsApp.getExecutionInfo().isPreview()) {
  275.       Logger.log('WARNING: This script needs to create a label named "%s" to ' +
  276.           'work correctly, but this action cannot be performed in preview ' +
  277.           'mode. Please run this script, or create the label manually if you ' +
  278.           'wish to preview the script.', LABEL_NAME);
  279.     }
  280.     AdWordsApp.createLabel(LABEL_NAME,
  281.         "Managed by Link Checker, please don't modify!", '#60e020');
  282.   }
  283. }
  284.  
  285. // Spreadsheet helper
  286. function SHelper() {
  287.   this.MAX_ROWS = 20000;
  288.   this.BATCH_SIZE = 50;
  289.  
  290.   Logger.log('Using spreadsheet - %s.', SPREADSHEET_URL);
  291.   this.spreadsheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
  292.  
  293.   this.dataSheet = this.spreadsheet.getSheets()[1];
  294.   this.config = {
  295.     checkAds: this.spreadsheet.getRangeByName('check_ads').getValue() == 'Yes',
  296.     checkKeywords: this.spreadsheet.getRangeByName('check_keywords').
  297.         getValue() == 'Yes',
  298.     email: this.spreadsheet.getRangeByName('email_address').getValue(),
  299.     emailPreference: this.spreadsheet.getRangeByName('email_preference').
  300.         getValue()
  301.   };
  302.   this.globalRow = 4;
  303.   this.cells = null;
  304.   this.localRow = 0;
  305.  
  306.   this.reset = function() {
  307.     this.globalRow = 4;
  308.     this.cells = null;
  309.     this.localRow = 0;
  310.   };
  311.   this.readRow = function() {
  312.     initCells(this);
  313.     if (this.localRow == this.cells.length) {
  314.       this.globalRow += this.cells.length;
  315.       if (this.globalRow >= this.dataSheet.getMaxRows()) {
  316.         return null;
  317.       }
  318.       this.cells = this.dataSheet.getRange(
  319.           this.globalRow, 2, this.BATCH_SIZE, 6).getValues();
  320.       this.localRow = 0;
  321.     }
  322.     if (this.cells[this.localRow][0].length > 0) {
  323.       return this.cells[this.localRow++];
  324.     } else {
  325.       return null;
  326.     }
  327.   };
  328.   this.writeRow = function() {
  329.     fetchCells(this);
  330.     for (var i = 0; i < arguments.length; i++) {
  331.       this.cells[this.localRow][i] = arguments[i];
  332.     }
  333.   };
  334.   this.flush = function() {
  335.     if (this.cells) {
  336.       this.dataSheet.getRange(this.globalRow, 2, this.cells.length, 6).
  337.           setValues(this.cells);
  338.       this.dataSheet.getRange(1, 1).copyFormatToRange(
  339.           this.dataSheet,
  340.           3,
  341.           3,
  342.           this.globalRow,
  343.           this.globalRow + this.cells.length);
  344.     }
  345.   };
  346.   function initCells(instance) {
  347.     if (instance.cells == null) {
  348.       instance.globalRow = 4;
  349.       instance.cells = instance.dataSheet.getRange(
  350.           instance.globalRow, 2, instance.BATCH_SIZE, 6).getValues();
  351.       instance.localRow = 0;
  352.     }
  353.   }
  354.   function fetchCells(instance) {
  355.     initCells(instance);
  356.     while (!findEmptyRow(instance) && instance.globalRow < instance.MAX_ROWS) {
  357.       if (instance.dataSheet.getMaxRows() <
  358.           instance.globalRow + this.BATCH_SIZE) {
  359.         instance.dataSheet.insertRowsAfter(
  360.             instance.dataSheet.getMaxRows(), instance.BATCH_SIZE);
  361.       }
  362.       instance.flush();
  363.       instance.globalRow += instance.cells.length;
  364.       instance.cells = instance.dataSheet.getRange(
  365.           instance.globalRow, 2, instance.BATCH_SIZE, 6).getValues();
  366.       instance.localRow = 0;
  367.     }
  368.     if (instance.globalRow >= instance.MAX_ROWS) {
  369.       Logger.log('WARNING: maximum length of the spreadsheet exceeded. ' +
  370.           'Exiting.');
  371.       throw '';
  372.     }
  373.   }
  374.   function findEmptyRow(instance) {
  375.     for (; instance.localRow < instance.cells.length &&
  376.         !(instance.cells[instance.localRow][0] == null ||
  377.         instance.cells[instance.localRow][0].length == 0); instance.localRow++);
  378.     return instance.localRow < instance.cells.length;
  379.   }
  380. }
Advertisement
Add Comment
Please, Sign In to add comment