GMC Top Converting Products Issue Checker

Find top converting products with any issues in Merchant Centre and send alerts via email.

Start Now!
Receive an email when top converting products encounter problems in Google Merchant Center
GMC Top Get started!

A few years ago, I wrote a script to verify if there are any issues in Merchant Centre. It gained quite a bit of popularity and received very positive feedback from the PPC community.

After a few months of using it, I stumbled across a problem: It's normal to have some issues in Merchant Centre. Instead of being helpful, the solution sent me email alerts almost every day. Eventually, I stopped paying attention to those messages.

I realised I needed a script that checks the most important products based on the number of conversions they generate. If any of them have issues, then it should email me. Thanks to this, I'll know that those messages are important.


  1. Enable Shopping Content (at the top right of the script edit window -> Advanced APIs).
  2. Set your email address in the EMAIL_SETTINGS variable.
  3. Set your Merchant ID in the MERCHANT_ID variable.
  4. Schedule the script to run once daily in the morning.

Optional Configuration

  • Set the number of days to look back in the DAYS_LOOK_BACK variable.
  • Set the number of products to check in the PRODUCTS_LIMIT variable.
The script
Copyright 2024 Krzysztof Bycina,
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
See the License for the specific language governing permissions and
limitations under the License.

// --------------------------------------- Configuration:

// Optional Configuration:
const PRODUCTS_LIMIT = 100; // Number of top converting items to fetch
const DAYS_LOOK_BACK = 30; // Number of days to look back on the conversion numbers
// --------------------------------------- End of the configuration

function main() {

  const topConvertingItems = getTopConvertingItemIDs();
  const allIssues = countIssues(MERCHANT_ID, topConvertingItems);

  allIssues.sort((a, b) => b.conversions - a.conversions);

  logIssues(allIssues); // Log issues

  const emailSent = sendEmails(allIssues);

  if (emailSent) {
    Logger.log("Email sent with issues.");
  } else {
    Logger.log("No issues found - email not sent.");

function getTopConvertingItemIDs() {
  const startDate = Utilities.formatDate(new Date( - DAYS_LOOK_BACK * 86400000), 
                                          AdsApp.currentAccount().getTimeZone(), 'yyyy-MM-dd');
  const endDate = Utilities.formatDate(new Date( - 86400000), 
                                       AdsApp.currentAccount().getTimeZone(), 'yyyy-MM-dd');

  const query = `SELECT segments.product_item_id, metrics.conversions, campaign.advertising_channel_type
                 FROM shopping_performance_view
                 WHERE BETWEEN '${startDate}' AND '${endDate}'
                 ORDER BY metrics.conversions DESC
                 LIMIT ${PRODUCTS_LIMIT}`;

  const report =;
  return [].map(row => ({
    id: row['segments.product_item_id'],
    conversions: row['metrics.conversions']

function countIssues(merchantId, topConvertingItems) {
  let issuesData = [];
  let pageToken;
  const maxResults = 250;

  do {
    const response = ShoppingContent.Productstatuses.list(merchantId, {pageToken, maxResults});
    response.resources.forEach(product => {
      const productId = product.productId.split(':').pop();
      const item = topConvertingItems.find(({ id }) => id.toLowerCase() === productId.toLowerCase());

      if (item && product.itemLevelIssues) {
          id: productId,
          issue: product.itemLevelIssues[0].description,
          conversions: item.conversions

    pageToken = response.nextPageToken;
  } while (pageToken);

  return issuesData;

function validateEmail(email) {
  if (!/^\S+@\S+\.\S+$/.test(email)) {
    throw new Error('Invalid email address.');

function validateMerchantID(id) {
  if (!/^\d+$/.test(id)) {
    throw new Error('Invalid Merchant Center ID.');

function logIssues(issuesData) {
  if (issuesData.length === 0) {
    Logger.log("No issues found.");

  Logger.log("List of issues:");
  issuesData.forEach(issue => {
    Logger.log(`ID: ${}, Issue: ${issue.issue}, Conversions: ${issue.conversions}`);

function sendEmails(issuesData) {
  if (issuesData.length === 0) {
    return false;

  const subject = `${AdsApp.currentAccount().getName()}: Converting IDs Issues - Look Back: ${DAYS_LOOK_BACK} Days`;
  let htmlContent = '<p>Hi,<br><br>Please see the list of issues:</p><table border="1"><tr><th>ID</th><th>Issue Type</th><th>Conversions</th></tr>';
  issuesData.forEach(issue => {
    htmlContent += `<tr><td>${}</td><td>${issue.issue}</td><td>${issue.conversions}</td></tr>`;
  htmlContent += '</table>';

    to: EMAIL.join(','),
    htmlBody: htmlContent

  return true;
Show whole script!
Loading Comments
The Experts
Tibbe van Asten Team Lead Performance Marketing
Nils Rooijmans Water Cooler Topics
Martijn Kraan Freelance PPC Specialist
Bas Baudoin Teamlead SEA @ Happy Leads
Jermaya Leijen Digital Marketing Strategist
Krzysztof Bycina PPC Specialist from Poland
How about you? JOIN US!
Sharing Knowledge
Caring is all about sharing knowledge. In the current market, PPC specialists like to keep their knowledge and experience to themselves. We're convinced that sharing knowledge can ensure that everyone gets better at their work. We want to change this by sharing our knowledge about scripts with everyone.

Do you also want to contribute? We are open to new ideas and feedback on everything you find on

Contact us

Training &
Contact us!
Adsscripts Training & Workshop