Alert disapproved products script in Google Ads
I have a Google Ads Script, which is supposed to notify me via e-mail, when products in my merchant center account are disapproved.
There is a "include" filter field in this script, which limits the monitored products, however, I can't get it to work. Everything else seems to be working.
This is the part of the script, where you can filter the products:
var productIdToInclude = [];
I have tried the following versions, to no avail:
var productIdToInclude = ["product123"]; var productIdToInclude = ['product123']; var productIdToInclude = [product123];
This is the comment in the script about this filter:
// 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"];
The whole script can be found here.
I believe, that I have a synthax error, but I can't figure it out.
Filter logic in the script seems to be working fine for include but for exclude I did found some issue. Update your exclude function and see if that works.
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; } }Run code snippetHide resultsExpand snippetUpdated script should look like:
/** * * 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; } }Run code snippetHide resultsExpand snippetHere is a real ID for example: Z200. Still doesn't work unfortunately, returns 0 out of 0 when including a disapproved product.
@user1721135 Is it possible for you to post one of the productStatus that way it will be easier to debug the script and check.
Status of a product is either "Disapproved or invalid" or "Active"
I would also be happy, if I could have the IDs in the mail, and have another loop to parse for hardcoded ID for example
Amazing. Seems to be working, will test more and award, thank you.