SEO-ракета: Як автоматизувати перевірку позицій через Google Apps Script
Для маленького сайту платні сервіси моніторингу позицій часто коштують занадто дорого для свого етапу. Коли проєкт тільки росте, хочеться бачити реальні дані, а не одразу закладати щомісячний бюджет на великий SEO-комбайн. Саме тут і починається логіка SEO-ракети: швидко зібрати власний інструмент контролю без зайвих витрат, але з користю для технічного SEO та щоденної звітності.

Хороша новина в тому, що для цього достатньо зв’язки Google Apps Script, Google Sheets і даних із Search Analytics API. Ви отримуєте контроль над кліками, середньою позицією та запитами прямо у своїй таблиці. А коли все запрацює, цей самий підхід легко масштабувати далі: додати окремі звіти, автоматичні сповіщення або нові SEO-показники.
Чому Google Apps Script для SEO працює так добре
Google Apps Script для SEO підходить для старту з дуже простої причини: він не вимагає окремого сервера, складної інфраструктури чи нових платних сервісів. Скрипт живе прямо всередині Google Таблиці, а значить ним зручно користуватися навіть тим, хто ніколи не писав великий код.
Ще один плюс — автоматизація Google Search Console дає дані не “зі сторони”, а напряму з вашого акаунта. Це означає, що ви бачите реальні запити, кліки та середню позицію саме свого сайту. Для малого бізнесу або нового SEO-проєкту цього вже достатньо, щоб перестати працювати навмання і почати дивитися на цифри.
Що потрібно перед стартом
Підготовка займає буквально кілька хвилин:
- доступ до потрібного ресурсу в Google Search Console;
- порожня Google Таблиця;
- базове право редагування скрипта у вашому Google-акаунті.
Після цього відкрийте таблицю та перейдіть у меню Розширення → Apps Script. Там буде ваш редактор. Далі у лівому меню відкрийте Services і додайте Search Console. Це важливий крок: без нього скрипт не зможе звертатися до API напряму.


Що саме робитиме скрипт
Логіка тут проста й зрозуміла навіть без досвіду в розробці. Скрипт:
- бере дані по запитах за обраний період;
- записує у Google Sheets query, clicks, impressions, ctr і position;
- окремо витягує динаміку по днях;
- будує лінійний графік;
- може запускатися автоматично раз на тиждень або раз на місяць.
Тобто ви отримуєте не просто разове вивантаження, а маленьку систему звітності у Google Sheets, яка оновлюється сама.
Порада
Для першого запуску не ускладнюйте звіт. Достатньо двох аркушів: один для запитів, другий для динаміки по днях.
Застереження
Середня позиція в Search Console — це усереднений показник, а не “місце сайту прямо зараз”. Його потрібно читати як аналітичний сигнал, а не як ручну перевірку видачі.
Готовий код для Google Таблиць
Нижче — повністю готовий скрипт. Вам потрібно лише:
1. вставити його в редактор Apps Script;
2. замінити значення SITE_URL на свій ресурс із Search Console;
3. запустити функцію updateSeoRocket();
4. дозволити доступи при першому запуску.
const SITE_URL = 'https://example.com/';
const QUERY_SHEET = 'GSC Queries';
const TREND_SHEET = 'GSC Trend';
const DASHBOARD_SHEET = 'GSC Dashboard';
const DAYS_BACK = 30;
const QUERY_LIMIT = 100;
function updateSeoRocket() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const querySheet = getOrCreateSheet_(ss, QUERY_SHEET);
const trendSheet = getOrCreateSheet_(ss, TREND_SHEET);
writeQueryReport_(querySheet);
writeTrendReport_(trendSheet);
buildTrendChart_(ss, trendSheet);
}
function writeQueryReport_(sheet) {
sheet.clear();
const range = getDateRange_(DAYS_BACK);
const request = {
startDate: range.startDate,
endDate: range.endDate,
dimensions: ['query'],
rowLimit: QUERY_LIMIT,
dataState: 'final'
};
const response = SearchConsole.Searchanalytics.query(request, SITE_URL);
const rows = response.rows || [];
const values = [
['Запит', 'Кліки', 'Покази', 'CTR', 'Середня позиція', 'Дата оновлення']
];
rows.forEach(row => {
const query = row.keys && row.keys[0] ? row.keys[0] : '';
const clicks = row.clicks || 0;
const impressions = row.impressions || 0;
const ctr = row.ctr || 0;
const position = row.position || 0;
values.push([
query,
clicks,
impressions,
ctr,
position,
new Date()
]);
});
if (values.length === 1) {
values.push(['Немає даних за вибраний період', '', '', '', '', new Date()]);
}
sheet.getRange(1, 1, values.length, values[0].length).setValues(values);
sheet.getRange(2, 4, Math.max(values.length - 1, 1), 1).setNumberFormat('0.00%');
sheet.getRange(2, 5, Math.max(values.length - 1, 1), 1).setNumberFormat('0.00');
sheet.autoResizeColumns(1, values[0].length);
sheet.setFrozenRows(1);
}
function writeTrendReport_(sheet) {
sheet.clear();
const range = getDateRange_(DAYS_BACK);
const request = {
startDate: range.startDate,
endDate: range.endDate,
dimensions: ['date'],
rowLimit: DAYS_BACK,
dataState: 'final'
};
const response = SearchConsole.Searchanalytics.query(request, SITE_URL);
const rows = response.rows || [];
const values = [
['Дата', 'Кліки', 'Покази', 'CTR', 'Середня позиція']
];
rows.forEach(row => {
const date = row.keys && row.keys[0] ? row.keys[0] : '';
values.push([
date,
row.clicks || 0,
row.impressions || 0,
row.ctr || 0,
row.position || 0
]);
});
if (values.length === 1) {
values.push(['Немає даних', '', '', '', '']);
}
sheet.getRange(1, 1, values.length, values[0].length).setValues(values);
sheet.getRange(2, 4, Math.max(values.length - 1, 1), 1).setNumberFormat('0.00%');
sheet.getRange(2, 5, Math.max(values.length - 1, 1), 1).setNumberFormat('0.00');
sheet.autoResizeColumns(1, values[0].length);
sheet.setFrozenRows(1);
}
function buildTrendChart_(ss, trendSheet) {
let dashboard = ss.getSheetByName(DASHBOARD_SHEET);
if (!dashboard) {
dashboard = ss.insertSheet(DASHBOARD_SHEET);
}
dashboard.clear();
dashboard.getRange('A1').setValue('Динаміка середньої позиції за останні 30 днів');
const lastRow = trendSheet.getLastRow();
if (lastRow < 2) return;
const chart = dashboard.newChart()
.setChartType(Charts.ChartType.LINE)
.addRange(trendSheet.getRange(1, 1, lastRow, 1))
.addRange(trendSheet.getRange(1, 5, lastRow, 1))
.setPosition(3, 1, 0, 0)
.setOption('title', 'Середня позиція по днях')
.setOption('legend', { position: 'bottom' })
.setOption('curveType', 'function')
.setOption('hAxis', { title: 'Дата' })
.setOption('vAxis', { title: 'Позиція', direction: -1 })
.build();
dashboard.insertChart(chart);
}
function createWeeklyTrigger() {
deleteTriggers_('updateSeoRocket');
ScriptApp.newTrigger('updateSeoRocket')
.timeBased()
.everyWeeks(1)
.onWeekDay(ScriptApp.WeekDay.MONDAY)
.atHour(9)
.create();
}
function createMonthlyTrigger() {
deleteTriggers_('updateSeoRocket');
ScriptApp.newTrigger('updateSeoRocket')
.timeBased()
.onMonthDay(1)
.atHour(9)
.create();
}
function deleteTriggers_(functionName) {
ScriptApp.getProjectTriggers().forEach(trigger => {
if (trigger.getHandlerFunction() === functionName) {
ScriptApp.deleteTrigger(trigger);
}
});
}
function getDateRange_(daysBack) {
const tz = Session.getScriptTimeZone();
const end = new Date();
const start = new Date();
start.setDate(end.getDate() - daysBack);
return {
startDate: Utilities.formatDate(start, tz, 'yyyy-MM-dd'),
endDate: Utilities.formatDate(end, tz, 'yyyy-MM-dd')
};
}
function getOrCreateSheet_(ss, name) {
let sheet = ss.getSheetByName(name);
if (!sheet) {
sheet = ss.insertSheet(name);
}
return sheet;
}
Як налаштувати графік
У цьому коді графік створюється автоматично на аркуші GSC Dashboard. Для цього окремо збирається динаміка по днях, а потім будується лінійна діаграма за середньою позицією. Це зручно: ви одразу бачите не тільки список запитів, а й загальну тенденцію — сайт рухається вгору, стоїть на місці чи починає просідати.
Цей метод автоматизації ідеально підходить для ніш із великою кількістю товарних запитів та високою конкуренцією. Наприклад, якщо ви просуваєте великий оптовий склад або дистриб'ютора, де потрібно щодня відстежувати сотні артикулів — таких як сигарети для магазинів оптом — ручна перевірка позицій у Search Console займе години. Наш скрипт робить це за лічені секунди, дозволяючи вам фокусуватися на стратегії, а не на рутині.
Якщо хочете, ви можете легко змінити показник для графіка. Наприклад, замість середньої позиції побудувати лінію за кліками або показами. Для цього достатньо замінити колонку в блоці buildTrendChart_.

Як поставити все на автопілот
Щоб не запускати скрипт вручну, використайте тригер. У коді вже є дві функції: createWeeklyTrigger() і createMonthlyTrigger(). Перша оновлює дані раз на тиждень, друга — раз на місяць. Для більшості невеликих проєктів щотижневого оновлення вистачає з головою.
Сценарій тут дуже практичний: ви один раз налаштовуєте звіт, а потім просто відкриваєте таблицю й дивитеся свіжі дані. Це і є нормальна автоматизація маркетингу: система працює сама, а ви витрачаєте час не на рутину, а на рішення.
Порада
Для локального бізнесу або мікросайту почніть із щотижневого оновлення. Так легше побачити зміни без зайвого шуму в цифрах.
Застереження
Перед запуском переконайтеся, що в змінній SITE_URL вказана саме та адреса ресурсу, яка є у вашому Google Search Console. Якщо ресурс доданий як domain property, формат може відрізнятися від звичайного https://site.com/.

Що ви отримаєте на виході
У результаті у вас буде власний безкоштовний інструмент для моніторингу позицій сайту, який:
- показує реальні дані з GSC;
- зберігає звітність у Google Sheets;
- візуалізує динаміку через графік;
- автоматично оновлюється без ручної роботи.
Для маленького проєкту цього більш ніж достатньо, щоб замінити базові сценарії платних сервісів на старті. А коли сайт виросте, ви вже будете переходити до складніших SEO-інструментів не “наосліп”, а з розумінням, які саме дані вам потрібні.