在 Google 个广告中提醒未获批准的产品脚本

Alert disapproved products script in Google Ads

我有一个 Google 广告脚本,当我的 Merchant Center 帐户中的产品被拒批时,它应该会通过电子邮件通知我。

此脚本中有一个 "include" 筛选字段,它限制了监视的产品,但是,我无法让它工作。其他一切似乎都正常。

这是脚本的一部分,您可以在其中过滤产品:

var productIdToInclude = [];

我试过以下版本,都没有用:

var productIdToInclude = ["product123"];
var productIdToInclude = ['product123'];
var productIdToInclude = [product123];

这是脚本中关于此过滤器的注释:

// Filters
// These two variables store the product ID's that we want to filter by.
// The ID's need to be in string format e.g. productIdToInclude = ["123"];

整个脚本可以找到here

我相信我有语法错误,但我无法弄清楚。

脚本中的过滤逻辑对于包含似乎工作正常但对于排除我确实发现了一些问题。更新您的排除功能,看看是否有效。

function satisfiesIdExcludeFilters(productIdToExclude, product) {
  if (productIdToExclude.length) {
    for (index = 0; index < productIdToExclude.length; ++index) {
      if (product['productId'].indexOf(productIdToExclude[index]) !== -1) {
        return false;
      }
    }
    return true;
  } else {
    return true;
  }
}

更新后的脚本应如下所示:

/**
 *
 * GMC Disapproval Checker
 *
 * This script checks your Google Merchant Centre for disapproved products. It will send you emails if the percentage of
 * disapproved products exceeds a specified threshold. You need to select the Shopping Content api in the Advanced Apis
 * section to run this script.
 *
 * Google AdWords Script maintained on brainlabsdigital.com
 *
 */


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

var merchantId = '';
// Replace this with your Merchant Center ID.

var threshold = 30;
// Percentage of disapproved products you would like to be alerted by.
// Do NOT include the percentage sign in this variable.

var email = ['aa@example.com'];
// Email addresses to send the disapproval alert to.
// If there is more than one email they should be comma separated
// - e.g. ["aa@example.com", "bb@example.com"]

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Filters
// These two variables store the product ID's that we want to filter by.
// The ID's need to be in string format e.g. productIdToInclude = ["123"];
// These are actually substrings of the productId so be careful not to use
// strings which are not reasonably specific.

var productIdToInclude = ['Z200'];
var productIdToExclude = [];

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

function main() {

  var pageToken;
  var maxResults = 250;
  // These variables are used to fetch all the products (maximum of 250) on a page
  // in the merchant centre. We can then iterate over the pages by using the next
  // page token which is given as part of the response to our request.

  var totalProducts = 0;
  var disapprovedProducts = [];

  do {
    // This is a quick check to see if the filters supplied are valid
    checkFiltersDontContradict(productIdToInclude, productIdToExclude);

    var productStatuses = ShoppingContent.Productstatuses.list(merchantId, {
      pageToken: pageToken,
      maxResults: maxResults
    });

    // If the 'approvalStatus' of our product is not 'approved' then we say it is disapproved.
    if (productStatuses.resources) {
      for (var i = 0; i < productStatuses.resources.length; i++) {
        product = productStatuses.resources[i];
        if (satisfiesAllFilters(product)) {
          totalProducts += 1;
          if (product['destinationStatuses'][0]['approvalStatus'] == 'disapproved') {
            disapprovedProducts.push(product['productId']);
          }
        }
      }
    } else {
      Logger.log('No more products in account ' + merchantId);
    }
    // We then pull our next PageToken from our response and use it to make a new request.
    // If there is no next PageToken then we exit our iteration.
    pageToken = productStatuses.nextPageToken;
  } while (pageToken);

  disapprovalPercentage = (disapprovedProducts.length * 100) / totalProducts;
  Logger.log(disapprovedProducts.length + ' of ' + totalProducts +
    ' products in your account were disapproved - ' +
    disapprovalPercentage.toFixed(2) + '%')

  // If our threshold is exceeded then we assemble an email with details of the alert and send it to our contact emails.
  if (disapprovalPercentage >= threshold) {

    var subject = merchantId + ' GMC Disapproval Alert Email';
    var message = disapprovedProducts.length + ' of ' + totalProducts +
      ' products in your GMC (' + merchantId + ') were disapproved - ' +
      disapprovalPercentage.toFixed(2) + '%' + '\n' +
      'Disapproved products: ' + disapprovedProducts.join('\n');

    MailApp.sendEmail(email.join(','), subject, message);
    Logger.log('Message to ' + email.join(',') + ' sent.');
  }
}

function checkFiltersDontContradict(productIdToInclude, productIdToExclude) {
  if (productIdToInclude.length && productIdToExclude.length) {
    for (var i in productIdToInclude) {
      if (productIdToExclude.indexOf(productIdToInclude[i]) > -1) {
        throw "Filters have shared values - can not include and exclude simultaneously";
      }
    }
  } else {
    return true;
  }
}

function satisfiesAllFilters(product) {
  return (satisfiesIdIncludeFilters(productIdToInclude, product) &&
    satisfiesIdExcludeFilters(productIdToExclude, product));
}

function satisfiesIdIncludeFilters(productIdToInclude, product) {
  if (productIdToInclude.length) {
    for (index = 0; index < productIdToInclude.length; ++index) {
      if (product['productId'].indexOf(productIdToInclude[index]) !== -1) {
        return true;
      }
    }
    return false;
  } else {
    return true;
  }
}

function satisfiesIdExcludeFilters(productIdToExclude, product) {
  if (productIdToExclude.length) {
    for (index = 0; index < productIdToExclude.length; ++index) {
      if (product['productId'].indexOf(productIdToExclude[index]) !== -1) {
        return false;
      }
    }
    return true;
  } else {
    return true;
  }
}