Google Ads Slack Alerts
Google Ads Slack Alerts
Google Ads Slack Alerts
// ========================================== // CONFIGURATION VARIABLES // ==========================================
// Insert your Slack Incoming Webhook URL here var SLACK_WEBHOOK_URL = 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX';
// Set your threshold percentage (0.15 = 15%) var THRESHOLD_PERCENTAGE = 0.15;
// Set your preferred currency symbol for the Slack message var ACCOUNT_CURRENCY_SYMBOL = '£';
// ========================================== // MAIN SCRIPT // ==========================================
function main() { var accountName = AdsApp.currentAccount().getName(); var today = new Date();
// 1. Calculate date ranges var last7DaysEnd = new Date(today.getTime() - (1 24 3600 1000)); var last7DaysStart = new Date(today.getTime() - (7 24 3600 1000));
var prev7DaysEnd = new Date(today.getTime() - (8 24 3600 1000)); var prev7DaysStart = new Date(today.getTime() - (14 24 3600 1000));
var lastYear7DaysEnd = new Date(last7DaysEnd); lastYear7DaysEnd.setFullYear(lastYear7DaysEnd.getFullYear() - 1);
var lastYear7DaysStart = new Date(last7DaysStart); lastYear7DaysStart.setFullYear(lastYear7DaysStart.getFullYear() - 1);
// Format dates for the Google Ads API (YYYYMMDD) var strLast7Start = formatDate(last7DaysStart); var strLast7End = formatDate(last7DaysEnd);
var strPrev7Start = formatDate(prev7DaysStart); var strPrev7End = formatDate(prev7DaysEnd);
var strLastYearStart = formatDate(lastYear7DaysStart); var strLastYearEnd = formatDate(lastYear7DaysEnd);
// 2. Retrieve account-level spend data var spendLast7 = getSpend(strLast7Start, strLast7End); var spendPrev7 = getSpend(strPrev7Start, strPrev7End); var spendLastYear = getSpend(strLastYearStart, strLastYearEnd);
// 3. Calculate percentage differences var diffPrev7 = spendPrev7 > 0 ? (spendLast7 - spendPrev7) / spendPrev7 : 0; var diffLastYear = spendLastYear > 0 ? (spendLast7 - spendLastYear) / spendLastYear : 0;
var triggerAlert = false; var alertBlocks = [];
// 4. Evaluate conditions and pull campaign breakdowns if needed if (diffPrev7 > THRESHOLD_PERCENTAGE) { triggerAlert = true; var msg = 'Spend is up ' + (diffPrev7 100).toFixed(2) + '%* compared to the previous 7 days.\n'; msg += getTopSpendersText(strLast7Start, strLast7End, strPrev7Start, strPrev7End); alertBlocks.push(msg); }
if (diffLastYear > THRESHOLD_PERCENTAGE) { triggerAlert = true; var msg = 'Spend is up ' + (diffLastYear 100).toFixed(2) + '%* compared to the same 7 days last year.\n'; msg += getTopSpendersText(strLast7Start, strLast7End, strLastYearStart, strLastYearEnd); alertBlocks.push(msg); }
// 5. Send Slack Alert if (triggerAlert) { var message = '' + accountName + ' Spend Alert\n\n'; message += alertBlocks.join('\n\n') + '\n\n'; message += 'Account Totals:\n'; message += 'Last 7 Days: ' + ACCOUNT_CURRENCY_SYMBOL + spendLast7.toFixed(2) + '\n'; message += 'Previous 7 Days: ' + ACCOUNT_CURRENCY_SYMBOL + spendPrev7.toFixed(2) + '\n'; message += 'Same 7 Days Last Year: ' + ACCOUNT_CURRENCY_SYMBOL + spendLastYear.toFixed(2);
sendSlackMessage(message);
} else { Logger.log('Spend is within normal limits. No alert sent.'); } }
function getTopSpendersText(currentStart, currentEnd, pastStart, pastEnd) { var campaignData = [];
// Only check enabled campaigns to keep the script fast var campaignIterator = AdsApp.campaigns() .withCondition("campaign.status = ENABLED") .get();
while (campaignIterator.hasNext()) { var campaign = campaignIterator.next(); var currentCost = campaign.getStatsFor(currentStart, currentEnd).getCost(); var pastCost = campaign.getStatsFor(pastStart, pastEnd).getCost(); var diff = currentCost - pastCost;
// Only record campaigns that actually increased in spend
if (diff > 0) {
campaignData.push({
name: campaign.getName(),
diff: diff
});
}
}
// Sort by the highest spend increase campaignData.sort(function(a, b) { return b.diff - a.diff; });
// Get the top 3 drivers var limit = Math.min(3, campaignData.length); if (limit === 0) return "No active campaigns found with a spend increase.";
var text = "Top drivers for this increase:\n"; for (var i = 0; i < limit; i++) { text += "• " + campaignData[i].name + " (+" + ACCOUNT_CURRENCY_SYMBOL + campaignData[i].diff.toFixed(2) + ")\n"; }
return text; }
function getSpend(startDate, endDate) { return AdsApp.currentAccount().getStatsFor(startDate, endDate).getCost(); }
function formatDate(date) { var year = date.getFullYear().toString(); var month = (date.getMonth() + 1).toString(); var day = date.getDate().toString();
if (month.length === 1) month = '0' + month; if (day.length === 1) day = '0' + day;
return year + month + day; }
function sendSlackMessage(text) { var payload = { "text": text };
var options = { "method": "post", "contentType": "application/json", "payload": JSON.stringify(payload) };
UrlFetchApp.fetch(SLACK_WEBHOOK_URL, options); Logger.log('Alert sent to Slack successfully.'); }