
пн, 2 червня 2025 р.
Ця стаття, як і велика частина інших з цього блогу, з'явилась випадково - завдяки запитанню в чаті.
Минулого тижня в нашому закритому чаті курсу PRO ANALYTICS Lena Kolisnyk задала питання: "Чи можна експортувати до Google Sheets інформацію про анотації з GA4, щоб в подальшому виводити ці дані у власні звіти?" Готового рішення ні я, ні студенти не згадали.
Але близько місяця назад в LinkedIn, а потім і в нашому внутрішньому чаті ProAnalytics.Team я зустрів рішення від Tamás Geiger, яке дозволяє автоматично створювати анотації в GA4 при публікації версій в GTM з допомогою Google App Script.
"Якщо можна створити анотації через API, то можна і отримати їх перелік" - подумав я і написав досить простий скрипт, який зчитує дані анотацій з GA4 і складає їх до Google Sheet, щоб в подальшому ви могли виводити їх в свої звіти Looker, Power BI чи Tableau. Ну або для будь-яких інших цілей.
Чесно кажучи, написання самого рішення зайняло в декілька разів менше часу, ніж його опис на блозі.
Пункти, які вам потрібно буде виконати:
Це найпростіший етап. Перейдіть у свій Google Drive та створіть новий Google Spreadsheet (назвемо його умовно “GA4 Annotations”). У меню зверху оберіть
Extensions → Apps Script. Відкриється середовище Google Apps Script, прив’язане до вашого Spreadsheet.
Наш скрипт використовуватиме Advanced Service “Google Analytics Admin API”, тому спершу потрібно активувати цей API в Google Cloud, а потім підключити до нашого
скрипта. Якщо у вас вже є проєкт GCP, можна скористатися ним. Якщо ні - доведеться створити новий.
Вибравши потрібний проект у боковому меню зліва, оберіть APIs & Services → Library.

Використовуючи пошук, знайдіть Google Analytics Admin API → відкрийте його → натисніть Enable. Це дасть змогу викликати кінцеві точки ReportingDataAnnotations.

Поверніться в редактор Apps Script (той, що відкрився з вашого Google Sheet). І у меню зліва натисніть на значок «+» поруч із “Services”).

У списку знайдіть Google Analytics Admin API. Натисніть «Add».

Після цього у файлі appsscript.json автоматично додасться запис про advanced service. Вам також знадобиться додати OAuth-скоп (analytics.readonly та spreadsheets) у ваш appsscript.json .
Щоб відкрити appsscript.json у лівій частині редактора натисніть на іконку Project Settings (шестерня) та знайдіть у вікні налаштувань пункт Show “appsscript.json” manifest file in editor і поставте чекбокс.

Закрийте вікно налаштувань. Тепер у списку файлів зліва з’явиться новий файл appsscript.json (поряд із Code.gs ).

Фінально appsscript.json має виглядати так:
{
  "timeZone": "Europe/Kyiv",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "dependencies": {
    "enabledAdvancedServices": [
      {
        "userSymbol": "AnalyticsAdmin",
        "serviceId": "analyticsadmin",
        "version": "v1alpha"
      }
    ]
  },
  "oauthScopes": [
    "https://www.googleapis.com/auth/analytics.readonly",
    "https://www.googleapis.com/auth/spreadsheets"
  ]
}Підготовча робота майже завершена. Залишилось додати код основної функції і все. Саме вона відповідальна за:
Додайте у Apps Script новий файл Code.gs (якщо його ще немає) та вставте такий код.
Обов'язково збережіть скрипт (натисніть іконку дискетки або Ctrl+S).

/**
 * Maks Hapchuk https://www.linkedin.com/in/maks-hapchuk/
 * 
 * Main function: fetches all annotations from a GA4 Property and writes them to a Google Sheet.
 */
function fetchGA4AnnotationsToSheet() {
  // Replace with your GA4 Property ID (numbers only, without the "properties/" prefix)
  var PROPERTY_ID = '253674377';
  
  // Construct the parent resource string: "properties/<PROPERTY_ID>"
  var parent = 'properties/' + PROPERTY_ID;
  
  // Call the list() method from the AnalyticsAdmin Advanced Service
  var response;
  try {
    response = AnalyticsAdmin.Properties.ReportingDataAnnotations.list(parent);
  } catch (e) {
    throw new Error(
      'Failed to fetch annotations from GA4. ' +
      'Verify that PROPERTY_ID is correct and that you have access to the Analytics Admin API.'
    );
  }
  
  // Extract the array of annotations
  var annotations = response.reportingDataAnnotations || [];
  
  // Access the active spreadsheet and locate (or create) the "Annotations" sheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheetName = 'Annotations';
  var sheet = ss.getSheetByName(sheetName);
  if (!sheet) {
    sheet = ss.insertSheet(sheetName);
  } else {
    sheet.clearContents();
  }
  
  // Write column headers
  var headers = ['Title', 'Description', 'Start Date', 'End Date', 'Color'];
  sheet.appendRow(headers);
  
  // Make the header row bold
  sheet.getRange(1, 1, 1, headers.length).setFontWeight('bold');
  
  // If there are no annotations, stop execution
  if (annotations.length === 0) {
    return;
  }
  
  // Loop through each annotation and append a row to the sheet
  annotations.forEach(function(annotation) {
    var title = annotation.title || '';
    var description = annotation.description || '';
    
    // Determine whether this annotation has a single date or a date range
    var startDate = '';
    var endDate = '';
    
    if (annotation.annotationDate) {
      // Single-date annotation
      startDate = formatDateObject(annotation.annotationDate);
      endDate = startDate;
    } else if (annotation.annotationDateRange) {
      // Multi-date annotation
      startDate = formatDateObject(annotation.annotationDateRange.startDate);
      if (annotation.annotationDateRange.endDate) {
        endDate = formatDateObject(annotation.annotationDateRange.endDate);
      } else {
        endDate = startDate;
      }
    }
    
    var color = annotation.color || '';
    sheet.appendRow([title, description, startDate, endDate, color]);
  });
}
/**
 * Helper function: formats an object {year, month, day} into "YYYY-MM-DD"
 */
function formatDateObject(obj) {
  var year = obj.year.toString();
  var month = (obj.month < 10 ? '0' : '') + obj.month.toString();
  var day = (obj.day < 10 ? '0' : '') + obj.day.toString();
  return year + '-' + month + '-' + day;
}УВАГА:
var PROPERTY_ID = '111111111111';на свій реальний GA4 Property ID.
Щоб знайти Property ID: зайдіть у GA4 → Admin → У стовпці “Property” (Властивість) → Property details (Налаштування властивості)

При першому запуску будь-якої функції з Apps Script, яка потребує доступу до зовнішніх API або до вашого Spreadsheet, Google попросить вас авторизувати скрипт. Щоб це зробити у редакторі Apps Script виберіть у випадаючому списку функцій (біля → “Run”) функцію fetchGA4AnnotationsToSheet та натисніть → Run.



Після успішної авторизації скрипт виконається, і у вашому Spreadsheet має з’явитися лист “Annotations” із набором колонок:

і всіма вашими GA4 анотаціями у рядках нижче.

Звісно, запускати щодня руками цей скрипт було б не набагато кращим рішенням, ніж копіювати анотації з інтерфейсу GA4 вручну, тому давайте налаштуємо так, щоб скрипт автоматично запускався щодня й оновлював дані.
У редакторі Apps Script (де ви писали код) у лівому бічному меню виберіть Triggers. Та натисніть + Add Trigger (Додати тригер).

У формі створення тригеру налаштуйте так:
fetchGA4AnnotationsToSheet.
Ось і все. Тепер інформація про нові анотації щодня автоматично потраплятиме в ваш файл.
Сподіваюся, цей спосіб підтягувати анотації з GA4 у Google Sheets і далі — в будь-які звіти чи дашборди — допоможе вам зробити дані в ваших репортах більш прозорими, а рішення, які на них приймаються, ще більш зваженими.
Якщо ви помітили баг, у вас з'явилась ідея покращення цього рішення, або ви просто хочете подякувати - коментарі завжди відкриті для вас.

Вебаналітик, Маркетолог