关键字和广告文案错误检查器脚本

如果你是一个人,你就会意识到人类会犯错误的事实。即使我们最优秀的人有时也会犯错,无论我们如何努力做到完美。Google Ads 也不例外:过时的促销活动、拼写错误(拼写正确吗?)、新手关键字定位错误——它们无处不在。将此脚本视为众所周知的铅笔的橡皮擦。PPC 校对员。

脚本是如何工作的?

该脚本将自动检查一些新手错误,例如带有加号的完全匹配关键字或缺少加号的广泛匹配关键字。(你不是还在使用纯粹的广泛匹配,是吗?)

它将寻找那些你忘记更新的过去几年非常令人尴尬的促销优惠——就像我昨天在进行账户审计时看到的那些 2013 年的促销优惠。然后,为了进行一些更卫生的检查,它会扫描您的广告文字,以查找一些常见的英语拼写错误和拼写错误。

我如何使用它?

要使用该脚本,请将以下代码复制到您的 Google Ads 帐户中,然后更改以下设置:

  1. 电子表格Url 是Google Sheet 的URL,结果将被复制到其中。创建一个空白电子表格并将 URL 放在此处。
  2. 在数组 campaignNameDoesNotContain 中输入要排除的活动名称中包含的短语列表。这些必须用引号引起来并用逗号分隔 – 例如,[“Display”、“Shopping”] 以排除名称包含“display”或“shopping”的所有广告系列。
    • 留空 [] 以不排除任何广告系列。
    • 这不区分大小写。
    • 您可以使用它来避免查看展示广告系列,其中关键字不使用 BMM。
  3. 在数组 campaignNameContains 中输入您想要包含的活动名称中包含的短语列表。与campaignNameDoesNotContain 一样,它们应该用引号和逗号分隔:例如[“Brand”、“Generic”] 仅包含名称包含“brand”或“generic”的广告系列。
    • 留空 [] 以包含所有广告系列。
    • 同样,这不区分大小写。
    • 如果您需要在 CampaignNameContains 或 CampaignNameDoesNotContain 中添加双引号,请在其前添加反斜杠。例如,如果广告系列名称为 9″ Tablets,您应将其输入为 9″ Tablets。
    • 如果您的帐户非常大并且脚本不断超时,您可以尝试使用 CampaignNameContains 或 campaignNameDoesNotContain 多次运行脚本以每次查看不同的广告系列。
  4. 如果 ignorePausedCampaigns 为 true,则脚本将只查看当前活动的广告系列。如果您想查看当前暂停的广告系列,请将它们设置为 false。
    • 您可以使用它在新广告系列上线之前对其进行检查!
  5. 如果 checkKeywords 为 true,则脚本将检查您的关键字。
  6. 如果 checkAdText 为 true,则脚本将检查您的文字广告。
  7. 如果 checkSpelling 为 true,则脚本将查看您的文字广告中是否出现了一些常见的英语拼写错误。
    • 如果脚本在您尝试运行时超时,您可以尝试将其中两个设置为 false,一个设置为 true,以便一次执行一项检查。
  8. checkAdsFor 是用于检查广告的文本片段列表(如果 checkAdText 为 true)。如果广告包含任何内容,则会将其记录在电子表格中。我们建议过去几年和复活节,但您可以删除任何您不想要的或添加您自己的 – 它们只需要用引号引起来并用逗号分隔。
    • 你猜怎么着?这不区分大小写。
    • 使用正则表达式的强大功能,该脚本将只检查整个单词——如果您正在检查“复活节”,它不会选择写着“东方”或“盛宴”的广告。它将选择“复活节”。
    • 该脚本将广告文字视为一个整体,而不是逐行查看。这意味着,如果您在 checkAdsFor 中输入“黑色星期五”,它会发现广告在 DL1 结束时是否显示为“黑色”,在 DL2 开始时是否显示为“星期五”。

关键字和广告文案错误检查器脚本代码

// ID: b56487c96aacf454b27b15e1fb427abe
/**
 *
 * AdWords Script for keyword and ad checking.
 * Checks keyword text for punctuation suggesting the wrong match type, checks
 * broad match keywords for missing BMM. Checks ad, sitelink and callout text
 * for text that suggests ads are out-of-date (like previous years and seasonal
 * events) and for common English spelling mistakes.
 *
 * Version: 2.1
 * Updated 2017-01-05: changed 'CreativeApprovalStatus' to 'CombinedApprovalStatus'
 * Google AdWords Script maintained by brainlabsdigital.com
 *
 */

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Options

var spreadsheetUrl = 'https://docs.google.com/YOUR-SPREADSHEET-URL-HERE';
// The URL of the Google Doc the results will be put into.

var campaignNameDoesNotContain = [];
// Use this if you want to exclude some campaigns.
// For example ["Display"] would ignore any campaigns with 'Display' in the name,
// while ["Display","Shopping"] would ignore any campaigns with 'Display' or
// 'Shopping' in the name.
// Leave as [] to not exclude any campaigns.

var campaignNameContains = [];
// Use this if you only want to look at some campaigns.
// For example ["Brand"] would only look at campaigns with 'Brand' in the name,
// while ["Brand","Generic"] would only look at campaigns with 'Brand' or 'Generic'
// in the name.
// Leave as [] to include all campaigns.

var ignorePausedCampaigns = true;
// Set this to true to only look at currently active campaigns.
// Set to false to include campaigns that had impressions but are currently paused.

var checkKeywords = true;
// Set this to true to look at keyword text for errors like missing BMM.

var checkAdText = true;
// Set this to true to look at ad text for errors like previous years.

var checkSpelling = true;
// Set this to true to check ad text for some common spelling errors.

var checkExtensions = true;
// Set this to true to check the text of sitelinks and callouts for text and
// spelling errors (if those are enabled above).

var checkAllExtensions = false;
// Set this to true to check the text of all of your sitelinks and callouts.
// If this is false, only extensions that have had impressions with the filtered
// campaigns will be checked.

var checkAdsFor = ['2014', '2015', '2016', 'Easter', 'Christmas', 'New Year'];
// This is the text that the script will look for in ad copy.
// Feel free to add more!


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Advanced Options
var misspellingsSheetUrl = 'https://docs.google.com/spreadsheets/d/1Z2Fg_F8WhmY8Ey5Bv4Zuk8vcTW7A2EoVwMbGVz7TNms/edit#gid=0';
// This spreadsheet has the list of English spelling errors, used if checkSpelling
// is true.

var misspellingsSheetName = 'Main';
// This is the name of the sheet in the above spreadsheet


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Functions

function main() {
  var spreadsheet = checkSpreadsheet(spreadsheetUrl, 'the spreadsheet');
  var sheet = spreadsheet.getSheets()[0];
  var campaignIds = getCampaignIds();

  if (checkKeywords) {
    keywordChecking(campaignIds, sheet);
    Logger.log('Finished keyword checks.');
  }

  if (checkAdText) {
    adTextChecking(campaignIds, sheet);
    Logger.log('Finished ad text checks.');
  }

  if (checkSpelling) {
    adSpellingChecking(campaignIds, sheet);
    Logger.log('Finished common misspelling checks.');
  }
}

// Check the spreadsheet URL has been entered, and that it works
function checkSpreadsheet(spreadsheetUrl, spreadsheetName) {
  if (spreadsheetUrl.replace(/[AEIOU]/g, 'X') == 'https://docs.google.com/YXXR-SPRXXDSHXXT-XRL-HXRX') {
    throw ('Problem with ' + spreadsheetName + " URL: make sure you've replaced the default with a valid spreadsheet URL.");
  }
  try {
    var spreadsheet = SpreadsheetApp.openByUrl(spreadsheetUrl);

    // Checks if you can edit the spreadsheet
    if (spreadsheetName == 'the spreadsheet') {
      var sheet = spreadsheet.getSheets()[0];
      var sheetName = sheet.getName();
      sheet.setName(sheetName);
    }

    return spreadsheet;
  } catch (e) {
    throw ('Problem with ' + spreadsheetName + " URL: '" + e + "'");
  }
}

// Get the IDs of campaigns which match the given options
function getCampaignIds() {
  var whereStatement = 'WHERE ';
  var whereStatementsArray = [];
  var campaignIds = [];

  if (ignorePausedCampaigns) {
    whereStatement += 'CampaignStatus = ENABLED ';
  } else {
    whereStatement += "CampaignStatus IN ['ENABLED','PAUSED'] ";
  }

  for (var i = 0; i < campaignNameDoesNotContain.length; i++) {
    whereStatement += "AND CampaignName DOES_NOT_CONTAIN_IGNORE_CASE '" + campaignNameDoesNotContain[i].replace(/"/g, '\"') + "' ";
  }

  if (campaignNameContains.length == 0) {
    whereStatementsArray = [whereStatement];
  } else {
    for (var i = 0; i < campaignNameContains.length; i++) {
      whereStatementsArray.push(whereStatement + 'AND CampaignName CONTAINS_IGNORE_CASE "' + campaignNameContains[i].replace(/"/g, '\"') + '" ');
    }
  }

  for (var i = 0; i < whereStatementsArray.length; i++) {
    var adTextReport = AdWordsApp.report(
      'SELECT CampaignId '
      + 'FROM   CAMPAIGN_PERFORMANCE_REPORT '
      + whereStatementsArray[i]
      + 'DURING LAST_30_DAYS'
    );

    var rows = adTextReport.rows();
    while (rows.hasNext()) {
      var row = rows.next();
      campaignIds.push(row.CampaignId);
    }
  }

  if (campaignIds.length == 0) {
    throw ('No campaigns found with the given settings.');
  }

  Logger.log(campaignIds.length + ' campaigns found');
  return campaignIds;
}

// Prints an array of rows into the spreadsheet
function printRows(sheet, title, headers, rows) {
  try {
    var printArray = [];

    sheet.getRange('R' + (sheet.getLastRow() + 2) + 'C1').setValue(title);
    if (rows.length == 0) {
      sheet.appendRow(['No issues found']);
      Logger.log("Nothing to output for '" + title + "'");
      return;
    }

    sheet.appendRow(headers);

    for (var i = 0; i < rows.length; i++) {
      printArray.push(rows[i]);
    }

    var lastRow = sheet.getLastRow();
    sheet.getRange('R' + (lastRow + 1) + 'C1:R' + (lastRow + printArray.length)
      + 'C' + (printArray[0].length)).setValues(printArray);

    Logger.log('Printed ' + rows.length + " rows for '" + title + "'");
  } catch (e) {
    Logger.log("Printing rows '" + title + "' failed: " + e);
  }
}

function keywordChecking(campaignIds, sheet) {
  try {
    var broadMissingPlusses = [];
    var nonBroadWithPlusses = [];
    var nonExactWithBrackets = [];
    var nonPhraseWithQuotes = [];

    var keywordMatchReport = AdWordsApp.report(
      'SELECT CampaignName, AdGroupName, Criteria, KeywordMatchType '
      + 'FROM   KEYWORDS_PERFORMANCE_REPORT '
      + 'WHERE AdGroupStatus = ENABLED AND Status = ENABLED AND IsNegative = FALSE '
      + 'AND CampaignId IN [' + campaignIds.join(',') + '] '
      + 'DURING LAST_30_DAYS'
    );

    var keywordMatchRows = keywordMatchReport.rows();

    while (keywordMatchRows.hasNext()) {
      var keywordMatchRow = keywordMatchRows.next();

      if (keywordMatchRow.KeywordMatchType.toLowerCase() === 'broad') {
        if (keywordMatchRow.Criteria.indexOf('+') < 0) {
          // if the broad KW is entirely missing +s
          broadMissingPlusses.push([keywordMatchRow.CampaignName, keywordMatchRow.AdGroupName, "'" + keywordMatchRow.Criteria, keywordMatchRow.KeywordMatchType]);
        } else {
          var words = keywordMatchRow.Criteria.split(' ');
          var missingPlus = false;
          for (var j = 0; j < words.length; j++) {
            if (words[j].substr(0, 1) != '+') {
              missingPlus = true;
              break;
            }
          }
          if (missingPlus) {
            broadMissingPlusses.push([keywordMatchRow.CampaignName, keywordMatchRow.AdGroupName, "'" + keywordMatchRow.Criteria, keywordMatchRow.KeywordMatchType]);
          }
        }
      } else {
        // If the keyword is not broad
        if (keywordMatchRow.Criteria.indexOf('+') > -1) {
          nonBroadWithPlusses.push([keywordMatchRow.CampaignName, keywordMatchRow.AdGroupName, "'" + keywordMatchRow.Criteria, keywordMatchRow.KeywordMatchType]);
        }
      }

      if (keywordMatchRow.KeywordMatchType.toLowerCase() != 'exact') {
        if (keywordMatchRow.Criteria.indexOf('[') > -1 || keywordMatchRow.Criteria.indexOf(']') > -1) {
          nonExactWithBrackets.push([keywordMatchRow.CampaignName, keywordMatchRow.AdGroupName, "'" + keywordMatchRow.Criteria, keywordMatchRow.KeywordMatchType]);
        }
      }

      if (keywordMatchRow.KeywordMatchType.toLowerCase() != 'phrase') {
        if (keywordMatchRow.Criteria.indexOf('"') > -1) {
          nonPhraseWithQuotes.push([keywordMatchRow.CampaignName, keywordMatchRow.AdGroupName, "'" + keywordMatchRow.Criteria, keywordMatchRow.KeywordMatchType]);
        }
      }
    } // end while

    var headers = ['Campaign', 'Ad Group', 'Keyword', 'Match'];

    printRows(sheet, 'Broad Match Keywords Missing +s', headers, broadMissingPlusses);
    printRows(sheet, 'Non-Broad Match Keywords With +s', headers, nonBroadWithPlusses);
    printRows(sheet, 'Non-Exact Match Keywords With [ or ]', headers, nonExactWithBrackets);
    printRows(sheet, 'Non-Phrase Match Keywords With "s', headers, nonPhraseWithQuotes);
  } catch (e) {
    Logger.log('Keyword checking failed: ' + e);
  }
} // end function keywordChecking


function adTextChecking(campaignIds, sheet) {
  try {
    //
    var adLines = ['Headline', 'Description1', 'Description2', 'DisplayUrl'];
    var adsWithBadText = [];
    var etaLines = ['HeadlinePart1', 'HeadlinePart2', 'Description', 'Path1', 'Path2'];
    var etasWithBadText = [];
    var patterns = [];
    var charactersToEscape = ['\', '/', '.', '?', '+', '*', '^', '$', '[', ']', '(', ')', '{', '}'];
    for (var k = 0; k < checkAdsFor.length; k++) {
      var cleanedText = checkAdsFor[k].toLowerCase();
      for (var i = 0; i < charactersToEscape.length; i++) {
        cleanedText = cleanedText.replace(charactersToEscape[i], '\' + charactersToEscape[i]);
      }
      patterns.push(RegExp('(^|\W)' + cleanedText + '($|\W)'));
    }

    var adTextReport = AdWordsApp.report(
      'SELECT CampaignName, AdGroupName, Headline, HeadlinePart1, HeadlinePart2, Description, Description1, Description2, DisplayUrl, Path1, Path2, AdType '
      + 'FROM   AD_PERFORMANCE_REPORT '
      + 'WHERE AdGroupStatus = ENABLED AND Status = ENABLED '
      + 'AND AdType IN [TEXT_AD, EXPANDED_TEXT_AD] AND CombinedApprovalStatus != DISAPPROVED '
      + 'AND CampaignId IN [' + campaignIds.join(',') + '] '
      + 'DURING LAST_30_DAYS'
    );

    var rows = adTextReport.rows();

    while (rows.hasNext()) {
      var row = rows.next();

      if (row.AdType == 'Text ad') {
        var textFound = checkAd(row, adLines, patterns);

        if (textFound.length > 0) {
          adsWithBadText.push([row.CampaignName, row.AdGroupName, row.Headline,
          row.Description1, row.Description2, row.DisplayUrl,
          textFound.join(', ')
          ]);
        }
      } else {
        var textFound = checkAd(row, etaLines, patterns);

        if (textFound.length > 0) {
          etasWithBadText.push([row.CampaignName, row.AdGroupName, row.HeadlinePart1,
          row.HeadlinePart2, row.Description, row.Path1, row.Path2,
          textFound.join(', ')
          ]);
        }
      }
    } // end while

    var headers = ['Campaign', 'Ad Group', 'Headline', 'Description 1', 'Description 2',
      'Display Url', 'Problematic Text'
    ];
    var etaHeaders = ['Campaign', 'Ad Group', 'Headline 1', 'Headline 2', 'Description',
      'Path 1', 'Path 2', 'Problematic Text'
    ];
    printRows(sheet, 'Ad Copy With Problematic Text', headers, adsWithBadText);
    printRows(sheet, 'ETA Ad Copy With Problematic Text', etaHeaders, etasWithBadText);

    if (checkExtensions) {
      var calloutLines = ['1'];
      var sitelinkLines = ['1', '3', '4', '5'];
      var calloutsWithBadText = [];
      var sitelinksWithBadText = [];

      var extReport = AdWordsApp.report(
        'SELECT AttributeValues, PlaceholderType '
        + 'FROM PLACEHOLDER_FEED_ITEM_REPORT '
        + 'WHERE PlaceholderType IN [1, 17] '
        + 'AND Status = ENABLED '
        + (checkAllExtensions ? '' : 'AND CampaignId IN [' + campaignIds.join(',') + '] ')
        + 'DURING LAST_30_DAYS'
      );

      var rows = extReport.rows();
      while (rows.hasNext()) {
        var row = rows.next();
        var values = JSON.parse(row.AttributeValues);

        if (row.PlaceholderType == 17) {
          var textFound = checkAd(values, calloutLines, patterns);

          if (textFound.length > 0) {
            calloutsWithBadText.push([values['1'], textFound.join(', ')]);
          }
        } else {
          var textFound = checkAd(values, sitelinkLines, patterns);

          if (textFound.length > 0) {
            sitelinksWithBadText.push([values['1'], removeUndefined(values['3']), removeUndefined(values['4']),
            values['5'], textFound.join(', ')
            ]);
          }
        }
      } // end while

      var sitelinkHeaders = ['Sitelink', 'Description 1', 'Description 2', 'Sitelink URL', 'Problematic Text'];
      var calloutHeaders = ['Callout', 'Problematic Text'];
      printRows(sheet, 'Sitelinks With Problematic Text', sitelinkHeaders, sitelinksWithBadText);
      printRows(sheet, 'Callouts With Problematic Text', calloutHeaders, calloutsWithBadText);
    }
  } catch (e) {
    Logger.log('Ad text checking failed: ' + e);
  }
} // function adTextChecking


function checkAd(ad, adLines, patterns) {
  var adCopy = '';

  for (var j = 0; j < adLines.length; j++) {
    adCopy += ' ' + ad[adLines[j]];
  }
  adCopy = adCopy.toLowerCase();
  var textFound = [];

  for (var k = 0; k < checkAdsFor.length; k++) {
    if (adCopy.match(patterns[k])) {
      textFound.push(checkAdsFor[k]);
    }
  }

  return textFound;
}


function removeUndefined(str) {
  return (str == undefined ? 'None' : str);
}


function adSpellingChecking(campaignIds, sheet) {
  try {
    var misspellingsSpreadsheet = checkSpreadsheet(misspellingsSheetUrl, 'the misspelling spreadsheet');
    var misspellingsSheet = misspellingsSpreadsheet.getSheetByName(misspellingsSheetName);
    var misspellings = misspellingsSheet.getRange(2, 1, misspellingsSheet.getLastRow() - 1, 2).getValues();

    for (var k = 0; k < misspellings.length; k++) {
      misspellings[k][0] = ' ' + misspellings[k][0] + ' ';
    }

    var adLines = ['Headline', 'Description1', 'Description2', 'DisplayUrl'];
    var etaLines = ['HeadlinePart1', 'HeadlinePart2', 'Description', 'Path1', 'Path2'];
    var adsWithBadText = [];
    var etasWithBadText = [];

    var adTextReport = AdWordsApp.report(
      'SELECT CampaignName, AdGroupName, Headline, HeadlinePart1, HeadlinePart2, Description, Description1, Description2, DisplayUrl, Path1, Path2, AdType '
      + 'FROM   AD_PERFORMANCE_REPORT '
      + 'WHERE AdGroupStatus = ENABLED AND Status = ENABLED '
      + 'AND AdType IN [TEXT_AD, EXPANDED_TEXT_AD] AND CombinedApprovalStatus != DISAPPROVED '
      + 'AND CampaignId IN [' + campaignIds.join(',') + '] '
      + 'DURING LAST_30_DAYS'
    );

    var rows = adTextReport.rows();
    while (rows.hasNext()) {
      var row = rows.next();

      if (row.AdType == 'TEXT_AD') {
        var [textFound, didYouMean] = spellCheck(row, adLines, misspellings);

        if (textFound.length > 0) {
          adsWithBadText.push([row.CampaignName, row.AdGroupName, row.Headline,
          row.Description1, row.Description2, row.DisplayUrl,
          textFound.join(', '), didYouMean.join(', ')
          ]);
        }
      } else {
        var [textFound, didYouMean] = spellCheck(row, etaLines, misspellings);

        if (textFound.length > 0) {
          etasWithBadText.push([row.CampaignName, row.AdGroupName, row.HeadlinePart1,
          row.HeadlinePart2, row.Description, row.Path1, row.Path2,
          textFound.join(', '), didYouMean.join(', ')
          ]);
        }
      }
    } // end while

    if (checkExtensions) {
      var calloutLines = ['1'];
      var sitelinkLines = ['1', '3', '4', '5'];
      var calloutsWithBadText = [];
      var sitelinksWithBadText = [];

      var extReport = AdWordsApp.report(
        'SELECT AttributeValues, PlaceholderType '
        + 'FROM PLACEHOLDER_FEED_ITEM_REPORT '
        + 'WHERE PlaceholderType IN [1, 17] '
        + 'AND Status = ENABLED '
        + (checkAllExtensions ? '' : 'AND CampaignId IN [' + campaignIds.join(',') + '] ')
        + 'DURING LAST_30_DAYS'
      );

      var rows = extReport.rows();

      while (rows.hasNext()) {
        var row = rows.next();
        var values = JSON.parse(row.AttributeValues);

        if (row.PlaceholderType == 17) {
          var [textFound, didYouMean] = spellCheck(values, calloutLines, misspellings);

          if (textFound.length > 0) {
            calloutsWithBadText.push([values['1'], textFound.join(', '), didYouMean.join(', ')]);
          }
        } else {
          var [textFound, didYouMean] = spellCheck(values, sitelinkLines, misspellings);

          if (textFound.length > 0) {
            sitelinksWithBadText.push([values['1'], removeUndefined(values['3']), removeUndefined(values['4']),
            values['5'], textFound.join(', '), didYouMean.join(', ')
            ]);
          }
        }
      } // end while
    }

    var headers = ['Campaign', 'Ad Group', 'Headline', 'Description 1', 'Description 2',
      'Display Url', 'Possible Misspelling', 'Possible Corrections'
    ];
    var etaHeaders = ['Campaign', 'Ad Group', 'Headline 1', 'Headline 2', 'Description',
      'Path 1', 'Path 2', 'Possible Misspelling', 'Possible Corrections'
    ];
    var sitelinkHeaders = ['Sitelink', 'Description 1', 'Description 2', 'Possible Misspelling', 'Possible Corrections'];
    var calloutHeaders = ['Callout', 'Possible Misspelling', 'Possible Corrections'];
    printRows(sheet, 'Ad Copy With Possible Misspellings', headers, adsWithBadText);
    printRows(sheet, 'ETA Ad Copy With Possible Misspellings', etaHeaders, etasWithBadText);
    if (checkExtensions) {
      printRows(sheet, 'Sitelinks With Possible Misspellings', sitelinkHeaders, sitelinksWithBadText);
      printRows(sheet, 'Callouts With Possible Misspellings', calloutHeaders, calloutsWithBadText);
    }
  } catch (e) {
    Logger.log('Ad spell checking failed: ' + e);
  }
} // function adSpellingChecking


function spellCheck(row, adLines, misspellings) {
  var adCopy = ' ';
  for (var j = 0; j < adLines.length; j++) {
    adCopy += ' ' + row[adLines[j]];
  }
  adCopy += ' ';
  adCopy = adCopy.toLowerCase();
  adCopy = adCopy.replace(/(_|[^w-'0-9])/g, ' ');
  var textFound = [];
  var didYouMean = [];

  for (var k = 0; k < misspellings.length; k++) {
    if (adCopy.indexOf(misspellings[k][0]) > -1) {
      textFound.push(misspellings[k][0].trim());
      didYouMean.push(misspellings[k][1]);
    }
  }

  return [textFound, didYouMean];
}

给TA打赏
共{{data.count}}人
人已打赏
广告投放

暂停重复的广泛关键字脚本

2021-10-17 18:27:06

广告投放

出价策略监控脚本

2021-10-17 18:34:19

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索