I have tried implementing the script (Account Anomaly) with slight modifications.

67 views
Skip to first unread message

Devaraju Pichchuka

unread,
Jan 5, 2025, 7:37:19 PMJan 5
to Google Ads Scripts Forum
Dear Team,

I have tried implementing the below script to get MCC Account Anomaly Detection for the last 30 days vs pervious 30 days absolute change and % of changes in the specific metrics including Impressions, Clicks, Conversions & Cost. However, this script is not running at all. it would be great. if i can get immediate assistance to correct this script and get objective fulfilled. 

/**
 * Configuration to be used for the Account Performance Comparator.
 */
CONFIG = {
  // URL of the default spreadsheet template. Make sure the sheet is owned by or shared with the same Google user executing the script.
  'spreadsheet_url': 'https://docs.google.com/spreadsheets/d/183GMf9qvzoV0O2b7be1JsNxNshyhkf-CwUwnN1MJDoM/edit?gid=0#gid=0',

  'mcc_child_account_limit': 100,

  // Reporting API version
  'reporting_options': {
    'apiVersion': 'v17'
  },

  // Alert thresholds for anomalies
  'alert_threshold': {
    'clicks': 50, // Example threshold; adjust as needed
    'impressions': 100,
    'cost': 1000
  }
};

function main() {
  const spreadsheet = SpreadsheetApp.openByUrl(CONFIG.spreadsheet_url);
  let sheet = spreadsheet.getSheetByName('PerformanceData');

  // Create or clear the 'PerformanceData' sheet
  if (!sheet) {
    sheet = spreadsheet.insertSheet('PerformanceData');
  } else {
    sheet.clear();
  }

  // Set headers
  const headers = [
    'MCC Account ID', 'Account ID', 'Account Name', 'Clicks', 'Impressions',
    'Conversions', 'Cost', 'Last 30 Days', 'Previous 30 Days', 'Absolute Change', 'Alert'
  ];
  sheet.appendRow(headers);

  const accountIterator = AdsManagerApp.accounts().withLimit(CONFIG.mcc_child_account_limit).get();

  while (accountIterator.hasNext()) {
    const account = accountIterator.next();
    AdsManagerApp.select(account);

    // Fetch data for last 30 days and previous 30 days
    const last30Days = fetchPerformanceData("LAST_30_DAYS");
    const prev30Days = fetchPerformanceData("PREVIOUS_30_DAYS");

    // Calculate percentage and absolute changes
    const changes = calculatePercentageChanges(last30Days, prev30Days);
    const absoluteChanges = calculateAbsoluteChanges(last30Days, prev30Days);

    // Determine alerts based on thresholds
    const alert = generateAlert(changes, absoluteChanges);

    // Append data to the spreadsheet
    sheet.appendRow([
      AdsApp.currentAccount().getCustomerId(),
      account.getCustomerId(),
      account.getName(),
      changes.clicks,
      changes.impressions,
      changes.conversions,
      changes.cost,
      JSON.stringify(last30Days),
      JSON.stringify(prev30Days),
      JSON.stringify(absoluteChanges),
      alert
    ]);
  }

  Logger.log('Performance data updated in spreadsheet.');
}

/**
 * Fetch performance data for the specified date range.
 */
function fetchPerformanceData(dateRange) {
  const query = `
    SELECT
      metrics.impressions,
      metrics.clicks,
      metrics.conversions,
      metrics.cost_micros
    FROM campaign
    WHERE metrics.impressions > 0
    DURING ${dateRange}
  `;

  const report = AdsApp.report(query);
  const rows = report.rows();

  let data = {
    impressions: 0,
    clicks: 0,
    conversions: 0,
    cost: 0
  };

  while (rows.hasNext()) {
    const row = rows.next();
    data.impressions += parseFloat(row['metrics.impressions']);
    data.clicks += parseFloat(row['metrics.clicks']);
    data.conversions += parseFloat(row['metrics.conversions']);
    data.cost += parseFloat(row['metrics.cost_micros']) / 1e6; // Convert micros to standard currency
  }

  return data;
}

/**
 * Calculate percentage changes between two periods.
 */
function calculatePercentageChanges(current, previous) {
  const calculateChange = (current, previous) => {
    return previous === 0 ? (current > 0 ? 100 : 0) : ((current - previous) / previous) * 100;
  };

  return {
    impressions: calculateChange(current.impressions, previous.impressions).toFixed(2),
    clicks: calculateChange(current.clicks, previous.clicks).toFixed(2),
    conversions: calculateChange(current.conversions, previous.conversions).toFixed(2),
    cost: calculateChange(current.cost, previous.cost).toFixed(2)
  };
}

/**
 * Calculate absolute changes between two periods.
 */
function calculateAbsoluteChanges(current, previous) {
  return {
    impressions: Math.abs(current.impressions - previous.impressions),
    clicks: Math.abs(current.clicks - previous.clicks),
    conversions: Math.abs(current.conversions - previous.conversions),
    cost: Math.abs(current.cost - previous.cost)
  };
}

/**
 * Generate alerts based on thresholds.
 */
function generateAlert(changes, absoluteChanges) {
  const alertMessages = [];
  if (changes.clicks > CONFIG.alert_threshold.clicks) {
    alertMessages.push('Clicks anomaly');
  }
  if (changes.impressions > CONFIG.alert_threshold.impressions) {
    alertMessages.push('Impressions anomaly');
  }
  if (absoluteChanges.cost > CONFIG.alert_threshold.cost) {
    alertMessages.push('Cost anomaly');
  }
  return alertMessages.join(', ');
}

Awaiting quick response.

Regards
Devaraj Pichchuka

Google Ads Scripts Forum Advisor

unread,
Jan 5, 2025, 7:57:32 PMJan 5
to adwords...@googlegroups.com

Hi Devaraj,

Thank you for reaching out to the Google Ads Scripts support team.

I would like to inform you that the Account Anomaly Detector script for MCC accounts have been deprecated and are removed from the Google Ads Script documentation. I would suggest that you use the Account Anomaly Detector - Single Account script in child accounts under the MCC account so that the script will work as intended. 

Please note that we explicitly do not support the deprecated solutions that no longer appear on the developers site. The solutions we do support are the ones that are in the Google Ads account (UI) "Tools > Bulk Actions > Solutions (only in child accounts)" menu.

I hope this helps! Feel free to get back to us if you still face any issues. 

This message is in relation to case "ref:!00D1U01174p.!5004Q02vGrRl:ref" (ADR-00280530)

Thanks,
 
Google Logo Google Ads Scripts Team

Feedback
How was our support today?

rating1    rating2    rating3    rating4    rating5



Reply all
Reply to author
Forward
0 new messages