const {
Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
AlignmentType, HeadingLevel, BorderStyle, WidthType, ShadingType, LevelFormat
} = require('docx');
const fs = require('fs');
const B = { style: BorderStyle.SINGLE, size: 1, color: "DDDDDD" };
const borders = { top: B, bottom: B, left: B, right: B };
const BLUE = "1A3A6B";
const RED = "C0392B";
const GOLD = "E67E22";
const GREEN = "1E8449";
const LGRAY = "F4F6F8";
const WHITE = "FFFFFF";
const LBLUE = "EAF2FF";
const LRED = "FEF9F0";
function cell(text, w, fill = WHITE, bold = false, color = "222222", size = 20, italic = false) {
return new TableCell({
borders,
width: { size: w, type: WidthType.DXA },
shading: { fill, type: ShadingType.CLEAR },
margins: { top: 90, bottom: 90, left: 140, right: 140 },
children: [new Paragraph({ children: [new TextRun({ text, bold, color, size, italics: italic, font: "Arial" })] })]
});
}
function hCell(text, w) {
return cell(text, w, BLUE, true, WHITE, 22);
}
function row(...cells) { return new TableRow({ children: cells }); }
function h1(text) {
return new Paragraph({
spacing: { before: 300, after: 140 },
children: [new TextRun({ text, bold: true, size: 34, color: BLUE, font: "Arial" })]
});
}
function h2(text) {
return new Paragraph({
spacing: { before: 240, after: 100 },
children: [new TextRun({ text, bold: true, size: 26, color: RED, font: "Arial" })]
});
}
function h3(text) {
return new Paragraph({
spacing: { before: 180, after: 80 },
children: [new TextRun({ text, bold: true, size: 23, color: GOLD, font: "Arial" })]
});
}
function p(text, opts = {}) {
return new Paragraph({
spacing: { after: 100 },
children: [new TextRun({ text, size: 20, font: "Arial", ...opts })]
});
}
function note(text) {
return new Paragraph({
spacing: { after: 120 },
shading: { fill: "FEF3CD", type: ShadingType.CLEAR },
border: { left: { style: BorderStyle.SINGLE, size: 12, color: GOLD, space: 6 } },
indent: { left: 200 },
children: [new TextRun({ text: "⚡ " + text, size: 20, font: "Arial", italics: true, color: "7D5A00" })]
});
}
function tip(text) {
return new Paragraph({
spacing: { after: 120 },
border: { left: { style: BorderStyle.SINGLE, size: 12, color: GREEN, space: 6 } },
indent: { left: 200 },
children: [new TextRun({ text: "✅ " + text, size: 20, font: "Arial", color: "1A5C2A" })]
});
}
function warn(text) {
return new Paragraph({
spacing: { after: 120 },
border: { left: { style: BorderStyle.SINGLE, size: 12, color: RED, space: 6 } },
indent: { left: 200 },
children: [new TextRun({ text: "⛔ " + text, size: 20, font: "Arial", color: "8B1A1A" })]
});
}
function bul(text, bold_prefix = null) {
const children = bold_prefix
? [new TextRun({ text: bold_prefix + " ", bold: true, size: 20, font: "Arial" }), new TextRun({ text, size: 20, font: "Arial" })]
: [new TextRun({ text, size: 20, font: "Arial" })];
return new Paragraph({
numbering: { reference: "bullets", level: 0 },
spacing: { after: 80 },
children
});
}
function divider() {
return new Paragraph({
spacing: { before: 200, after: 200 },
border: { bottom: { style: BorderStyle.SINGLE, size: 6, color: "DDDDDD", space: 1 } },
children: [new TextRun("")]
});
}
function gap(n = 120) {
return new Paragraph({ spacing: { after: n }, children: [new TextRun("")] });
}
// ─── ТАБЛИЦЫ ────────────────────────────────────────────────
function adBlock(title, rows) {
return [
h3(title),
new Table({
width: { size: 9200, type: WidthType.DXA },
columnWidths: [2600, 5000, 1600],
rows: [
row(hCell("Элемент", 2600), hCell("Текст", 5000), hCell("Симв.", 1600)),
...rows.map((r, i) => row(
cell(r[0], 2600, i % 2 === 0 ? LBLUE : WHITE, true, BLUE, 20),
cell(r[1], 5000, i % 2 === 0 ? LBLUE : WHITE),
cell(r[2], 1600, i % 2 === 0 ? LRED : "FFFDF5", false, r[2].includes("✓") ? GREEN : RED, 19)
))
]
}),
gap(160)
];
}
function kwBlock(groupTitle, rows) {
return [
h3(groupTitle),
new Table({
width: { size: 9200, type: WidthType.DXA },
columnWidths: [5400, 1900, 1900],
rows: [
row(hCell("Ключевое слово", 5400), hCell("Тип", 1900), hCell("Частота", 1900)),
...rows.map((r, i) => row(
cell(r[0], 5400, i % 2 === 0 ? LBLUE : WHITE, false, "222222", 20),
cell(r[1], 1900, i % 2 === 0 ? LBLUE : WHITE, false, BLUE, 19),
cell(r[2], 1900, i % 2 === 0 ? LRED : "FFFDF5", r[2] === "Высокая", r[2] === "Высокая" ? GREEN : r[2] === "Средняя" ? GOLD : "888888", 19)
))
]
}),
gap(160)
];
}
// ─── ДОКУМЕНТ ───────────────────────────────────────────────
const doc = new Document({
numbering: {
config: [{
reference: "bullets",
levels: [{ level: 0, format: LevelFormat.BULLET, text: "•", alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 560, hanging: 280 } } } }]
}]
},
styles: {
default: { document: { run: { font: "Arial", size: 20 } } }
},
sections: [{
properties: {
page: {
size: { width: 11906, height: 16838 },
margin: { top: 1080, right: 1080, bottom: 1080, left: 1080 }
}
},
children: [
// ═══════════════════════════════════════
// ОБЛОЖКА
// ═══════════════════════════════════════
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 1200, after: 360 },
children: [new TextRun({ text: "ЯНДЕКС ДИРЕКТ", bold: true, size: 60, color: RED, font: "Arial" })]
}),
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { after: 200 },
children: [new TextRun({ text: "Стратегия и структура рекламной кампании", bold: true, size: 32, color: BLUE, font: "Arial" })]
}),
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { after: 160 },
children: [new TextRun({ text: "Вывоз мусора — Санкт-Петербург + Ленинградская область", size: 26, color: "555555", font: "Arial" })]
}),
gap(60),
new Table({
width: { size: 6000, type: WidthType.DXA },
columnWidths: [3000, 3000],
rows: [
row(
cell("Бюджет в день:", 3000, LBLUE, true, BLUE, 22),
cell("1 000 — 3 000 ₽", 3000, LBLUE, true, RED, 22)
),
row(
cell("География:", 3000, WHITE, true, BLUE, 22),
cell("СПб + вся Ленинградская область", 3000, WHITE, false, "333333", 22)
),
row(
cell("Тип кампании:", 3000, LBLUE, true, BLUE, 22),
cell("Поиск + отдельно РСЯ", 3000, LBLUE, false, "333333", 22)
),
row(
cell("Стратегия ставок:", 3000, WHITE, true, BLUE, 22),
cell("Ручные ставки → Оптимизация кликов", 3000, WHITE, false, "333333", 22)
),
]
}),
gap(300),
divider(),
// ═══════════════════════════════════════
// РАЗДЕЛ 1: ЛОГИКА И СТРАТЕГИЯ
// ═══════════════════════════════════════
h1("1. СТРАТЕГИЯ КАМПАНИИ"),
p("При бюджете 1 000–3 000 ₽/день главный принцип — концентрация. Нельзя распылять бюджет на все ключи сразу. Нужно начать с горячих коммерческих запросов и постепенно расширяться по мере накопления данных."),
gap(100),
h2("1.1 Фазы запуска"),
new Table({
width: { size: 9200, type: WidthType.DXA },
columnWidths: [1600, 2400, 3200, 2000],
rows: [
row(hCell("Фаза", 1600), hCell("Период", 2400), hCell("Что делаем", 3200), hCell("Бюджет", 2000)),
row(
cell("Фаза 1", 1600, LBLUE, true, BLUE),
cell("Дни 1–14", 2400, LBLUE),
cell("Только горячие ключи: срочность + цена. Ручные ставки. Смотрим что конвертит.", 3200, LBLUE),
cell("1 000 ₽/день", 2000, LBLUE, true, RED)
),
row(
cell("Фаза 2", 1600, WHITE, true, BLUE),
cell("Дни 15–30", 2400, WHITE),
cell("Добавляем ключи по типу мусора и районам. Отключаем неэффективные. Оптимизируем объявления.", 3200, WHITE),
cell("1 500–2 000 ₽/день", 2000, WHITE, true, RED)
),
row(
cell("Фаза 3", 1600, LBLUE, true, BLUE),
cell("Месяц 2+", 2400, LBLUE),
cell("Переключаем на «Оптимизацию кликов». Запускаем РСЯ отдельно. Расширяем гео по ЛО.", 3200, LBLUE),
cell("2 000–3 000 ₽/день", 2000, LBLUE, true, RED)
),
]
}),
gap(160),
note("При бюджете 1 000 ₽/день и клике ~40–60 ₽ вы получаете 16–25 кликов в сутки. Это реально при CTR 8–12% даст 1–3 заявки в день — нормальный старт."),
h2("1.2 Структура аккаунта"),
p("Создайте 2 отдельные кампании — не смешивайте поиск и РСЯ:"),
gap(80),
new Table({
width: { size: 9200, type: WidthType.DXA },
columnWidths: [2400, 3600, 3200],
rows: [
row(hCell("Кампания", 2400), hCell("Содержание", 3600), hCell("Примечание", 3200)),
row(
cell("Кампания 1: ПОИСК", 2400, LBLUE, true, BLUE),
cell("5 групп объявлений по типу запроса (см. раздел 2)", 3600, LBLUE),
cell("Запускать ПЕРВОЙ — горячий трафик", 3200, LBLUE, false, GREEN)
),
row(
cell("Кампания 2: РСЯ", 2400, WHITE, true, BLUE),
cell("Более широкие ключи, визуальные баннеры", 3600, WHITE),
cell("Запустить на ФАЗЕ 3, когда отладите поиск", 3200, WHITE, false, GOLD)
),
]
}),
gap(200),
divider(),
// ═══════════════════════════════════════
// РАЗДЕЛ 2: СТРУКТУРА ГРУПП
// ═══════════════════════════════════════
h1("2. СТРУКТУРА ГРУПП ОБЪЯВЛЕНИЙ"),
p("5 групп, каждая — под свой тип коммерческого запроса. Своё объявление с точным вхождением ключа в заголовок."),
gap(100),
new Table({
width: { size: 9200, type: WidthType.DXA },
columnWidths: [400, 2600, 3000, 1800, 1400],
rows: [
row(hCell("№", 400), hCell("Группа", 2600), hCell("Тип запроса", 3000), hCell("Приоритет", 1800), hCell("Фаза", 1400)),
...[
["1", "Цена / стоимость", "вывоз мусора спб цена, стоимость", "🔥 Горячие", "Фаза 1"],
["2", "Срочно / сегодня", "срочный вывоз, вывоз сегодня, за 2 часа", "🔥 Горячие", "Фаза 1"],
["3", "Строительный мусор", "вывоз строительного мусора спб", "🔥 Горячие", "Фаза 1"],
["4", "По районам СПб", "вывоз мусора Приморский район и т.д.", "🟡 Тёплые", "Фаза 2"],
["5", "Города ЛО", "вывоз мусора Всеволожск, Гатчина и т.д.", "🟡 Тёплые", "Фаза 2"],
].map((r, i) => row(
cell(r[0], 400, i % 2 === 0 ? LBLUE : WHITE, true, BLUE),
cell(r[1], 2600, i % 2 === 0 ? LBLUE : WHITE, true),
cell(r[2], 3000, i % 2 === 0 ? LBLUE : WHITE),
cell(r[3], 1800, i % 2 === 0 ? LRED : "FFFDF5", true, r[3].startsWith("🔥") ? RED : GOLD),
cell(r[4], 1400, i % 2 === 0 ? LBLUE : WHITE, false, BLUE)
))
]
}),
gap(200),
divider(),
// ═══════════════════════════════════════
// РАЗДЕЛ 3: ОБЪЯВЛЕНИЯ
// ═══════════════════════════════════════
h1("3. ТЕКСТЫ ОБЪЯВЛЕНИЙ"),
p("Формат: Заголовок 1 (56 симв.) + Заголовок 2 (30 симв.) + Текст объявления (81 симв.). Для каждой группы — минимум 2 варианта: система сама выберет лучший по CTR."),
gap(80),
note("Правило: ключевое слово должно быть в Заголовке 1. Яндекс выделяет его жирным — CTR растёт на 20–35%."),
gap(120),
// ГРУППА 1
h2("ГРУППА 1 — «Цена / стоимость»"),
...adBlock("Объявление 1.1 — Акцент на цену + гарантия", [
["Заголовок 1", "Вывоз мусора от 2500 ₽ — СПб", "30 / 56 ✓"],
["Заголовок 2", "За 2 часа. Без предоплаты", "25 / 30 ✓"],
["Текст", "Своя техника. Лицензия. Платите только после вывоза. Работаем 24/7 по СПб и ЛО.", "79 / 81 ✓"],
["URL", "ваш-сайт.рф/vyvoz-musora", "—"],
]),
...adBlock("Объявление 1.2 — Прямой прайс", [
["Заголовок 1", "Вывоз мусора СПб — цены 2025", "31 / 56 ✓"],
["Заголовок 2", "От 2500 руб. Без скрытых доплат", "30 / 30 ✓"],
["Текст", "Газель от 2500 ₽, Камаз от 5500 ₽. Грузчики. Фото отчёт. Звоните — приедем сегодня!", "81 / 81 ✓"],
["URL", "ваш-сайт.рф/vyvoz-musora", "—"],
]),
// ГРУППА 2
h2("ГРУППА 2 — «Срочно / сегодня»"),
...adBlock("Объявление 2.1 — Скорость", [
["Заголовок 1", "Срочный вывоз мусора — 2 часа", "29 / 56 ✓"],
["Заголовок 2", "Приедем сегодня. СПб и ЛО", "26 / 30 ✓"],
["Текст", "Заявки 24/7. Машина выезжает сразу. Оплата после вывоза. Без очередей и предоплаты.", "81 / 81 ✓"],
["URL", "ваш-сайт.рф/srochno", "—"],
]),
...adBlock("Объявление 2.2 — Сегодня/сейчас", [
["Заголовок 1", "Вывоз мусора сегодня в СПб", "27 / 56 ✓"],
["Заголовок 2", "Звоните — выедем через час!", "30 / 30 ✓"],
["Текст", "Работаем без выходных и праздников. 18 машин в парке. Цена по телефону без сюрпризов.", "80 / 81 ✓"],
["URL", "ваш-сайт.рф/srochno", "—"],
]),
// ГРУППА 3
h2("ГРУППА 3 — «Строительный мусор»"),
...adBlock("Объявление 3.1 — Общее", [
["Заголовок 1", "Вывоз строительного мусора СПб", "31 / 56 ✓"],
["Заголовок 2", "От 2500 ₽. Сегодня. Лицензия", "29 / 30 ✓"],
["Текст", "Бой плитки, штукатурка, кирпич, стяжка. Камаз, еврофура. Документы об утилизации.", "79 / 81 ✓"],
["URL", "ваш-сайт.рф/stroitelnyj", "—"],
]),
...adBlock("Объявление 3.2 — Для юрлиц", [
["Заголовок 1", "Строительный мусор — вывоз СПб", "31 / 56 ✓"],
["Заголовок 2", "Договор, акт, лицензия. 24/7", "29 / 30 ✓"],
["Текст", "Работаем с юрлицами и ИП. Договор, акт, лицензия. Фото отчёт на полигоне. Без наличных.", "81 / 81 ✓"],
["URL", "ваш-сайт.рф/stroitelnyj", "—"],
]),
// ГРУППА 4
h2("ГРУППА 4 — «По районам СПб» (шаблон — создать под каждый)"),
p("Создайте отдельное объявление под каждый район. Просто замените название района в заголовке — это даёт +20–35% к CTR за счёт точного вхождения."),
gap(80),
...adBlock("Шаблон по районам (пример: Приморский)", [
["Заголовок 1", "Вывоз мусора [РАЙОН] район СПб", "~50 / 56 ✓"],
["Заголовок 2", "Приедем за 2 часа. От 2500 ₽", "30 / 30 ✓"],
["Текст", "Работаем в [РАЙОН] р-не СПб. Строительный, бытовой, мебель. Грузчики. Без предоплаты.", "81 / 81 ✓"],
["URL", "ваш-сайт.рф/rayon", "—"],
]),
p("Районы для создания объявлений: Приморский, Выборгский, Калининский, Московский, Красносельский, Невский, Фрунзенский, Петроградский, Кировский, Василеостровский.", { italics: true, color: "666666" }),
gap(120),
// ГРУППА 5
h2("ГРУППА 5 — «Города ЛО» (шаблон)"),
...adBlock("Шаблон по городам ЛО (пример: Всеволожск)", [
["Заголовок 1", "Вывоз мусора [ГОРОД]", "~30 / 56 ✓"],
["Заголовок 2", "Приедем сегодня. Без предоплаты", "30 / 30 ✓"],
["Текст", "Вывозим мусор в [ГОРОД] и районе. Строительный, бытовой, мебель. Оплата после вывоза.", "81 / 81 ✓"],
["URL", "ваш-сайт.рф/lo", "—"],
]),
p("Города ЛО: Всеволожск, Гатчина, Тосно, Кингисепп, Выборг, Мурино, Кудрово, Девяткино, Сертолово, Шушары.", { italics: true, color: "666666" }),
gap(200),
divider(),
// ═══════════════════════════════════════
// РАЗДЕЛ 4: РАСШИРЕНИЯ
// ═══════════════════════════════════════
h1("4. РАСШИРЕНИЯ ОБЪЯВЛЕНИЙ"),
p("Расширения увеличивают площадь объявления и CTR на 15–40%. Заполните все — система выберет лучшую комбинацию."),
gap(120),
h2("4.1 Быстрые ссылки"),
new Table({
width: { size: 9200, type: WidthType.DXA },
columnWidths: [2400, 4200, 2600],
rows: [
row(hCell("Текст ссылки", 2400), hCell("Описание (видно на десктопе)", 4200), hCell("URL страницы", 2600)),
...[
["Рассчитать стоимость", "Онлайн-калькулятор — цена за 30 секунд", "#calculator"],
["Прайс-лист 2025", "Газель от 2500 ₽, Камаз от 5500 ₽", "#prices"],
["Строительный мусор", "Кирпич, плитка, штукатурка, стяжка", "#stroi"],
["Зоны выезда", "Все районы СПб + ЛО до 150 км", "#zones"],
].map((r, i) => row(
cell(r[0], 2400, i % 2 === 0 ? LBLUE : WHITE, true),
cell(r[1], 4200, i % 2 === 0 ? LBLUE : WHITE),
cell(r[2], 2600, i % 2 === 0 ? LRED : "FFFDF5", false, "0070C0")
))
]
}),
gap(160),
h2("4.2 Уточнения (до 8 штук по 25 символов)"),
new Table({
width: { size: 9200, type: WidthType.DXA },
columnWidths: [4600, 4600],
rows: [
row(hCell("Текст уточнения", 4600), hCell("Символов", 4600)),
...[
["Без предоплаты", "14 / 25 ✓"],
["Платите только после вывоза", "27 — сократить до «Оплата после вывоза» ✓"],
["Работаем 24/7", "13 / 25 ✓"],
["Официальная лицензия", "21 / 25 ✓"],
["18 машин — свой парк", "20 / 25 ✓"],
["Фото отчёт об утилизации", "24 / 25 ✓"],
["Приедем за 2 часа", "17 / 25 ✓"],
["Документы для юрлиц", "20 / 25 ✓"],
].map((r, i) => row(
cell(r[0], 4600, i % 2 === 0 ? LBLUE : WHITE),
cell(r[1], 4600, i % 2 === 0 ? LRED : "FFFDF5", false, r[1].includes("сократить") ? RED : GREEN)
))
]
}),
gap(160),
h2("4.3 Телефон и визитка"),
bul("Добавьте расширение «Контактная информация» — показывает номер прямо в объявлении"),
bul("На мобильных появляется кнопка «Позвонить» — это самый ценный клик в нише вывоза мусора"),
bul("Заполните адрес компании в визитке — повышает доверие и улучшает ранжирование"),
gap(160),
h2("4.4 Цена в объявлении"),
bul("Добавьте расширение «Цены»: Газель — от 2 500 ₽, Камаз — от 5 500 ₽, Грузчики — от 800 ₽/час"),
bul("Люди видят цену до клика — отсекаются нецелевые, CTR растёт у целевых"),
gap(200),
divider(),
// ═══════════════════════════════════════
// РАЗДЕЛ 5: КЛЮЧЕВЫЕ СЛОВА
// ═══════════════════════════════════════
h1("5. КЛЮЧЕВЫЕ СЛОВА"),
p("Тип соответствия: фразовое (кавычки) для всех ключей. Это даёт точность без потери охвата. Широкое соответствие при бюджете 1–3к/день сожжёт деньги на мусорный трафик."),
gap(80),
warn("Не используйте широкое соответствие при таком бюджете — деньги уйдут на нецелевые показы"),
tip("На старте (Фаза 1) подключите только Группы 1, 2, 3. Группы 4–5 добавьте на Фазе 2."),
gap(120),
...kwBlock("ГРУППА 1 — Цена / стоимость (Фаза 1 — ЗАПУСКАТЬ ПЕРВЫМИ)", [
["вывоз мусора спб цена", "Фразовое", "Высокая"],
["вывоз мусора санкт петербург стоимость", "Фразовое", "Высокая"],
["сколько стоит вывоз мусора спб", "Фразовое", "Высокая"],
["вывоз мусора цены спб 2025", "Фразовое", "Высокая"],
["вывоз строительного мусора спб цена", "Фразовое", "Высокая"],
["вывоз мусора газель цена спб", "Фразовое", "Средняя"],
["вывоз мусора камаз цена спб", "Фразовое", "Средняя"],
["заказать вывоз мусора спб недорого", "Фразовое", "Средняя"],
["вывоз мусора ленинградская область цена", "Фразовое", "Средняя"],
]),
...kwBlock("ГРУППА 2 — Срочно / сегодня (Фаза 1 — ЗАПУСКАТЬ ПЕРВЫМИ)", [
["срочный вывоз мусора спб", "Фразовое", "Высокая"],
["вывоз мусора сегодня спб", "Фразовое", "Высокая"],
["вывоз мусора срочно санкт петербург", "Фразовое", "Высокая"],
["вызвать машину для вывоза мусора спб", "Фразовое", "Высокая"],
["вывоз мусора в течение дня спб", "Фразовое", "Средняя"],
["вывоз мусора без предоплаты спб", "Фразовое", "Средняя"],
["вывоз мусора ночью спб", "Фразовое", "Низкая"],
["срочный вывоз строительного мусора спб", "Фразовое", "Средняя"],
]),
...kwBlock("ГРУППА 3 — Строительный мусор (Фаза 1 — ЗАПУСКАТЬ ПЕРВЫМИ)", [
["вывоз строительного мусора спб", "Фразовое", "Высокая"],
["вывоз строительного мусора петербург", "Фразовое", "Высокая"],
["вывоз строительного мусора после ремонта спб", "Фразовое", "Высокая"],
["вывоз мусора после ремонта квартиры спб", "Фразовое", "Высокая"],
["вывоз бетонного мусора спб", "Фразовое", "Средняя"],
["вывоз боя плитки спб", "Фразовое", "Средняя"],
["вывоз штукатурки спб", "Фразовое", "Средняя"],
["вывоз кирпичного боя спб", "Фразовое", "Средняя"],
["вывоз грунта спб", "Фразовое", "Средняя"],
["вывоз старой мебели спб", "Фразовое", "Средняя"],
["вывоз хлама из квартиры спб", "Фразовое", "Средняя"],
["вывоз строительного мусора ленинградская область", "Фразовое", "Средняя"],
]),
...kwBlock("ГРУППА 4 — По районам СПб (Фаза 2)", [
["вывоз мусора приморский район спб", "Фразовое", "Высокая"],
["вывоз мусора выборгский район спб", "Фразовое", "Высокая"],
["вывоз мусора калининский район спб", "Фразовое", "Высокая"],
["вывоз мусора московский район спб", "Фразовое", "Высокая"],
["вывоз мусора красносельский район спб", "Фразовое", "Высокая"],
["вывоз мусора невский район спб", "Фразовое", "Средняя"],
["вывоз мусора фрунзенский район спб", "Фразовое", "Средняя"],
["вывоз мусора кировский район спб", "Фразовое", "Средняя"],
["вывоз мусора петроградский спб", "Фразовое", "Средняя"],
["вывоз мусора василеостровский спб", "Фразовое", "Средняя"],
["вывоз мусора колпино спб", "Фразовое", "Средняя"],
]),
...kwBlock("ГРУППА 5 — Города ЛО (Фаза 2)", [
["вывоз мусора всеволожск", "Фразовое", "Высокая"],
["вывоз мусора гатчина", "Фразовое", "Высокая"],
["вывоз мусора мурино", "Фразовое", "Высокая"],
["вывоз мусора кудрово", "Фразовое", "Высокая"],
["вывоз мусора девяткино", "Фразовое", "Средняя"],
["вывоз мусора тосно", "Фразовое", "Средняя"],
["вывоз мусора кингисепп", "Фразовое", "Средняя"],
["вывоз мусора выборг", "Фразовое", "Средняя"],
["вывоз мусора сертолово", "Фразовое", "Средняя"],
["вывоз мусора шушары", "Фразовое", "Средняя"],
["вывоз мусора парголово", "Фразовое", "Низкая"],
["вывоз мусора ленинградская область", "Фразовое", "Средняя"],
]),
gap(200),
divider(),
// ═══════════════════════════════════════
// РАЗДЕЛ 6: МИНУС-СЛОВА
// ═══════════════════════════════════════
h1("6. МИНУС-СЛОВА"),
p("Добавлять на уровне КАМПАНИИ. Экономят до 30% бюджета, отсекая нецелевые клики. При бюджете 1–3к/день это критично."),
gap(80),
tip("После 2 недель зайдите в «Поисковые запросы» и добавьте минус-слова из реальных нецелевых кликов — это самые ценные минуса."),
gap(120),
h2("Блок 1 — Информационные запросы"),
p("-своими руками -самостоятельно -как сделать -что такое -правила -нормы -законодательство -СНИЛС -штраф -скачать -реферат -дипломная -курсовая -доклад -рассчитать самому -калькулятор скачать"),
gap(120),
h2("Блок 2 — Нерелевантные типы отходов"),
p("-медицинский -радиоактивный -опасный -токсичный -химический -ядерный -биологический -взрывоопасный -класс а -класс б -класс в"),
gap(120),
h2("Блок 3 — Другие города (не ваша зона)"),
p("-Москва -Московская -Новосибирск -Екатеринбург -Краснодар -Казань -Самара -Уфа -Челябинск -Омск"),
gap(120),
h2("Блок 4 — Вакансии и работа"),
p("-вакансия -работа -зарплата -водитель -устроиться -требуется -ищу работу -оформление -трудоустройство"),
gap(120),
h2("Блок 5 — Покупка и продажа"),
p("-купить контейнер -продам -б/у -аренда -прокат -стоимость контейнера купить"),
gap(120),
h2("Блок 6 — Прочие нецелевые"),
p("-форум -отзывы (если не ваш сайт) -фото -видео -дёшево (если вы не самые дешёвые) -бесплатно -за спасибо -своими силами"),
gap(200),
divider(),
// ═══════════════════════════════════════
// РАЗДЕЛ 7: НАСТРОЙКИ
// ═══════════════════════════════════════
h1("7. НАСТРОЙКИ КАМПАНИИ"),
gap(80),
h2("7.1 Стратегия ставок при бюджете 1–3к/день"),
new Table({
width: { size: 9200, type: WidthType.DXA },
columnWidths: [1600, 3200, 4400],
rows: [
row(hCell("Период", 1600), hCell("Стратегия", 3200), hCell("Что делать", 4400)),
row(
cell("Дни 1–14", 1600, LBLUE, true, BLUE),
cell("Ручные ставки", 3200, LBLUE, true),
cell("Начните с 25–40 ₽ за клик. Мониторьте каждые 2 дня. Поднимайте ставку на ключах с CTR > 5%.", 4400, LBLUE)
),
row(
cell("Дни 15–30", 1600, WHITE, true, BLUE),
cell("Ручные ставки (оптимизация)", 3200, WHITE, true),
cell("Отключите ключи: расход > 200 ₽ без конверсий. Оставьте топ-10 конвертирующих.", 4400, WHITE)
),
row(
cell("Месяц 2+", 1600, LBLUE, true, BLUE),
cell("Оптимизация кликов (авто)", 3200, LBLUE, true),
cell("Переключить на «Макс. кликов в неделю» при накопленной статистике 100+ кликов.", 4400, LBLUE)
),
]
}),
gap(160),
warn("Не включайте сразу «Оптимизацию конверсий» — нужно минимум 10–20 конверсий в неделю. При 1–3к/день это придёт к концу 2-го месяца."),
gap(160),
h2("7.2 Геотаргетинг"),
bul("Регион показа: Санкт-Петербург + Ленинградская область"),
bul("Расширенный геотаргетинг: ВЫКЛЮЧИТЬ — иначе покажетесь людям из Москвы, ищущим вывоз в СПб"),
bul("Корректировка ставок +15%: Приморский, Выборгский, Калининский р-ны (высокая плотность и спрос)"),
bul("Корректировка ставок −20%: отдалённые районы ЛО (Выборг, Кингисепп) на Фазе 1"),
gap(120),
h2("7.3 Временной таргетинг"),
new Table({
width: { size: 9200, type: WidthType.DXA },
columnWidths: [3000, 2600, 3600],
rows: [
row(hCell("Время", 3000), hCell("Ставка", 2600), hCell("Обоснование", 3600)),
...[
["Пн–Пт 07:00–21:00", "100%", "Основное рабочее время — максимум"],
["Сб–Вс 07:00–21:00", "+10%", "Пик ремонтов и генеральных уборок"],
["Ежедневно 21:00–23:00", "70%", "Люди планируют на завтра — стоит быть"],
["Ежедневно 23:00–07:00", "40%", "Срочные ночные запросы — не отключать"],
].map((r, i) => row(
cell(r[0], 3000, i % 2 === 0 ? LBLUE : WHITE, true),
cell(r[1], 2600, i % 2 === 0 ? LRED : "FFFDF5", true, r[1] === "100%" ? GREEN : r[1] === "+10%" ? GOLD : "555555"),
cell(r[2], 3600, i % 2 === 0 ? LBLUE : WHITE)
))
]
}),
gap(160),
h2("7.4 Корректировки ставок"),
bul("+20% мобильные устройства", "→"), p(" Большинство ищут с телефона чтобы сразу позвонить. Это самый ценный трафик.", { color: "666666" }),
bul("+40% ретаргетинг (посетители сайта)", "→"), p(" Люди которые уже были — конвертируют в 3–5 раз лучше.", { color: "666666" }),
bul("−50% аудитория «дети 0–12 лет»", "→"), p(" Нецелевая аудитория — экономим бюджет.", { color: "666666" }),
bul("−30% возраст 18–24", "→"), p(" Низкая конверсия в нише вывоза мусора.", { color: "666666" }),
gap(160),
h2("7.5 Обязательные технические настройки"),
bul("Счётчик Яндекс Метрики — подключить к кампании (без этого оптимизация не работает)"),
bul("Цели в Метрике: «Клик по номеру», «Отправка формы», «Сессия > 60 сек» — настроить ДО запуска"),
bul("Колтрекинг — рекомендуется (CoMagic / Calltouch) — видно какой ключ приносит звонки"),
bul("UTM-метки — на всех URL объявлений: ?utm_source=yandex&utm_medium=cpc&utm_campaign=poisk"),
bul("Показ по доп. релевантным фразам — ВЫКЛЮЧИТЬ на Фазе 1"),
bul("Автотаргетинг — ВЫКЛЮЧИТЬ (добавит нецелевой трафик)"),
bul("Остановка при недоступности сайта — ВКЛЮЧИТЬ"),
gap(200),
divider(),
// ═══════════════════════════════════════
// РАЗДЕЛ 8: ЧЕКЛИСТ И МЕТРИКИ
// ═══════════════════════════════════════
h1("8. ЧЕКЛИСТ ЗАПУСКА И KPI"),
h2("8.1 Чеклист — проверить перед стартом"),
new Table({
width: { size: 9200, type: WidthType.DXA },
columnWidths: [600, 8600],
rows: [
row(hCell("", 600), hCell("Задача", 8600)),
...[
["☐", "Яндекс Метрика подключена к сайту и к кампании Директ"],
["☐", "Настроены цели: «Клик по телефону», «Отправка формы», «Кнопка заявки»"],
["☐", "Номер телефона в объявлении (расширение «Контактная информация»)"],
["☐", "Заполнена визитка (адрес, часы работы)"],
["☐", "Все минус-слова добавлены на уровне кампании"],
["☐", "Лендинг открывается на мобильном < 3 секунд"],
["☐", "Телефон на лендинге кликабелен (тег tel:)"],
["☐", "UTM-метки на всех URL объявлений"],
["☐", "Дневной бюджет с ограничением выставлен"],
["☐", "Расширенный геотаргетинг ВЫКЛЮЧЕН"],
["☐", "Автотаргетинг и доп. фразы ВЫКЛЮЧЕНЫ"],
["☐", "2 варианта объявления в каждой группе (A/B тест)"],
].map((r, i) => row(
cell(r[0], 600, i % 2 === 0 ? "F0FFF0" : WHITE, false, GREEN, 22),
cell(r[1], 8600, i % 2 === 0 ? "F0FFF0" : WHITE)
))
]
}),
gap(160),
h2("8.2 Целевые KPI при бюджете 1–3к/день"),
new Table({
width: { size: 9200, type: WidthType.DXA },
columnWidths: [3200, 2400, 3600],
rows: [
row(hCell("Метрика", 3200), hCell("Целевое значение", 2400), hCell("Если хуже — что делать", 3600)),
...[
["CTR (кликабельность)", "> 8–12%", "Переписать заголовок, добавить цену или цифры"],
["Цена клика (CPC)", "30–70 ₽", "Снизить ставки или сузить ключи"],
["Конверсия сайта в заявку", "> 5–8%", "Улучшить лендинг, добавить форму выше"],
["Стоимость заявки (CPL)", "< 500–800 ₽", "Отключить неконвертирующие ключи"],
["Отказы", "< 30%", "Проверить релевантность объявления и страницы"],
].map((r, i) => row(
cell(r[0], 3200, i % 2 === 0 ? LBLUE : WHITE, true),
cell(r[1], 2400, i % 2 === 0 ? LRED : "FFFDF5", true, GREEN),
cell(r[2], 3600, i % 2 === 0 ? LBLUE : WHITE, false, "555555", 19)
))
]
}),
gap(240),
divider(),
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 120, after: 80 },
children: [new TextRun({ text: "Яндекс Директ · Вывоз мусора СПб и ЛО · Бюджет 1 000–3 000 ₽/день", size: 18, color: "AAAAAA", italics: true, font: "Arial" })]
}),
]
}]
});
Packer.toBuffer(doc).then(buf => {
fs.writeFileSync('/home/claude/yd-strategy.docx', buf);
console.log('Done');
});