Google Ads Script for Low‑Spending Shopping Products

Most Shopping accounts have a long tail of products that get impressions and a few clicks, but never enough spend to generate statistically significant data. These products stagnate in the background while your budget keeps flowing into a small set of items. The result is missed revenue opportunities and a distorted view of what really works in your catalog.
The low‑spending products script tackles this by systematically identifying items with very low ad spend over a defined period and surfacing them so you can optimize them separately. Instead of letting Google allocate budget blindly, you create a controlled environment where promising products can finally ramp up.

How does this custom script work?

This script scans your Pmax campaigns and looks for products that:
• Have accumulated only a small amount of spend in the selected date range.
• Label low‑spending items so you can group and manage them in dedicated campaigns.
• Export them to a spreadsheet, giving you a clear list of IDs that need attention.

• This turns what was previously a hidden issue into something visible, measurable, and optimizable.

				
					// Low performing IDs Script by Francesco Azzarone
// custom requests? francesco.azzarone@foxdatax.com


// Enter your data here;

// CONFIG

const MERCHANT_ID = Merchant id number;
const SPREADSHEET_URL = "Spreadsheet URL";
const SHEET_NAME_SUFFIX = "Low Spending Products";
const COST_THRESHOLD = 3; // Here you can choose the amount
const DAYS_AGO = 30;
const LABEL_VALUE = "Low Spending Products"; // custom label Value
const CUSTOM_LABEL = "custom_label_4"; // Choose your custom label


function main() {
  try {
    const accountName = AdWordsApp.currentAccount().getName();
    const sheetName = accountName + " " + SHEET_NAME_SUFFIX;

    Logger.log("Analysis for account: " + accountName);

    const productIdsMerchant = getProductIds(MERCHANT_ID);
    const lowCostProducts = getLowCostProducts(DAYS_AGO, COST_THRESHOLD);
    const updatedProducts = updateProductIds(lowCostProducts, productIdsMerchant);

    pushToSpreadsheet(updatedProducts, sheetName);
    Logger.log("Script completed.");
  } catch (error) {
    Logger.log("Error: " + error.toString());
  }
}

function getProductIds(merchantId) {
  let productIds = [];
  let pageToken;
  do {
    let response = ShoppingContent.Products.list(merchantId, { pageToken: pageToken });
    if (response && response.resources) {
      response.resources.forEach(product => {
        let idParts = product.id.split(':');
        productIds.push(idParts[idParts.length - 1]);
      });
      pageToken = response.nextPageToken;
    } else {
      break;
    }
  } while (pageToken);
  return productIds;
}

function getLowCostProducts(daysAgo, costThreshold) {
  const today = new Date();
  const startDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() - daysAgo);
  const dateFrom = Utilities.formatDate(startDate, AdWordsApp.currentAccount().getTimeZone(), 'yyyyMMdd');
  const dateTo = Utilities.formatDate(today, AdWordsApp.currentAccount().getTimeZone(), 'yyyyMMdd');

  const query = `
    SELECT OfferId, Cost, Conversions, ConversionValue
    FROM SHOPPING_PERFORMANCE_REPORT
    DURING ${dateFrom},${dateTo}
  `;

  const products = [];
  const report = AdsApp.report(query);
  const rows = report.rows();

  while (rows.hasNext()) {
    const row = rows.next();
    const offerId = row['OfferId'];
    const cost = parseFloat(row['Cost'].replace(",", ""));
    const conversions = parseFloat(row['Conversions'].replace(",", ""));
    const conversionValue = parseFloat(row['ConversionValue'].replace(",", ""));
    const roas = cost > 0 ? (conversionValue / cost) * 100 : 0;
    
    if (cost < costThreshold) {
      products.push([
        offerId,
        LABEL_VALUE,
        cost.toFixed(2) + " €",
        conversionValue.toFixed(2) + " €",
        roas.toFixed(2) + " %",
        conversions.toFixed(2)
      ]);
    }
  }

  return products;
}

function updateProductIds(productsGoogle, productIdsMerchant) {
  const idMap = {};
  productIdsMerchant.forEach(id => {
    idMap[id.toLowerCase()] = id;
  });

  return productsGoogle.map(product => {
    product[0] = idMap[product[0].toLowerCase()] || product[0];
    return product;
  });
}

function pushToSpreadsheet(data, sheetName) {
  const spreadsheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
  let sheet = spreadsheet.getSheetByName(sheetName);

  if (!sheet) {
    sheet = spreadsheet.insertSheet(sheetName);
  } else {
    sheet.clear();
  }

  // Updated headers
  sheet.appendRow(["id", CUSTOM_LABEL, "Cost (€;)", "Conversion Value (€)", "ROAS (%)", "Conversions"]);

  if (data.length > 0) {
    const range = sheet.getRange(2, 1, data.length, 6);
    range.setValues(data);
    sheet.getRange('A2:A' + (data.length + 1)).setNumberFormat("@");
    Logger.log("Inseriti " + data.length + " prodotti.");
  } else {
    Logger.log("No products with cost lower than " + COST_THRESHOLD + "€.");
  }
}
				
			

How to install the script

To install this Google Ads script in your account, follow these steps:

    • Sign in to your Google Ads account.
    • Click the Tools and settings icon in the top menu.
    • Under Bulk actions, click Scripts to open the Scripts workspace.
    • On the Scripts page, click the blue + button to create a New script.
    • Give the script a clear name (for example: “Low Spending Products – Shopping”), so it’s easy to identify later.
    • Paste the script code
    • Delete any placeholder code that appears in the editor.
    • Copy the full script and paste it into the Google Ads script editor.
    • Replace the placeholder values in the config section, such as:`MERCHANT_ID` with your Merchant Center ID, `SPREADSHEET_URL` with the URL of your Google Sheets document (important: the sheet must have edit access so the script can write into it).
    • On Advanced API, flag the option “Shopping Content
    • Authorize the script
    • Click Save in the top right of the editor.
    • Click “Authorize” above the editor to grant the script permission to access and modify your Google Ads account and linked services.
    • Run and schedule the script when you are satisfied with the preview, click Run to apply it for the first time.
    • Check the “Logs” and “Changes” panel to verify that: No errors are thrown.
    • Back on the Scripts list, set the Frequency (running it on the first day of the month is suggested; once per month is enough)
    • Save the schedule so the script keeps updating your low-spending products and the spreadsheet automatically.
    • Last Thing is to import the spreadsheet in Merchant Center as a supplemental feed
    • After few hours, the new label should start appearing in Merchant Center and then in Google Ads.
      At that point, you can build a dedicated campaign for these products to give them extra visibility.