Phát Hiện Sự Bất Thường Trong Chi Tiêu Chiến Dịch Với Tập Lệnh Này Của Quảng Cáo Google
Quảng cáo Google bội chi hoặc thiếu chi tiêu trong tài khoản có thể được kiểm tra bằng cách tìm các thay đổi trong chi tiêu với tập lệnh được chia sẻ dưới đây bởi Daniel Gilbert.
Bạn đã bao giờ có một chiến dịch tiêu tốn phần ngân sách nhiều hơn bạn nghĩ hay chưa? Không ai thích các chiến dịch của mình ở dưới mức chi tiêu, chứ đừng nói đến bội chi. Nếu một thay đổi hoặc vấn đề xuất hiện trong kế hoạch chi tiêu cho Quảng cáo Google, tốt nhất là bạn nên được thông báo về điều đó ngay từ khi phát sinh.
Đây là tập lệnh có thể tùy chỉnh cho phép bạn kiểm tra hành vi bất thường trong tài khoản của mình bằng cách tìm các thay đổi trong chi tiêu. Nó lấy chi tiêu trung bình của các chiến dịch riêng lẻ trong một khoảng thời gian đã chọn và so sánh nó với chi tiêu vào chiến dịch hiện thời. Nếu chi tiêu cho ngày hiện tại cao hơn so với tỷ lệ phần trăm được chỉ định, nó sẽ gửi một email cảnh báo tới cho bạn.
Có nhiều cách để sửa đổi tập lệnh này. Ví dụ: Bạn có thể cho tập lệnh biết ngưỡng nào của sự thay đổi tỷ lệ phần trăm để thông báo email. Bằng cách này, bạn sẽ biết khi nào có sự tăng hay giảm chi tiêu. Bạn có thể chọn số ngày áp dụng tính toán để tạo trung bình chi tiêu lịch sử . Chọn thời gian trong ngày để tập lệnh bắt đầu việc thu thập dữ liệu. Và bạn cũng có thể đặt giá trị cảnh báo tối thiểu để tránh bị làm phiền chỉ vì những thay đổi nhỏ trong các chiến dịch.
Cách thức hoạt động của tập lệnh
Hãy bắt đầu và xem cách nó hoạt động.
- Điền vào các biến ở đầu tập lệnh (bên dưới) theo nhu cầu và đặc điểm quảng cáo Google của bạn. Bạn cần thêm các địa chỉ email bạn muốn gửi thông báo và các chiến dịch mà tập lệnh cần lấy dữ liệu.
- Khi bạn đã ủy quyền tập lệnh quảng cáo Google và xác nhận nó hoạt động với bản chạy thử, hãy lên lịch để chạy hàng giờ nếu bạn có thể kiểm tra chi tiêu mỗi giờ.
Hệ Sinh Thái Display Advertising (P.1)
Dưới đây là một số lưu ý cần biết về tập lệnh:
- Tập lệnh ghi lại thời gian chạy trong ngày và lấy số chi tiêu trung bình từ các chiến dịch được chọn cho đến thời điểm hiện tại.
- Tập lệnh so sánh mức trung bình này với chi tiêu hiện tại.
- Nếu chi tiêu hiện tại vượt quá ngưỡng chỉ định, nó sẽ thông báo cho bạn bằng email.
Sơ lược về tập lệnh
Để sử dụng tập lệnh này, bạn cần truy cập tài khoản của mình trong giao diện Quảng cáo Google, đến mục Hành động hàng loạt, chọn Tập lệnh, sau đó tạo tập lệnh mới và dán vào bên dưới. Đừng quên chỉnh sửa các tùy chọn dưới đây.
- “campaignNameContains” và “campaignNameDoesNotContain” là bộ lọc xác định các chiến dịch được chọn và không được chọn mà tập lệnh sẽ lấy dữ liệu. Ví dụ: nếu “campaignNameContains” là [“Brand”, “Generic”] thì dữ liệu được lấy chỉ từ các chiến dịch trong tên có chứa “brand” or “generic” . Nếu “campaignNameDoesNotContain” là [“Display”, “Competitor”], thì bất kỳ chiến dịch nào có tên chứa từ “Display” hoặc “Competitor” đều được bỏ qua.
- Đây không phải là các thông tin chủ đạo.
- Để trống [ ] nếu chọn tất cả các chiến dịch.
- Nếu bạn cần đặt một trích dẫn kép vào “campaignNameContains” hoặc “campaignNameDoesNotContain”, hãy đặt dấu gạch chéo trước nó.
- “addressesToNotify” là một loạt các địa chỉ email sẽ nhận được thông báo nếu chi tiêu vượt quá ngưỡng chỉ định. Chúng phải nằm trong danh sách được phân tách bằng dấu phẩy bên trong dấu ngoặc vuông. Ví dụ: [“dan@example.com”].
- “percentageDifferenceSpend” là ngưỡng thay đổi tỷ lệ phần trăm mà bạn chỉ định. Ví dụ: 10 có nghĩa là bạn sẽ được thông báo khi có thay đổi lớn hơn 10% (cho dù đó là tăng 10% hay giảm 10%). Con số này phải là số dương và lớn hơn không.
- Nếu một chiến dịch có lượng chi tiêu thấp, thì sự thay đổi của một vài đô la cũng sẽ tạo thành sự thay đổi tỷ lệ phần trăm lớn. Để tránh bị cảnh báo về những thay đổi nhỏ này trong các chiến dịch quảng cáo Google có chi tiêu thấp, bạn có thể đặt mức “averageSpendMinimumThreshold”. Nếu chi tiêu trung bình của một chiến dịch trong quá khứ nằm dưới ngưỡng này, thì những thay đổi trong chi tiêu của chiến dịch hiện tại sẽ bị bỏ qua.
- Đây là một số tiền tuyệt đối, với đơn vị tiền tệ giống với tài khoản của bạn. Ví dụ: nếu tài khoản của bạn sử dụng đô la, thì 100 có nghĩa là 100 đô la.
- Nó phải lớn hơn không.
- Lưu ý: Điều này cũng có nghĩa là bạn sẽ không được cảnh báo khi chiến dịch quảng cáo Google tạm dừng hoặc không có chi tiêu chiến dịch nào trước đó được kích hoạt, vì bất kể số tiền chi tiêu hôm nay là bao nhiêu thì đều dưới mức chi tiêu quá khứ (bằng không).
- Vì chi tiêu có thể thấp vào buổi sáng, điều này cũng có nghĩa là những thay đổi nhỏ trong chi tiêu có thể là những thay đổi phần trăm lớn. Bạn có nhiều khả năng đang ngủ và không chú ý đến email của mình. Bạn có thể đặt “earliestHour” là giờ mà bạn muốn tập lệnh chạy và nó sẽ không chạy sớm hơn giờ bạn đã đặt. Tập lệnh sẽ chờ đến thời gian đó để bắt đầu tích lũy dữ liệu trong ngày. Đây là giờ trong múi giờ tài khoản quảng cáo Google của bạn.
Ngoài ra còn có một cài đặt nâng cao:
- “timePeriod” là số ngày được sử dụng để lấy dữ liệu chi tiêu trung bình trong lịch sử. Mặc định là 7, có nghĩa là tập lệnh sẽ lấy dữ liệu trung bình trong một tuần, nhưng bạn có thể thay đổi thành số ngày tùy chỉnh.
- Giá trị này phải lớn hơn 1.
Lưu ý với tập lệnh Quảng cáo Google
Tập lệnh chỉ xem xét các chiến dịch quảng cáo Google đang diễn ra, vì vậy bạn sẽ không được cảnh báo khi chiến dịch đột nhiên ngừng chi tiêu vì nó bị tạm dừng.
Nếu bạn gặp sự cố với việc hết thời gian tập lệnh, bạn có thể thử bản sao của tập lệnh mà mỗi tập tin sẽ xem xét các chiến dịch khác nhau, sử dụng cài đặt “Tên chiến dịch chứa” và “Tên chiến dịch không chứa” trong chiến dịch quảng cáo Google của mình.
6 màu sắc dự báo “thống trị” năm 2019
Tập lệnh quảng cáo Google
/**
*
* Change in Campaign Spending Alert
*
* This script uses the current hour to calculate how much has been spent on
* individual campaigns on the day of running. The average spend up to the
* current hour in a specified numbers of days previously is averaged. If the
* spend today is higher by a specified percentage threshold an alert email
* is sent.
*
* There is a 20 minute delay between events occurring and the data being
* available in AdWords. This script should be scheduled to run after 20
* past the hour.
*
* Version: 1.0
* Google AdWords Script maintained on brainlabsdigital.com
*
**/
function main() {
//////////////////////////////////////////////////////////////////////////////
// Options
var campaignNameDoesNotContain = [];
// Use this if you want to exclude some campaigns.
// For example [“Display”] would ignore any campaigns with ‘Display’ in the name,
// while [“Display”,”Shopping”] would ignore any campaigns with ‘Display’ or
// ‘Shopping’ in the name.
// Leave as [] to not exclude any campaigns.
var campaignNameContains = [];
// Use this if you only want to look at some campaigns.
// For example [“Brand”] would only look at campaigns with ‘Brand’ in the name,
// while [“Brand”,”Generic”] would only look at campaigns with ‘Brand’ or ‘Generic’
// in the name.
// Leave as [] to include all campaigns.
var addressesToNotify = [];
// An array of email addresses to send alerts to, example usage:
// [‘ron@gryffindor.hogwarts.ac.uk’, ‘hermione@gryffindor.hogwarts.ac.uk’]
// [‘luna@ravenclaw.hogwarts.ac.uk’]
//////////////////////////////////////////////////////////////////////////////
// Thresholds
var percentageDifferenceSpend = 10;
// The positive or negative percentage change in spend must be greater than
// this number for an alert to be sent. eg 10 means greater than a positive or negative
// 10% change. The variable must be positive.
var averageSpendMinimumThreshold = 100.00;
// This value sets a minimum value that the average historic spend should be
// for it to be compared to today’s spend. This number must be greater than 0.
var earliestHour = 7;
// Restricts the script to run only after a certain hour of the day so that a
// significant amount of data can be gathered. This number should be 0 – 23.
//////////////////////////////////////////////////////////////////////////////
// Advanced settings
var timePeriod = 7;
// The default time period averages the previous 7 days of spending. This number
// must be greater than 0.
//////////////////////////////////////////////////////////////////////////////
// The actual code starts here
// Validate input
var validated = validateInput(
addressesToNotify,
percentageDifferenceSpend,
averageSpendMinimumThreshold,
earliestHour,
timePeriod
);
if (validated !== true) {
throw validated;
}
// Create date strings for AWQL query and data comparison
var dates = makeDates(timePeriod);
// Check if it’s too early to run the script or not
if (dates.currentHour < earliestHour) {
Logger.log(‘Too early for code, need coffee.’);
return;
}
// Get the IDs of the campaigns to look at
var ignorePausedCampaigns = true;
var activeCampaignIds = getCampaignIds(campaignNameDoesNotContain, campaignNameContains, ignorePausedCampaigns);
// Construct the AWQL query using the campaign IDs and dates
var query = constructQuery(activeCampaignIds, dates);
var queryReport = AdWordsApp.report(query);
// Calculate sum of spend today and historically by campaign ID
var costs = calculateCostByCampaign(queryReport, dates);
Logger.log(“Got the costs for all campaigns”);
// Generate a dictionary of overspending campaigns
var overSpendingCampaigns = checkPercentageChange(costs, averageSpendMinimumThreshold, timePeriod, percentageDifferenceSpend);
// Do nothing if there are no overspending campaigns
if (Object.keys(overSpendingCampaigns).length === 0) {
Logger.log(‘No overspending campaigns.’);
return;
}
Logger.log(‘Overspending campaigns: ‘ + JSON.stringify(overSpendingCampaigns));
// Notify contacts if there are overspending campaigns
notifyContact(addressesToNotify, overSpendingCampaigns, averageSpendMinimumThreshold);
Logger.log(“Email sent.”);
}
function validateInput(addressesToNotify,
percentageDifferenceSpend,
averageSpendMinimumThreshold,
earliestHour,
timePeriod
) {
if (addressesToNotify.length === 0) {
return ‘Please provide at least one email address to notify.’;
}
if (percentageDifferenceSpend <= 0) {
return ‘Please provide a positive percentage difference spend.’;
}
if (averageSpendMinimumThreshold <= 0) {
return ‘Please provide a positive average spend minimum threshold.’;
}
if (earliestHour > 23 | earliestHour < 0) {
return ‘Please provide an earliest hour between 0 and 23 inclusive.’
}
if (timePeriod < 1) {
return ‘Please provide a time period of at least one day.’
}
return true;
}
function notifyContact(addresses, overSpendingCampaigns, threshold) {
var accountName = AdWordsApp.currentAccount().getName();
var subject = accountName + ‘ | Spend Checker Script | Campaigns have exceeded your spend change threshold.’;
var body = ‘The following campaigns have exceeded the ‘ + threshold + ‘% spend threshold:\n\n’;
var campaignIds = Object.keys(overSpendingCampaigns);
for (var i = 0; i < campaignIds.length; i++) {
var campaignId = campaignIds[i];
var campaign = overSpendingCampaigns[campaignId];
var campaignName = campaign.campaignName;
var percentageChange = campaign.percentageChange.toFixed(2);
var spendToday = campaign.today.toFixed(2);
body += (i+1) + ‘. \nName: ‘ + campaignName + ‘\n’ +
‘ID: ‘ + campaignId + ‘\n’ +
‘Change(%): ‘ + percentageChange + ‘\n’ +
‘Spend today (£): ‘ + spendToday + ‘\n\n’;
}
MailApp.sendEmail(addresses.join(‘,’), subject, body);
}
function checkPercentageChange(costs, spendThreshold, timePeriod, percentageThreshold) {
var campaignIds = Object.keys(costs);
return campaignIds.reduce(function(overspendingCampaigns, campaignId){
var campaign = costs[campaignId];
var averageSpend = campaign.sumTimePeriod / timePeriod;
var spendToday = campaign.today;
if(averageSpend < spendThreshold){
return overspendingCampaigns;
}
var percentageChange = ((spendToday – averageSpend) / averageSpend) * 100;
if (Math.abs(percentageChange) > percentageThreshold) {
campaign[‘percentageChange’] = percentageChange;
overspendingCampaigns[campaignId] = campaign;
}
return overspendingCampaigns;
}, {});
}
function makeDates(timePeriod) {
var millisPerDay = 1000 * 60 * 60 * 24;
var timeZone = AdWordsApp.currentAccount().getTimeZone();
var now = new Date();
var dateInPast = new Date(now – ((timePeriod + 1) * millisPerDay));
var todayHyphenated = Utilities.formatDate(now, timeZone, ‘yyyy-MM-dd’);
var todayFormatted = todayHyphenated.replace(/-/g, ”);
var currentHour = Utilities.formatDate(now, timeZone, ‘H’);
var dateInPastFormatted = Utilities.formatDate(dateInPast, timeZone, ‘yyyyMMdd’);
return {
‘todayHyphenated’: todayHyphenated,
‘todayFormatted’: todayFormatted,
‘dateInPastFormatted’: dateInPastFormatted,
‘currentHour’: currentHour,
};
}
function constructQuery(activeCampaignIds, dates) {
var currentHour = dates.currentHour;
var todayFormatted = dates.todayFormatted;
var dateInPastFormatted = dates.dateInPastFormatted;
var query =
‘SELECT CampaignName, CampaignId, Cost, HourOfDay, Date ‘ +
‘FROM CAMPAIGN_PERFORMANCE_REPORT ‘ +
‘WHERE CampaignId IN [‘ + activeCampaignIds.join(‘,’) + ‘] ‘ +
‘AND CampaignStatus = ENABLED ‘ +
‘AND HourOfDay < ‘ + currentHour + ‘ ‘ +
‘DURING ‘ + dateInPastFormatted + ‘,’ + todayFormatted;
Logger.log(‘AWQL Query: ‘ + query);
return query;
}
function calculateCostByCampaign(report, dates) {
var reportRows = report.rows();
var costs = {};
while(reportRows.hasNext()) {
var row = reportRows.next();
var cost = parseFloat(row.Cost);
var campaignId = row.CampaignId;
if (costs[campaignId] === undefined) {
costs[campaignId] = {
‘today’: 0,
‘sumTimePeriod’: 0,
‘campaignName’: row.CampaignName,
}
}
if (row.Date === dates.todayHyphenated) {
costs[campaignId].today += cost;
} else {
costs[campaignId].sumTimePeriod += cost;
}
}
return costs;
}
function getCampaignIds(campaignNameDoesNotContain, campaignNameContains, ignorePausedCampaigns) {
var whereStatement = “WHERE “;
var whereStatementsArray = [];
var campaignIds = [];
if (ignorePausedCampaigns) {
whereStatement += “CampaignStatus = ENABLED “;
} else {
whereStatement += “CampaignStatus IN [‘ENABLED’,’PAUSED’] “;
}
for (var i=0; i<campaignNameDoesNotContain.length; i++) {
whereStatement += “AND CampaignName DOES_NOT_CONTAIN_IGNORE_CASE ‘” + campaignNameDoesNotContain[i].replace(/”/g,’\\\”‘) + “‘ “;
}
if (campaignNameContains.length == 0) {
whereStatementsArray = [whereStatement];
} else {
for (var i=0; i<campaignNameContains.length; i++) {
whereStatementsArray.push(whereStatement + ‘AND CampaignName CONTAINS_IGNORE_CASE “‘ + campaignNameContains[i].replace(/”/g,’\\\”‘) + ‘” ‘);
}
}
for (var i=0; i<whereStatementsArray.length; i++) {
var campaignReport = AdWordsApp.report(
“SELECT CampaignId ” +
“FROM CAMPAIGN_PERFORMANCE_REPORT ” +
whereStatementsArray[i] +
“DURING LAST_30_DAYS”);
var rows = campaignReport.rows();
while (rows.hasNext()) {
var row = rows.next();
campaignIds.push(row[‘CampaignId’]);
}
}
if (campaignIds.length == 0) {
throw(“No campaigns found with the given settings.”);
}
Logger.log(campaignIds.length + ” campaigns found”);
return campaignIds;
}