Advertisement
Marc_Cornelius

Google Ads Script: MCC level Change History

Jul 23rd, 2024
425
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.38 KB | None | 0 0
  1. /**
  2. * MCC Level Change History Alerts
  3. *
  4. * This script checks the change history of all accounts under a Google Ads MCC,
  5. * and sends an alert via email if a change is made by a user not in the 'recognized' users list.
  6. */
  7.  
  8. // Configuration Settings
  9. var SPREADSHEET_URL = "[SPREADSHEET URL]";
  10. var EMAIL_ADDRESSES = "[EMAIL ADDRESS LIST]";
  11. var IGNORE_USERS = ['[USER1]', '[USER2]', '[USER3]'];
  12.  
  13. var SEND_EMAIL = true;
  14. var EMAIL_SUBJECT = "[GAds Script] - WARNING - Change by person outside of organisation";
  15. var PERIOD = "YESTERDAY";
  16.  
  17. var EMAIL_BODY =
  18. "\n"+
  19. "***\n"+
  20. "\n"+
  21. "This script checks changes in the 'Change history':\n"+
  22. "\n"+
  23. "For all changes during "+PERIOD+" \n"+
  24. " check if there is a change being made by users other than "+IGNORE_USERS+" \n"+
  25. " if so, alerts are logged in Google Sheet: "+SPREADSHEET_URL+" \n"+
  26. "\n"+
  27. "If there is an alert an email is sent to:\n"+ EMAIL_ADDRESSES +"\n";
  28.  
  29. function processAccounts() {
  30. var accountSelector = AdsManagerApp.accounts();
  31. var accountIterator = accountSelector.get();
  32.  
  33. while (accountIterator.hasNext()) {
  34. var account = accountIterator.next();
  35. AdsManagerApp.select(account);
  36. main();
  37. }
  38. }
  39.  
  40. function main() {
  41. Logger.log("Processing account: "+AdsApp.currentAccount().getName());
  42. var changeAlerts = getChangeAlerts();
  43.  
  44. if (changeAlerts.length > 0) {
  45. reportResults(changeAlerts);
  46. sendEmail(changeAlerts.length);
  47. } else {
  48. Logger.log("No changes found in change history made by unauthorized users\n");
  49. logNoChanges();
  50. }
  51. }
  52.  
  53. function logNoChanges() {
  54. var spreadsheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
  55. var sheet = spreadsheet.getActiveSheet();
  56. var today = new Date();
  57. sheet.appendRow([Utilities.formatDate(today, AdsApp.currentAccount().getTimeZone(), "yyyy-MM-dd"), "No changes made by unauthorized users"]);
  58. }
  59.  
  60. function getChangeAlerts() {
  61. var accountName = AdsApp.currentAccount().getName();
  62. var changes = [];
  63. var query = "SELECT " +
  64. "campaign.name, " +
  65. "ad_group.name, " +
  66. "change_event.change_date_time, " +
  67. "change_event.change_resource_type, " +
  68. "change_event.changed_fields, " +
  69. "change_event.client_type, " +
  70. "change_event.feed, " +
  71. "change_event.feed_item, " +
  72. "change_event.new_resource, " +
  73. "change_event.old_resource, " +
  74. "change_event.resource_change_operation, " +
  75. "change_event.resource_name, " +
  76. "change_event.user_email " +
  77. "FROM change_event " +
  78. "WHERE change_event.change_date_time DURING "+PERIOD+" " +
  79. "AND change_event.user_email NOT IN ('"+IGNORE_USERS.join("', '")+"') "+
  80. "ORDER BY change_event.change_date_time DESC "+
  81. "LIMIT 9999 ";
  82.  
  83. var result = AdsApp.search(query);
  84.  
  85. while (result.hasNext()) {
  86. var row = result.next();
  87. var campaignName = "";
  88. var adGroupName = "";
  89. try {
  90. campaignName = row.campaign.name;
  91. adGroupName = row.adGroup.name;
  92. } catch(e) {
  93. }
  94.  
  95. try {
  96. var change = [
  97. row.changeEvent.changeDateTime,
  98. accountName,
  99. row.changeEvent.userEmail,
  100. row.changeEvent.clientType,
  101. campaignName,
  102. adGroupName,
  103. row.changeEvent.changeResourceType,
  104. row.changeEvent.changedFields,
  105. row.changeEvent.feed,
  106. row.changeEvent.feedItem,
  107. row.changeEvent.newResource,
  108. row.changeEvent.oldResource,
  109. row.changeEvent.resourceChangeOperation
  110. ];
  111. changes.push(change);
  112.  
  113. } catch(e) {
  114. Logger.log("Issue with parsing results from search API: "+e);
  115. }
  116. }
  117. return changes;
  118. }
  119.  
  120. function reportResults(changes) {
  121. var sheet = prepareOutputSheet();
  122. addOutputToSheet(changes, sheet);
  123. }
  124.  
  125. function prepareOutputSheet() {
  126. var spreadsheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
  127. var sheet = spreadsheet.getActiveSheet();
  128. var numberOfRows = sheet.getLastRow();
  129.  
  130. if (numberOfRows == 0) {
  131. addHeaderToOutputSheet(sheet);
  132. }
  133. return sheet;
  134. }
  135.  
  136. function addHeaderToOutputSheet(sheet) {
  137. var header = [
  138. "date",
  139. "account",
  140. "user",
  141. "clientType",
  142. "campaignName",
  143. "adGroupName",
  144. "changeResourceType",
  145. "changedFields",
  146. "feed",
  147. "feedItem",
  148. "newResource",
  149. "oldResource",
  150. "resourceChangeOperation"
  151. ];
  152. sheet.appendRow(header);
  153. }
  154.  
  155. function addOutputToSheet(output, sheet) {
  156. var numberOfRows = sheet.getLastRow();
  157. sheet.insertRowsBefore(2, output.length);
  158. var startRow = 2;
  159. var range = sheet.getRange(startRow, 1, output.length, output[0].length);
  160. range.setValues(output);
  161. Logger.log("\nNumber of rows added to output sheet: "+output.length+"\n\n");
  162. }
  163.  
  164. function sendEmail(numberOfalerts) {
  165. var accountName = AdsApp.currentAccount().getName();
  166. if (SEND_EMAIL) {
  167. var emailBody =
  168. "Number of changes: " + numberOfalerts + "\n" +
  169. "See details: "+ SPREADSHEET_URL+ "\n" + EMAIL_BODY;
  170. MailApp.sendEmail(EMAIL_ADDRESSES, EMAIL_SUBJECT+" | "+accountName, emailBody);
  171. Logger.log("Sending alert mail");
  172. }
  173. }
  174.  
  175. // Run processAccounts function to execute the script across all accounts managed by the MCC
  176. processAccounts();
  177.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement