This script has a straightforward purpose: it reviews the change history for all accounts linked to our MCC (My Client Center) daily.
Its function is to identify changes made by Auto Applied recommendations. When it detects any, it sends a detailed report of these changes to a specified email address.
In essence, this solution ensures that Auto Applied recommendations remain under our control, providing added security and peace of mind.
This tool is particularly valuable for agencies and freelancers who manage multiple Google Ads accounts.
Configuration
- Set your email address in the
EMAIL_SETTINGS
variable. - Schedule the script to run once daily in the morning.
- Optionally, adjust the
LOOKBACK_DAYS
variable to define the number of days to review; the default is 3 days, with a maximum limit of 30 days.
/*
Alerts On Auto Applied Recommendations
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
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// --------------------------------------- Configuration:
const EMAIL_SETTINGS = {
RECIPIENT: 'YOUR EMAIL HERE',
SUBJECT: 'Auto-apply Recommendations have been found.'
};
const LOOKBACK_DAYS = 5; // Specify the number of days to look back (Max 30)
// --------------------------------------- End of the configuration
function main() {
const dateRange = computeDateRange(LOOKBACK_DAYS);
const managerAccount = AdsApp.currentAccount();
const allAccounts = AdsManagerApp.accounts();
let formattedEmailContent = '<html><body>';
for (const account of allAccounts) {
Logger.log('Checking account: ' + account.getName());
AdsManagerApp.select(account);
const reportData = fetchReportData(dateRange);
const accountContent = formatReportData(reportData);
if (accountContent) {
Logger.log('Auto-apply Recommendations have been found in account: ' + account.getName());
}
formattedEmailContent += accountContent;
}
formattedEmailContent += '</body></html>';
if (formattedEmailContent !== '<html><body></body></html>') {
sendEmail(formattedEmailContent, EMAIL_SETTINGS);
} else {
Logger.log("No changes found. Email not sent.");
}
}
function computeDateRange(days) {
const today = new Date();
const lookbackDate = new Date(today.getTime() - (days - 1) * 24 * 60 * 60 * 1000);
const formattedStartDate = Utilities.formatDate(lookbackDate, AdsApp.currentAccount().getTimeZone(), 'yyyyMMdd');
const formattedEndDate = Utilities.formatDate(today, AdsApp.currentAccount().getTimeZone(), 'yyyyMMdd');
return { start: formattedStartDate, end: formattedEndDate };
}
function fetchReportData(dateRange) {
const reportFields = [
'customer.descriptive_name',
'change_event.change_date_time',
'campaign.name',
'ad_group.name',
'change_event.resource_change_operation',
'change_event.change_resource_type',
];
const selectStatement = reportFields.join(', ');
return AdsApp.report(
`SELECT ${selectStatement} ` +
`FROM change_event ` +
`WHERE change_event.change_date_time BETWEEN '${dateRange.start}' AND '${dateRange.end}' AND change_event.user_email = 'Recommendations Auto-Apply' ` +
`ORDER BY change_event.change_date_time DESC ` +
`LIMIT 100`
);
}
function formatReportData(report) {
const fieldMapping = {
'customer.descriptive_name': 'Account name',
'change_event.change_date_time': 'Date and time',
'campaign.name': 'Campaign name',
'ad_group.name': 'Ad group name',
'change_event.resource_change_operation': 'Change type',
'change_event.change_resource_type': 'Change in'
};
let emailContent = '';
let rows = report.rows();
while (rows.hasNext()) {
let row = rows.next();
emailContent += '<div style="border:1px solid #e5e5e5; padding: 10px; margin-bottom: 10px;">';
for (const field in fieldMapping) {
let fieldName = fieldMapping[field];
let fieldValue = field === 'change_event.change_date_time' ? reformatDate(row[field]) : row[field];
emailContent += `<b>${fieldName}</b>: ${fieldValue}<br>`;
}
emailContent += '</div>';
}
return emailContent;
}
function reformatDate(dateTimeString) {
const options = {
year: 'numeric', month: 'long', day: 'numeric',
hour: '2-digit', minute: '2-digit',
hour12: true
};
const dateObj = new Date(dateTimeString);
return dateObj.toLocaleDateString('en-US', options);
}
function sendEmail(content, settings) {
MailApp.sendEmail({
to: settings.RECIPIENT,
subject: settings.SUBJECT,
htmlBody: content
});
}
The script credit goes to: Krzysztof Bycina