docs-combiner 0.4.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agentApi/agentControlClaim.js +26 -0
- package/dist/agentApi/approachMatrixView.js +19 -0
- package/dist/agentApi/capabilitiesMeta.js +78 -0
- package/dist/agentApi/catalogUrlPresets.js +26 -0
- package/dist/agentApi/constants.js +11 -0
- package/dist/agentApi/creativeSelections.js +25 -0
- package/dist/agentApi/escalation.js +221 -0
- package/dist/agentApi/generatedPairsGuard.js +85 -0
- package/dist/agentApi/httpHelpers.js +77 -0
- package/dist/agentApi/imagesReadiness.js +60 -0
- package/dist/agentApi/jobStatus.js +113 -0
- package/dist/agentApi/productImageDrive.js +39 -0
- package/dist/agentApi/regenerateImages.js +125 -0
- package/dist/agentApi/rendererTypes.js +3 -0
- package/dist/agentApi/routes.js +440 -0
- package/dist/agentApi/sessionSnapshot.js +82 -0
- package/dist/agentApi/sessionTypes.js +2 -0
- package/dist/agentApi/spec.js +1045 -0
- package/dist/agentApi/types.js +2 -0
- package/dist/agentApi/validation.js +32 -0
- package/dist/campaignsCsv.js +420 -0
- package/dist/contentPairs.js +62 -0
- package/dist/flexcardBalance.js +88 -0
- package/dist/integrations/driveApi.js +420 -0
- package/dist/integrations/httpTimeout.js +116 -0
- package/dist/integrations/openrouter.js +532 -0
- package/dist/main.js +316 -1214
- package/dist/models.js +17 -0
- package/dist/offerSettings.js +19 -0
- package/dist/preload.js +9 -0
- package/dist/promptOverrides.js +437 -0
- package/dist/prompts.js +1243 -0
- package/dist/renderer.js +19 -19
- package/dist/renderer.js.map +1 -1
- package/dist/server/app.js +378 -0
- package/dist/server/auth.js +74 -0
- package/dist/server/contentJobs.js +367 -0
- package/dist/server/driveCatalog.js +122 -0
- package/dist/server/driveProxy.js +220 -0
- package/dist/server/flexcardMeta.js +29 -0
- package/dist/server/googleAuth.js +84 -0
- package/dist/server/imageAssets.js +87 -0
- package/dist/server/imageJobs.js +776 -0
- package/dist/server/index.js +38 -0
- package/dist/server/jobEvents.js +116 -0
- package/dist/server/jobs.js +358 -0
- package/dist/server/openRouterMeta.js +58 -0
- package/dist/server/spec.js +544 -0
- package/dist/server/storage.js +133 -0
- package/dist/server/telegram.js +53 -0
- package/dist/server/workspaceSnapshot.js +273 -0
- package/package.json +15 -3
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,1243 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Промпты для генерации контента
|
|
4
|
+
* Все промпты на русском языке для консистентности
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.CREO_APPROACHES = exports.TEXTS_APPROACH_POOL = exports.TITLES_APPROACH_POOL = exports.PAIR_APPROACH_POOL = exports.QUIZ_AGE_APPROACH = exports.MALE_VERTICAL_CRITERIA = void 0;
|
|
8
|
+
exports.getCreoApproachBaseNameFromImageLabel = getCreoApproachBaseNameFromImageLabel;
|
|
9
|
+
exports.creoApproachHasNoBullets = creoApproachHasNoBullets;
|
|
10
|
+
exports.getEffectiveCreoNoBullets = getEffectiveCreoNoBullets;
|
|
11
|
+
exports.pickRandomBullets = pickRandomBullets;
|
|
12
|
+
exports.getTitlesSystemPrompt = getTitlesSystemPrompt;
|
|
13
|
+
exports.getTextsSystemPrompt = getTextsSystemPrompt;
|
|
14
|
+
exports.getUserPrompt = getUserPrompt;
|
|
15
|
+
exports.getPairsSystemPrompt = getPairsSystemPrompt;
|
|
16
|
+
exports.getPairsUserPrompt = getPairsUserPrompt;
|
|
17
|
+
exports.getValidationProductReferencePreamble = getValidationProductReferencePreamble;
|
|
18
|
+
exports.getValidationPrompt = getValidationPrompt;
|
|
19
|
+
exports.getImageGenerationBasePrompt = getImageGenerationBasePrompt;
|
|
20
|
+
exports.getCreoApproachExpandedTasks = getCreoApproachExpandedTasks;
|
|
21
|
+
exports.getCreoApproaches = getCreoApproaches;
|
|
22
|
+
exports.findCreoApproachByName = findCreoApproachByName;
|
|
23
|
+
const promptOverrides_1 = require("./promptOverrides");
|
|
24
|
+
/** Единый критерий «мужская вертикаль» для ветвления по брифу во всех промптах. */
|
|
25
|
+
exports.MALE_VERTICAL_CRITERIA = 'мужское здоровье, потенция, либидо, эрекция, простата, фертильность';
|
|
26
|
+
/** Рекламно-приемлемые рамки «желаемого образа» (женский портрет в мужской вертикали). */
|
|
27
|
+
const MALE_VERTICAL_DESIRED_IMAGE_BOUNDS = 'обычная одежда, портрет или поясной план, дружелюбно-уверенная подача; ЗАПРЕЩЕНО: обнажение, сексуализированные/лежачие позы, визуал «объект для потребления» — привлекательный человек в мейнстрим-рекламе, не эротика';
|
|
28
|
+
/** Имя визуального подхода «квиз-экран» — для TEXT LIMIT, валидатора и CREO_APPROACHES. */
|
|
29
|
+
exports.QUIZ_AGE_APPROACH = 'Квиз / Выбор возраста';
|
|
30
|
+
/** Условное смягчение деликатных тем + запрет количественных клеймов (тексты/пары). */
|
|
31
|
+
function getDelicateTopicsAndQuantitativeClaimsRule() {
|
|
32
|
+
return `- ДЕЛИКАТНЫЕ/ИНТИМНЫЕ ТЕМЫ (по вертикали продукта из задания):
|
|
33
|
+
* Если продукт относится к **мужской вертикали** (${exports.MALE_VERTICAL_CRITERIA}) — прямую лексику симптома и результата на языке GEO **разрешено**: можно называть проблему и желаемый результат (эрекция, потенция, либидо, влечение, выносливость и т.п.) без обязательного эвфемизма. Тон допускается уверенный и прямой.
|
|
34
|
+
* Иначе (все остальные вертикали) — избегай прямых упоминаний интимных или деликатных деталей, связанных с проблемой. Используй мягкие формулировки, описывающие дискомфорт и симптомы, а не физиологические процессы.
|
|
35
|
+
* **Граница для всех вертикалей, включая мужскую:** запрещены **количественные** выдуманные обещания результата, которых нет в задании — конкретные проценты прироста («+390%»), сантиметры («+3–5 см»), «N раз за ночь» и любые измеримые обещания. Послабление по тону **не** отменяет этот запрет.`;
|
|
36
|
+
}
|
|
37
|
+
/** Тон и прямота лексики на image-макете для мужской вертикали. */
|
|
38
|
+
function getMaleVerticalImageToneBlock(generateGeo) {
|
|
39
|
+
return `- **МУЖСКАЯ ВЕРТИКАЛЬ** (${exports.MALE_VERTICAL_CRITERIA}): для HOOK и буллитов допускается прямая лексика симптома и результата на языке ${generateGeo} (эрекция, потенция, либидо, влечение, простата, выносливость и т.п.), уверенный/прямой тон — не сглаживай до абстрактного «общего самочувствия» без привязки к нише.
|
|
40
|
+
- **КОЛИЧЕСТВЕННЫЕ КЛЕЙМЫ (все вертикали):** на макете ЗАПРЕЩЕНЫ выдуманные измеримые обещания, которых нет в брифе — проценты прироста («+390%»), сантиметры («+3–5 см»), «N раз за ночь» и т.п. Это правило **не** ослабляется для мужской вертикали.`;
|
|
41
|
+
}
|
|
42
|
+
/** Безопасность для валидатора: прямая мужская лексика ≠ ошибка тона. */
|
|
43
|
+
function getMaleVerticalValidationToneNote() {
|
|
44
|
+
return `- **Мужская вертикаль** (${exports.MALE_VERTICAL_CRITERIA}): если продукт из брифа относится к этой категории — прямая лексика симптома/результата на языке GEO (эрекция, потенция, либидо, влечение, простата, выносливость и т.п.) **не** является ошибкой тона и **не** требует смягчения.
|
|
45
|
+
- **Мужская вертикаль — женский портрет («желаемый образ»):** для подхода «Эмоция / Портрет» женщина в кадре как «желаемый образ» результата (близость, партнёрство, уверенность) **не** является ошибкой релевантности, если HOOK, буллеты и тема остаются в мужской нише.`;
|
|
46
|
+
}
|
|
47
|
+
/** Пул шаблонов буллетов по категориям (на русском — модель переводит на язык GEO).
|
|
48
|
+
* Без привязки к «чужим» вертикалям (суставы/боль/ЖКТ/кожа): иначе модель переносит их на любой оффер. */
|
|
49
|
+
const BULLET_BY_CATEGORY = {
|
|
50
|
+
action: [
|
|
51
|
+
'Поддержка организма', 'Комфорт в повседневности', 'Мягкая поддержка формулы',
|
|
52
|
+
'Заметная поддержка самочувствия', 'Для регулярного приёма', 'Естественная поддержка',
|
|
53
|
+
'Видимая разница со временем', 'Больше уверенности в себе'
|
|
54
|
+
],
|
|
55
|
+
timeframe: [
|
|
56
|
+
'Эффект за 7–14 дней', 'Эффект за 2 недели', 'Быстрый результат', 'Поддержка с первого дня',
|
|
57
|
+
'Эффект за 7 дней', 'Заметно уже скоро', 'С первого дня курса', 'В первые дни приёма'
|
|
58
|
+
],
|
|
59
|
+
socialProof: [
|
|
60
|
+
'9 из 10 рекомендуют', '9 из 10 мужчин рекомендуют', 'Тысячи уже выбрали',
|
|
61
|
+
'8 из 10 довольны результатом', 'Высокая оценка покупателей'
|
|
62
|
+
],
|
|
63
|
+
formula: [
|
|
64
|
+
'Натуральная формула', 'Натуральные ингредиенты', 'Без лишней химии', 'Тщательно подобранный состав',
|
|
65
|
+
'Продуманное сочетание компонентов'
|
|
66
|
+
],
|
|
67
|
+
qualityOfLife: [
|
|
68
|
+
'Спокойнее каждый день', 'Больше энергии', 'Увереннее в себе', 'Ровнее самочувствие',
|
|
69
|
+
'Поддержка вашего запроса'
|
|
70
|
+
]
|
|
71
|
+
};
|
|
72
|
+
/** Какие категории для какого подхода (по 1 из каждой категории, порядок случайный) */
|
|
73
|
+
const APPROACH_BULLET_CATEGORIES = {
|
|
74
|
+
'Эксперт / Авторитет': ['action', 'timeframe', 'socialProof'],
|
|
75
|
+
'Lifestyle / Момент приёма': ['timeframe', 'socialProof', 'action'], // срок + цифра + действие
|
|
76
|
+
'Эмоция / Портрет': ['qualityOfLife', 'action', 'timeframe'], // качество жизни + действие + срок
|
|
77
|
+
'Визуализация проблемы': ['action', 'timeframe', 'socialProof'],
|
|
78
|
+
'Power / Сила решения': ['action', 'timeframe', 'socialProof'], // действие + скорость + цифра
|
|
79
|
+
'Минимализм / Clean Big Text': ['action', 'timeframe', 'formula'],
|
|
80
|
+
'Врач / Эксперт': ['action', 'timeframe', 'socialProof'],
|
|
81
|
+
'Сплит До/После': ['action', 'timeframe', 'socialProof']
|
|
82
|
+
};
|
|
83
|
+
function pickOne(arr) {
|
|
84
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
85
|
+
}
|
|
86
|
+
function shuffle(arr) {
|
|
87
|
+
return [...arr].sort(() => Math.random() - 0.5);
|
|
88
|
+
}
|
|
89
|
+
/** Старая цена при -50%: удвоенная новая (для примеров в промпте генерации). */
|
|
90
|
+
function formatDoubledPriceForPrompt(priceStr) {
|
|
91
|
+
const nv = parseFloat(String(priceStr).replace(/\s/g, '').replace(',', '.'));
|
|
92
|
+
if (!Number.isFinite(nv) || nv <= 0)
|
|
93
|
+
return '';
|
|
94
|
+
const oldNum = nv * 2;
|
|
95
|
+
return Number.isInteger(oldNum)
|
|
96
|
+
? String(oldNum)
|
|
97
|
+
: (Math.round(oldNum * 100) / 100).toString().replace(/\.?0+$/, '');
|
|
98
|
+
}
|
|
99
|
+
function isBulgariaGeo(geo) {
|
|
100
|
+
const g = geo.trim().toLowerCase();
|
|
101
|
+
return g === 'bg' || /болгар|bulgar/.test(g);
|
|
102
|
+
}
|
|
103
|
+
function getBulgariaEuroCurrencyPromptBlock(geo, currencyHint) {
|
|
104
|
+
if (!isBulgariaGeo(geo))
|
|
105
|
+
return '';
|
|
106
|
+
const cur = (currencyHint === null || currencyHint === void 0 ? void 0 : currencyHint.trim()) ? ` (${currencyHint.trim()})` : '';
|
|
107
|
+
return `
|
|
108
|
+
🇧🇬 БОЛГАРИЯ — ВАЛЮТА (КРИТИЧНО):
|
|
109
|
+
- С 2026 года в Болгарии официальная валюта — **только евро** (€ / EUR)${cur}.
|
|
110
|
+
- **ЗАПРЕЩЕНО** рисовать или принимать устаревшие **лева**: лв, лв., BGN, «лев», «лева» — это ошибка устаревших данных модели, не актуальный рынок.
|
|
111
|
+
- На ценниках всегда **евро** из брифа; не подставляй болгарские левы «по привычке».
|
|
112
|
+
`;
|
|
113
|
+
}
|
|
114
|
+
/** Суффикс ` (1:1)` / ` (2:3)` / ` (4:5)` в подписи слота — убрать, чтобы сопоставить с CREO_APPROACHES. */
|
|
115
|
+
function getCreoApproachBaseNameFromImageLabel(approachLabel) {
|
|
116
|
+
return approachLabel.replace(/\s+\((1:1|2:3|4:5)\)\s*$/, '').trim() || approachLabel;
|
|
117
|
+
}
|
|
118
|
+
function creoApproachHasNoBullets(approach) {
|
|
119
|
+
return approach.bulletsMode === 'none';
|
|
120
|
+
}
|
|
121
|
+
function formatApproachNamesCond(names) {
|
|
122
|
+
return names.map(n => `"${n}"`).join(' или ');
|
|
123
|
+
}
|
|
124
|
+
/** Склеить опциональные строки промпта без пустых строк от тернарников. */
|
|
125
|
+
function joinPromptLines(...parts) {
|
|
126
|
+
return parts
|
|
127
|
+
.filter((p) => Boolean(p))
|
|
128
|
+
.map(p => (p.endsWith('\n') ? p : `${p}\n`))
|
|
129
|
+
.join('');
|
|
130
|
+
}
|
|
131
|
+
/** Строгие noBullets: без буллитов и без доп. элементов (HOOK+цена+скидка+CTA). */
|
|
132
|
+
function selectedStrictNoBulletsCond(approaches) {
|
|
133
|
+
return formatApproachNamesCond(approaches.filter(a => getEffectiveCreoNoBullets(a) && !a.allowsExtraText).map(a => a.name));
|
|
134
|
+
}
|
|
135
|
+
/** Все noBullets среди выбранных подходов. */
|
|
136
|
+
function selectedNoBulletsCond(approaches) {
|
|
137
|
+
return formatApproachNamesCond(approaches.filter(a => getEffectiveCreoNoBullets(a)).map(a => a.name));
|
|
138
|
+
}
|
|
139
|
+
/** Подходы с псевдо-кнопками возрастов среди выбранных. */
|
|
140
|
+
function selectedAgeButtonsCond(approaches) {
|
|
141
|
+
return formatApproachNamesCond(approaches.filter(a => a.allowsAgeButtons).map(a => a.name));
|
|
142
|
+
}
|
|
143
|
+
/** Подходы с доп. текстом, кроме квиза (числовой стек и т.п.). */
|
|
144
|
+
function selectedExtraTextNonQuizCond(approaches) {
|
|
145
|
+
return formatApproachNamesCond(approaches.filter(a => a.allowsExtraText && !a.allowsAgeButtons && a.offerMode !== 'window_sticker').map(a => a.name));
|
|
146
|
+
}
|
|
147
|
+
/** Подходы с витринным стикером вместо полного оффер-блока (offerMode === 'window_sticker'). */
|
|
148
|
+
function selectedWindowStickerCond(approaches) {
|
|
149
|
+
return formatApproachNamesCond(approaches.filter(a => a.offerMode === 'window_sticker').map(a => a.name));
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Итог: буллет-блок **не** использовать (0 буллетов), с учётом глобального и per-approach в promptOverrides
|
|
153
|
+
* и `bulletsMode` в `CREO_APPROACHES`.
|
|
154
|
+
*/
|
|
155
|
+
function getEffectiveCreoNoBullets(approach) {
|
|
156
|
+
if ((0, promptOverrides_1.getImageBulletsGlobalOff)())
|
|
157
|
+
return true;
|
|
158
|
+
const mode = (0, promptOverrides_1.getImageApproachNoBulletsMode)(approach.name);
|
|
159
|
+
if (mode === 'off')
|
|
160
|
+
return true;
|
|
161
|
+
if (mode === 'on')
|
|
162
|
+
return false;
|
|
163
|
+
return creoApproachHasNoBullets(approach);
|
|
164
|
+
}
|
|
165
|
+
/** Выбрать 3 случайных буллета по правилам подхода (1 из каждой категории, порядок случайный) */
|
|
166
|
+
function pickRandomBullets(approachName) {
|
|
167
|
+
const categories = APPROACH_BULLET_CATEGORIES[approachName];
|
|
168
|
+
if (!categories || categories.length < 3) {
|
|
169
|
+
// fallback: все категории
|
|
170
|
+
const all = Object.values(BULLET_BY_CATEGORY).flat();
|
|
171
|
+
return shuffle(all).slice(0, 3);
|
|
172
|
+
}
|
|
173
|
+
const bullets = categories.map(cat => pickOne(BULLET_BY_CATEGORY[cat] || []));
|
|
174
|
+
return shuffle(bullets);
|
|
175
|
+
}
|
|
176
|
+
// Debug logging — пишет в терминал Electron (или в console как fallback)
|
|
177
|
+
function _debugLog(...args) {
|
|
178
|
+
if (typeof localStorage === 'undefined' ||
|
|
179
|
+
localStorage.getItem('promptOverridesDebug') !== 'true') {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const api = typeof window !== 'undefined' ? window.electronAPI : null;
|
|
183
|
+
if (api === null || api === void 0 ? void 0 : api.log) {
|
|
184
|
+
api.log('log', '[PromptOverrides]', ...args).catch(() => console.log('[PromptOverrides]', ...args));
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
console.log('[PromptOverrides]', ...args);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
exports.PAIR_APPROACH_POOL = [
|
|
191
|
+
{
|
|
192
|
+
name: 'болевая точка',
|
|
193
|
+
titleApproach: 'одна ясная боль (не две проблемы в одном заголовке). Усиливай через несправедливость / ощущение «так несправедливо» (устал бороться, снова срыв, тело не слушается) — не только сухое перечисление симптомов. ЗАГОЛОВОК = КОНСТАТАЦИЯ, не вопрос: ЗАПРЕЩЕНО заканчивать на «почему?», «зачем?», «why?» и подобное — боль называешь фактом, не спрашиваешь',
|
|
194
|
+
textApproach: 'Одна центральная проблема за текст — не распыляйся на несколько болей. ЗАПРЕЩЕНО перечислять ингредиенты, состав, matcha/MCT/«формулу» — это территория «авторитет/экспертиза», не болевой точки. Опиши дискомфорт и как продукт снимает именно эту боль; без каталога компонентов.',
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: 'трансформация до/после',
|
|
198
|
+
titleApproach: 'контраст СОСТОЯНИЙ и ощущений до/после (вздутие/усталость → лёгкость, тяжесть → контроль, «не узнаю себя в зеркале» → спокойствие) с якорем во времени во фразе, но БЕЗ цифр на весах. ЗАПРЕЩЕНО в заголовке: −X kg, «минус N кг», весы, любой явный минус килограммов (для похудения такой акцент — только у testimonial и только если продукт явно про вес)',
|
|
199
|
+
textApproach: 'СТРОГО от первого лица (на языке GEO — естественное «я» для локали). Это не отзыв с именем — это МОЙ контраст «как было плохо / как стало лучше» по телу и эмоциям. ЗАПРЕЩЕНО копировать формат отзыва: не начинай как реклама «я попробовала продукт и минус X кг» подряд; сначала ощущения и жизнь до/после, продукт — связка, а не пересказ цифр с весов (цифры веса допустимы в тексте лишь второстепенно, если уместно; акцент — на смене состояния). ЗАПРЕЩЕНО соцдоказательство («многие отмечают», «тысячи уже выбрали» вместо личной истории).',
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
name: 'testimonial',
|
|
203
|
+
isTestimonial: true,
|
|
204
|
+
titleApproach: 'короткая «живая» фраза с **конкретным результатом по теме продукта** и сроком (7–14 дней). Цифры −кг, весы, «минус на весах» — **только** если продукт явно про похудение / контроль веса. Для любых офферов не про вес — результат = облегчение симптомов, комфорт, сон, подвижность, меньше дискомфорта (без выдуманных кг). Это отличает testimonial от «трансформации». НЕ используй «Имя, возраст:» в заголовке — только в тексте',
|
|
205
|
+
textApproach: `Это единственный подход-ОТЗЫВ: читатель должен поверить в реального человека.
|
|
206
|
+
* Обязательно начало текста с «Имя, возраст:» (формат на языке GEO, например «Анна, 49 лет:», «Олег, 41 год:»)
|
|
207
|
+
* История только от первого лица после имени
|
|
208
|
+
* Конкретный результат с таймингом (7–14 дней), релевантный категории продукта; килограммы упоминай только если оффер действительно про вес/похудение
|
|
209
|
+
* Заканчивается приглашением попробовать + CTA`,
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
name: 'срочность/дефицит',
|
|
213
|
+
titleApproach: 'ТОЛЬКО дефицит оффера: время до конкретного дедлайна, остаток штук, «до полуночи», «осталось N упаковок» — ЗАПРЕЩЕНО в заголовке проблема, тело, продукт, «лишние кг», категория товара. Не баннер магазина — конкретная граница (день, час, число мест)',
|
|
214
|
+
textApproach: 'Начни с конкретного сигнала ограниченности — времени или количества («только сегодня», «последние упаковки», «Осталось 12 упаковок», «Акция до конца дня» — всё на языке GEO). Весь текст строится ИСКЛЮЧИТЕЛЬНО вокруг дефицита или дедлайна: осталось мало, время заканчивается, потом будет дороже или не будет вообще. ЗАПРЕЩЕНО упоминать состав, ингредиенты, свойства или пользу продукта — только ограниченность оффера. CTA максимально срочный.',
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: 'социальное доказательство',
|
|
218
|
+
titleApproach: 'одна ЧИТАЕМАЯ фраза с крупной цифрой (уровень: «Уже 50 000 женщин выбрали … 🔥» на языке GEO) — грамматика и смысл на языке GEO должны сходиться; читатель понимает фразу с первого раза. ЗАПРЕЩЕНО несвязные склейки («9 из 10 выбирают контроль 🔥 голод» — бессмыслица) и обрывки, где цифра + существительные не составляют нормального высказывания',
|
|
219
|
+
textApproach: 'Начни с цифры или массового факта («Уже 50 000 клиентов», «9 из 10 отмечают разницу» — на языке GEO). Акцент на том, что проблему уже решили тысячи — и ты тоже можешь.',
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
name: 'любопытство/интрига',
|
|
223
|
+
titleApproach: 'провокационный вопрос или утверждение, которое ломает сразу ДВА привычных решения (например диета и спорт одновременно) — но ОДНОЙ ЦЕЛЬНОЙ фразой: связный синтаксис, без рубки на обрывки через запятую и эмодзи посередине. Пример уровня на русском для тона: «Диета и зал, а живот всё равно? 🤔» — на GEO перепиши естественно; не три оторванных куска',
|
|
224
|
+
textApproach: 'Начни с провокационного вопроса или неожиданного инсайта («Знаете, почему обычные средства не помогают?», «А вы знали, что…» — на языке GEO). Раскрой неочевидный факт о проблеме или механизме решения и выведи к продукту.',
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
name: 'авторитет/экспертиза',
|
|
228
|
+
titleApproach: 'information gap: в заголовке ЗАПРЕЩЕНО называть ингредиенты и раскрывать метод/механизм напрямую — никаких matcha, MCT, «зелёный чай», «формула с…», «натуральный метод для…», «ускорить обмен веществ», «поддерживает обмен веществ» и т.п.; иначе ответ уже в заголовке и клик не нужен. Подай состав или подход как тайну / открытие / «что скрывают» / «почему это не то же самое, что обычные средства» — без конкретики, ответ только в основном тексте. ЗАПРЕЩЕНЫ эмодзи-подсказки по составу (например 🍵, если по смыслу выдаёт чай), если они заменяют то, что должен открыть текст. Не закрывай интригу сухими схемами вроде «Почему X и Y поддерживают…»',
|
|
229
|
+
textApproach: 'Начни с ФАКТА/утверждения об экспертизе («Итальянская рецептура», «Произведено в Италии», «3 натуральных компонента», «Разработано фармацевтами» — перенеси смысл на язык GEO). Акцент на составе, происхождении или механизме действия. Почему это работает — объясни просто и убедительно.',
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: 'страх бездействия',
|
|
233
|
+
titleApproach: 'узнаваемый паттерн промедления — ОДНА СВЯЗНАЯ фраза (допустимы многоточие, союз «но», тире), а не перечень обрывков через запятую. Пример уровня: «Отложила на понедельник… а голод не ждёт 😣» — на GEO перепиши естественно; смысл течёт от начала к концу',
|
|
234
|
+
textApproach: 'Начни с описания негативного сценария бездействия («С каждым днём становится хуже…», «Если не взять под контроль сейчас…»). Покажи, что проблема прогрессирует. Финальный CTA — ТОЛЬКО про заботу о себе / начать сейчас / не откладывать (на языке GEO). ЗАПРЕЩЕНЫ прямые призывы к заказу в финале: «закажи», «закажи сейчас», «купи», «купи сейчас», «оформи заказ» — вместо них: взять под контроль, сделать первый шаг, начать сегодня и т.п.',
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
name: 'прямой оффер/выгода',
|
|
238
|
+
titleApproach: 'выгода в заголовке = **-50%** как есть (знак процента), плюс по желанию 2–4 слова срочности на языке GEO («только сегодня», «сейчас»). ОБЯЗАТЕЛЬНО минимум один эмодзи (💸 🔥 ✨ 🎁 ⏳ 📦). **Не придумывай** другую механику: никаких «2-й пакет», «вторая упаковка», «полцены» вместо простого **-50%**, если в задании пользователя явно не сказано иначе. **-50% = просто -50%.**',
|
|
239
|
+
textApproach: 'Коротко про сделку: **-50% не перефразируй** длинно («платишь половину», «акция на сегодня», «скидка на вторую упаковку»), если пользователь этого не писал — повтори **-50%** и добавь одну короткую фразу срочности + CTA. ЗАПРЕЩЕНО расписывать математику скидки и выдумывать условия акции. ЗАПРЕЩЕНО объяснять пользу продукта или боли — только **-50%**, срочность, CTA.',
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
name: 'ситуационный/узнаваемый момент',
|
|
243
|
+
titleApproach: 'одна яркая узнаваемая сцена в 1–2 коротких связных сегментах (лучше одна картинка), без перечня симптомов через запятую. Пример уровня: «После обеда джинсы жмут 😩» — на GEO перепиши естественно; сразу видно момент и боль; ЗАПРЕЩЕНО нагромождать «после обеда 😩 джинсы, живот, тесно» отдельными ярлыками',
|
|
244
|
+
textApproach: 'Начни с конкретной жизненной сцены, где проблема ощущается («[ключевой симптом категории продукта]…», «Вечером перед сном не можешь уснуть из-за дискомфорта…» — адаптируй под категорию). Создай узнаваемую ситуацию — читатель должен сказать «это про меня» — и предложи решение.',
|
|
245
|
+
},
|
|
246
|
+
];
|
|
247
|
+
// Обратная совместимость для PromptManagerDialog
|
|
248
|
+
/** @deprecated Use PAIR_APPROACH_POOL */
|
|
249
|
+
exports.TITLES_APPROACH_POOL = exports.PAIR_APPROACH_POOL.map(p => `[${p.name}] — ${p.titleApproach}`);
|
|
250
|
+
/** @deprecated Use PAIR_APPROACH_POOL */
|
|
251
|
+
exports.TEXTS_APPROACH_POOL = exports.PAIR_APPROACH_POOL.map(p => ({ label: p.name, instruction: p.textApproach, isTestimonial: p.isTestimonial }));
|
|
252
|
+
/**
|
|
253
|
+
* Промпт для генерации заголовков (titles)
|
|
254
|
+
*/
|
|
255
|
+
function getTitlesSystemPrompt(geo, noOverride, count = 3) {
|
|
256
|
+
if (!noOverride) {
|
|
257
|
+
const override = (0, promptOverrides_1.getPromptOverride)('getTitlesSystemPrompt');
|
|
258
|
+
if ((override === null || override === void 0 ? void 0 : override.enabled) && override.customPrompt) {
|
|
259
|
+
_debugLog('✅ Using CUSTOM getTitlesSystemPrompt');
|
|
260
|
+
return override.customPrompt
|
|
261
|
+
.replace(/\$\{geo\}/g, geo)
|
|
262
|
+
.replace(/\$\{count\}/g, String(count))
|
|
263
|
+
.replace(/\$\{n\}/g, String(count));
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const n = Math.min(10, Math.max(2, count));
|
|
267
|
+
const pairs = exports.PAIR_APPROACH_POOL.slice(0, n);
|
|
268
|
+
const distributionLine = pairs
|
|
269
|
+
.map((p, i) => `Заголовок ${i + 1} → [${p.name}]: ${p.titleApproach}`)
|
|
270
|
+
.join(', ');
|
|
271
|
+
const maxMedTerms = Math.max(1, Math.floor(n / 3));
|
|
272
|
+
return `Ты — эксперт-копирайтер, специализирующийся на рекламе в Facebook. Твоя задача — создать ровно ${n} идеальных продающих заголовка для рекламы в Facebook на языке ${geo}.
|
|
273
|
+
|
|
274
|
+
ВАЖНО — СИСТЕМА ПАРЫ (заголовок + текст):
|
|
275
|
+
- Каждый заголовок образует ПАРУ с соответствующим текстом (Заголовок 1 ↔ Текст 1, и т.д.)
|
|
276
|
+
- Заголовок и текст одной пары используют ОДИН угол/подход — они дополняют друг друга, а не повторяют
|
|
277
|
+
- Заголовок — короткий крючок, текст — раскрытие того же угла с деталями и CTA
|
|
278
|
+
|
|
279
|
+
КРИТИЧЕСКОЕ ТРЕБОВАНИЕ К РАЗНООБРАЗИЮ:
|
|
280
|
+
- Фиксированное распределение подходов: ${distributionLine}
|
|
281
|
+
- Каждый заголовок ДОЛЖЕН использовать совершенно другой рекламный подход и стратегию
|
|
282
|
+
- Заголовки должны иметь МИНИМАЛЬНОЕ пересечение в сообщениях, углах или эмоциональных триггерах
|
|
283
|
+
- Вместе все ${n} заголовка должны охватывать различные рекламные подходы, такие как:
|
|
284
|
+
* Болевая точка (прямой симптом, без решения в заголовке)
|
|
285
|
+
* Трансформация до/после (контраст жизни до и после)
|
|
286
|
+
* Testimonial (намёк на личный результат)
|
|
287
|
+
* Срочность/дефицит (дедлайн по офферу или запасам)
|
|
288
|
+
* Социальное доказательство (цифры людей, которые решили проблему)
|
|
289
|
+
* Любопытство/интрига (секрет, почему не работают другие методы)
|
|
290
|
+
* Авторитет/экспертиза (состав, происхождение, механизм)
|
|
291
|
+
* Страх бездействия (дедлайн по здоровью, последствия промедления)
|
|
292
|
+
* Прямой оффер/выгода (цена, скидка, условия сделки)
|
|
293
|
+
* Ситуационный/узнаваемый момент (конкретная сцена из жизни)
|
|
294
|
+
- Избегай повторения похожих концепций, слов или углов в заголовках
|
|
295
|
+
- Каждый заголовок должен нацеливаться на разный психологический триггер или мотивацию к покупке
|
|
296
|
+
|
|
297
|
+
Требования к стилю:
|
|
298
|
+
- Копия должна звучать как прямая реклама, а не как рассказ
|
|
299
|
+
- Избегай поэтического, метафорического, расплывчатого или кинематографического формулирования
|
|
300
|
+
- Предпочитай короткие, конкретные, рекламные фразы
|
|
301
|
+
- Избегай клише, тона чуда или преувеличенных выражений
|
|
302
|
+
- Заголовки должны звучать как естественные рекламные сообщения, написанные человеком-медиабайером
|
|
303
|
+
- Избегай структур с набивкой ключевых слов, роботического тона или паттернов "Симптом + Продукт + Скидка"
|
|
304
|
+
- Заголовки должны читаться как естественные человеческие рекламные фразы, а не как строки ключевых слов или списки продуктов
|
|
305
|
+
- Язык должен быть простым, естественным и дружелюбным к потребителю
|
|
306
|
+
- Избегай академических, синтетических или звучащих как ИИ слов и фраз
|
|
307
|
+
- НЕ упоминай название продукта в заголовке — оно уже на креативе. Заголовок = только боль + решение/триггер
|
|
308
|
+
|
|
309
|
+
Технические требования:
|
|
310
|
+
- Каждый заголовок может быть 1–4 строки. Допускается до 12 слов (при многострочности)
|
|
311
|
+
- Каждый заголовок предпочтительно до 55 символов в строке. При необходимости для разнообразия допускается до 60 символов в строке
|
|
312
|
+
- ЗАПРЕЩЕНО использовать двоеточие (:) в заголовках. Используй тире (—) или переформулируй заголовок без двоеточия. Если в заголовке есть двоеточие — это критическая ошибка, перепиши заголовок
|
|
313
|
+
- Используй 1-2 эмодзи естественно внутри заголовка, не только в конце. Эмодзи должны заменять или визуально отмечать смысл (эмоция, действие, предупреждение), а не украшать или заполнять пространство. Максимум 1-2 на строку
|
|
314
|
+
- Избегай эмодзи ⚠️ и 🚨 — они ассоциируются с опасностью. Для привлечения внимания используй 👉, ✅, 🌿, ⏳
|
|
315
|
+
- КРИТИЧНО: Заголовок должен быть **в одной теме с продуктом** из задания пользователя: читатель сразу понимает, какую потребность или боль вы закрываете (симптом, ситуация или ясная выгода в этой нише). Запрещено подменять другую вертикаль здоровья или «типичную» боль соседней категории. Нельзя оставаться на уровне общих слов («легче», «лучше», «помощь») без привязки к теме оффера — перепиши
|
|
316
|
+
- Используй знания лучших практик рекламного копирайтинга
|
|
317
|
+
- После создания проверь их правильность и разнообразие
|
|
318
|
+
- Верни только заголовки, по одному на строку, без нумерации или буллетов
|
|
319
|
+
- Заголовки должны быть на языке ${geo}
|
|
320
|
+
- Верни только финальные результаты. Не добавляй объяснений или комментариев`;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Промпт для генерации текстов (descriptions)
|
|
324
|
+
*/
|
|
325
|
+
function getTextsSystemPrompt(geo, noOverride, count = 3) {
|
|
326
|
+
if (!noOverride) {
|
|
327
|
+
const override = (0, promptOverrides_1.getPromptOverride)('getTextsSystemPrompt');
|
|
328
|
+
if ((override === null || override === void 0 ? void 0 : override.enabled) && override.customPrompt) {
|
|
329
|
+
_debugLog('✅ Using CUSTOM getTextsSystemPrompt');
|
|
330
|
+
return override.customPrompt
|
|
331
|
+
.replace(/\$\{geo\}/g, geo)
|
|
332
|
+
.replace(/\$\{count\}/g, String(count))
|
|
333
|
+
.replace(/\$\{n\}/g, String(count));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const n = Math.min(10, Math.max(2, count));
|
|
337
|
+
const pairs = exports.PAIR_APPROACH_POOL.slice(0, n);
|
|
338
|
+
const hasTestimonial = pairs.some(p => p.isTestimonial);
|
|
339
|
+
const maxMedTerms = Math.max(1, Math.floor(n / 3));
|
|
340
|
+
const distributionLines = pairs
|
|
341
|
+
.map((p, i) => `- Текст ${i + 1} → [${p.name}]. ${p.textApproach}`)
|
|
342
|
+
.join('\n');
|
|
343
|
+
const deadlineNote = n >= 2
|
|
344
|
+
? `- В Тексте 1 ИЛИ Тексте 2 ОБЯЗАТЕЛЬНО укажи ожидаемый срок результата 7–14 дней (в языке GEO).`
|
|
345
|
+
: `- В Тексте 1 ОБЯЗАТЕЛЬНО укажи ожидаемый срок результата 7–14 дней (в языке GEO).`;
|
|
346
|
+
return `Ты — эксперт-копирайтер, специализирующийся на рекламе в Meta Ads (Facebook/Instagram). Твоя задача — создать ровно ${n} идеальных продающих рекламных текста для Meta Ads на языке ${geo}.
|
|
347
|
+
|
|
348
|
+
ВАЖНО — СИСТЕМА ПАРЫ (заголовок + текст):
|
|
349
|
+
- Каждый текст образует ПАРУ с заголовком того же номера (Текст 1 ↔ Заголовок 1, и т.д.)
|
|
350
|
+
- Заголовок и текст одной пары используют ОДИН угол/подход — текст раскрывает то, что заголовок зацепил
|
|
351
|
+
- Текст НЕ должен дословно повторять заголовок, но должен развивать тот же угол глубже
|
|
352
|
+
|
|
353
|
+
КРИТИЧЕСКОЕ РАСПРЕДЕЛЕНИЕ ПОДХОДОВ И СТАРТОВ:
|
|
354
|
+
${distributionLines}
|
|
355
|
+
- Каждый текст строго следует подходу своей пары (не меняй углы местами)
|
|
356
|
+
- Тексты разных пар должны иметь МИНИМАЛЬНОЕ пересечение в болях/триггерах${hasTestimonial ? '' : ''}
|
|
357
|
+
|
|
358
|
+
КРИТИЧНО — СРОК + ОФФЕР ДЛЯ КОНВЕРСИИ:
|
|
359
|
+
${deadlineNote}
|
|
360
|
+
- Опционально (не обязательно): усили CTA упоминанием **-50%** как есть и ограниченности по времени («только сегодня/ограничено») — коротко, в конце; **не** заменяй -50% на «полцены», «вторая упаковка» и т.п., если это не в задании.${hasTestimonial ? '' : ''}
|
|
361
|
+
|
|
362
|
+
Требования к стилю и тону:
|
|
363
|
+
- Копия должна звучать как прямая реклама, а не как рассказ
|
|
364
|
+
- Избегай поэтического, метафорического, расплывчатого или кинематографического формулирования
|
|
365
|
+
- Предпочитай короткие, конкретные, рекламные фразы
|
|
366
|
+
- Тон: уверенный, убедительный, ориентированный на конверсию. Текст должен подталкивать пользователя к действию, а не просто информировать. Пиши жёстче и срочнее: короткие рубленые фразы, императивы («не жди», «действуй сейчас»), FOMO допустим
|
|
367
|
+
- Избегай тона коучинга, вдохновляющего или wellness-стиля жизни
|
|
368
|
+
- Используй эмоциональные триггеры: дискомфорт, усталость, снижение энергии, чувство перегруженности и т.д.
|
|
369
|
+
- Используй убедительные и продающие формулировки, не слишком стерильные
|
|
370
|
+
- Избегай клише, тона чуда или преувеличенных выражений
|
|
371
|
+
- Язык должен быть простым, естественным и дружелюбным к потребителю
|
|
372
|
+
- Избегай академических, синтетических или звучащих как ИИ слов и фраз
|
|
373
|
+
- Избегай искусственного или неестественного формулирования, которое реальные рекламодатели не использовали бы
|
|
374
|
+
- Если фраза звучит синтетически или академически — перепиши её
|
|
375
|
+
Требования к содержанию:
|
|
376
|
+
- КРИТИЧНО: Держи каждый текст кратким — цель примерно 150-280 символов на текст. Тексты в стиле отзыва могут использовать до 300 символов при необходимости для естественного повествования. Будь эффектным, но коротким
|
|
377
|
+
- Если текст длиннее 280 символов (или 300 для стиля отзыва) — сожми и перепиши, сохраняя смысл
|
|
378
|
+
- КРИТИЧНО: Текст держи **в той же теме, что продукт** из задания: конкретная боль, ситуация или выгода, которые очевидно относятся к этому офферу, без ухода в соседние ниши. Если тема размыта или общая — перепиши
|
|
379
|
+
- КРИТИЧНО: Каждый текст должен заканчиваться сильным и явным призывом к действию (кликни, попробуй сейчас, закажи сегодня, узнай больше и т.д.)
|
|
380
|
+
- Избегай слабых окончаний или информационного тона. Слабые или нейтральные окончания не допускаются
|
|
381
|
+
- CTA должен быть “нажимным”: допускаются формулировки «не откладывай», «последний шанс», «только сегодня», «забери -50%» (всё строго на языке GEO). Если пишешь скидку — **-50%** буквально, без выдуманной механики акции
|
|
382
|
+
- В каждом тексте строго следуй заданному формату старта согласно его подходу (см. распределение выше)
|
|
383
|
+
- Если ингредиенты предоставлены в дополнительной информации, упоминай их ТОЛЬКО если они естественно подходят выбранному рекламному подходу. Например: подходы авторитета/экспертизы выигрывают от деталей ингредиентов, в то время как подходы срочности/эмоционального триггера могут не нуждаться в них. Упоминай только релевантные ингредиенты, не обязательно все из них. Если ингредиенты не подходят подходу или не предоставлены — полностью пропусти их упоминание и не изобретай и не упоминай никакие ингредиенты
|
|
384
|
+
- Добавляй только существенные поддерживающие детали, которые усиливают убеждение или ясность, а не заполнители или общие утверждения. Будь кратким и прямым
|
|
385
|
+
- Используй 1-4 эмодзи естественно внутри текста, не только в конце. Эмодзи должны заменять или визуально отмечать смысл (эмоция, действие, предупреждение), а не украшать или заполнять пространство. Максимум 1-2 на строку
|
|
386
|
+
- Избегай эмодзи ⚠️ и 🚨 — они ассоциируются с опасностью. Для привлечения внимания используй 👉, ✅, 🌿, ⏳
|
|
387
|
+
${getDelicateTopicsAndQuantitativeClaimsRule()}
|
|
388
|
+
- Избегай повторения полного названия продукта более 2 раз в одном тексте. Используй местоимения или более короткие ссылки при необходимости
|
|
389
|
+
|
|
390
|
+
Требования к формату:
|
|
391
|
+
- Разделяй разные тексты пустой строкой (двойной перевод строки)
|
|
392
|
+
- КРИТИЧНО: Каждый текст ДОЛЖЕН быть многострочным с естественными переносами строк. Используй переносы строк для разделения предложений, выделения ключевых моментов или создания визуальной структуры. НЕ пиши описания как одиночные непрерывные строки
|
|
393
|
+
- КРИТИЧНО: Все тексты ДОЛЖНЫ быть написаны на языке ${geo}. Используй точное название языка "${geo}" — не используй русский, английский или любой другой язык
|
|
394
|
+
- ВСЕ слова в тексте должны быть на языке GEO. Английские фразы вроде «Made in Italy», «Made in Germany» ЗАПРЕЩЕНЫ — используй перевод на язык GEO (например «Произведено в Италии», «Сделано в Германии» и аналоги).
|
|
395
|
+
- После создания проверь их правильность И убедись в максимальном разнообразии между текстами
|
|
396
|
+
- Верни только финальные результаты. Не добавляй объяснений или комментариев`;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Промпт пользователя для генерации заголовков и текстов
|
|
400
|
+
*/
|
|
401
|
+
function getUserPrompt(product, geo, additionalInfo, type, noOverride, count = 3) {
|
|
402
|
+
if (!noOverride) {
|
|
403
|
+
const override = (0, promptOverrides_1.getPromptOverride)('getUserPrompt');
|
|
404
|
+
if ((override === null || override === void 0 ? void 0 : override.enabled) && override.customPrompt) {
|
|
405
|
+
return override.customPrompt
|
|
406
|
+
.replace(/\$\{product\}/g, product)
|
|
407
|
+
.replace(/\$\{geo\}/g, geo)
|
|
408
|
+
.replace(/\$\{additionalInfo\}/g, additionalInfo.trim() || '')
|
|
409
|
+
.replace(/\$\{type\}/g, type)
|
|
410
|
+
.replace(/\$\{count\}/g, String(count))
|
|
411
|
+
.replace(/\$\{n\}/g, String(count));
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
const n = Math.min(10, Math.max(2, count));
|
|
415
|
+
const taskText = type === 'titles'
|
|
416
|
+
? `Создай ${n} идеальных продающих заголовка для рекламы в Facebook.`
|
|
417
|
+
: `Создай ${n} идеальных продающих текста для рекламы в Facebook.`;
|
|
418
|
+
return `Продукт: ${product}
|
|
419
|
+
Локация: ${geo}${additionalInfo.trim() ? `\n\nДополнительная информация:\n${additionalInfo}` : ''}
|
|
420
|
+
|
|
421
|
+
${taskText}`;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Единый системный промпт для генерации N пар «заголовок + текст» одним запросом
|
|
425
|
+
*/
|
|
426
|
+
function getPairsSystemPrompt(geo, noOverride, count = 3, selectedIndices) {
|
|
427
|
+
// Resolve which approaches to use
|
|
428
|
+
const resolvedPairs = selectedIndices && selectedIndices.length >= 1
|
|
429
|
+
? selectedIndices.map(i => exports.PAIR_APPROACH_POOL[i]).filter(Boolean)
|
|
430
|
+
: exports.PAIR_APPROACH_POOL.slice(0, Math.min(10, Math.max(2, count)));
|
|
431
|
+
const n = resolvedPairs.length;
|
|
432
|
+
if (!noOverride) {
|
|
433
|
+
const override = (0, promptOverrides_1.getPromptOverride)('getPairsSystemPrompt');
|
|
434
|
+
if ((override === null || override === void 0 ? void 0 : override.enabled) && override.customPrompt) {
|
|
435
|
+
_debugLog('✅ Using CUSTOM getPairsSystemPrompt');
|
|
436
|
+
return override.customPrompt
|
|
437
|
+
.replace(/\$\{geo\}/g, geo)
|
|
438
|
+
.replace(/\$\{count\}/g, String(n))
|
|
439
|
+
.replace(/\$\{n\}/g, String(n));
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const pairs = resolvedPairs;
|
|
443
|
+
const maxMedTerms = Math.max(1, Math.floor(n / 3));
|
|
444
|
+
const hasTestimonial = pairs.some(p => p.isTestimonial);
|
|
445
|
+
const distributionLines = pairs
|
|
446
|
+
.map((p, i) => `Пара ${i + 1} → [${p.name}]:\n Заголовок: ${p.titleApproach}\n Текст: ${p.textApproach}`)
|
|
447
|
+
.join('\n');
|
|
448
|
+
const hasUrgencyScarcity = pairs.some(p => p.name === 'срочность/дефицит');
|
|
449
|
+
const hasFearInaction = pairs.some(p => p.name === 'страх бездействия');
|
|
450
|
+
const hasSocialProof = pairs.some(p => p.name === 'социальное доказательство');
|
|
451
|
+
const hasAuthorityExpertise = pairs.some(p => p.name === 'авторитет/экспертиза');
|
|
452
|
+
const hasDirectOffer = pairs.some(p => p.name === 'прямой оффер/выгода');
|
|
453
|
+
const hasTransformAndTestimonial = pairs.some(p => p.name === 'трансформация до/после') && pairs.some(p => p.isTestimonial);
|
|
454
|
+
const deadlineNote = n >= 2
|
|
455
|
+
? `- В Тексте 1 ИЛИ Тексте 2 ОБЯЗАТЕЛЬНО укажи ожидаемый срок результата 7–14 дней (на языке ${geo}).`
|
|
456
|
+
: `- В Тексте 1 ОБЯЗАТЕЛЬНО укажи ожидаемый срок результата 7–14 дней (на языке ${geo}).`;
|
|
457
|
+
return `Ты — эксперт-копирайтер, специализирующийся на рекламе в Meta Ads (Facebook/Instagram). Создай ровно ${n} пар «заголовок + текст» для рекламы на языке ${geo}.
|
|
458
|
+
|
|
459
|
+
ФОРМАТ ОТВЕТА (строго соблюдай, без лишних символов):
|
|
460
|
+
ЗАГОЛОВОК 1: <текст заголовка>
|
|
461
|
+
ТЕКСТ 1: <текст объявления>
|
|
462
|
+
|
|
463
|
+
ЗАГОЛОВОК 2: <текст заголовка>
|
|
464
|
+
ТЕКСТ 2: <текст объявления>
|
|
465
|
+
|
|
466
|
+
... и так для всех ${n} пар. Каждая пара отделена пустой строкой.
|
|
467
|
+
|
|
468
|
+
КРИТИЧНО ДЛЯ РАЗБОРА:
|
|
469
|
+
- Служебные метки в начале строки пиши РОВНО как в примере: слово «ЗАГОЛОВОК» целиком кириллицей (не ZAG, не смесь латиницы и кириллицы), слово «ТЕКСТ» целиком кириллицей.
|
|
470
|
+
- Не вставляй строки «ЗАГОЛОВОК N:» внутрь текста объявления; каждый заголовок — отдельная строка перед своим «ТЕКСТ N:».
|
|
471
|
+
- Контент объявления (заголовок и текст) — на языке ${geo}; только метки ЗАГОЛОВОК/ТЕКСТ остаются кириллицей как шаблон.
|
|
472
|
+
- Язык ${geo}: если это название страны — пиши на **официальном языке этой страны**; не путай близкие коды и локали (например Словения ≠ Словакия, хорватский ≠ словенский).
|
|
473
|
+
|
|
474
|
+
РАСПРЕДЕЛЕНИЕ ПОДХОДОВ ПО ПАРАМ:
|
|
475
|
+
${distributionLines}
|
|
476
|
+
|
|
477
|
+
ПРАВИЛО ПАРЫ — заголовок и текст используют ОДИН угол:
|
|
478
|
+
- Заголовок — короткий крючок (боль или триггер)
|
|
479
|
+
- Текст — раскрывает тот же угол глубже, добавляет детали, заканчивается CTA
|
|
480
|
+
- Текст НЕ повторяет заголовок дословно, но развивает его смысл
|
|
481
|
+
- Не подмешивай чужие углы: например в «трансформация до/после» не используй формулировки соцдоказательства («многие отмечают», «клиенты говорят»)
|
|
482
|
+
${hasTransformAndTestimonial ? '\n- РАЗВЕДЕНИЕ «трансформация до/после» и «testimonial» в одном ответе: у трансформации заголовок = контраст ощущений/состояния (без −кг и без «минус X kg за N дней»); у testimonial −кг и весы в заголовке — **только если продукт в задании явно про похудение**; иначе testimonial = конкретный симптомный/комфортный результат + срок. Не делай два заголовка в одном формате «цифра + срок на весах».' : ''}
|
|
483
|
+
|
|
484
|
+
ТРЕБОВАНИЯ К ЗАГОЛОВКУ:
|
|
485
|
+
- До 55–60 символов, максимум 6–7 слов
|
|
486
|
+
- Цельность: заголовок читается как одно высказывание (или один связный вопрос целиком). ЗАПРЕЩЕНО склеивать несвязные ярлыки запятыми ради ключевых слов; эмодзи не должно разрывать грамматику так, что фраза перестаёт быть человеческой
|
|
487
|
+
- ЗАПРЕЩЕНО двоеточие (:) — используй тире (—) или переформулируй
|
|
488
|
+
- 1–2 эмодзи естественно (часто в конце фразы или после целого смыслового блока); избегай ⚠️ и 🚨${hasDirectOffer ? '\n- Для пары «прямой оффер/выгода» эмодзи в заголовке ОБЯЗАТЕЛЕН (минимум один) — визуально вровень с остальными парами набора' : ''}
|
|
489
|
+
- Заголовок с явной привязкой к теме продукта из задания (симптом, ситуация или понятная выгода в этой нише), не абстрактный слоган${hasUrgencyScarcity ? '\n- ИСКЛЮЧЕНИЕ: для пары с подходом «срочность/дефицит» в заголовке ЗАПРЕЩЕНЫ симптомы, проблема, тело, продукт — только лимит оффера (время, количество, дедлайн)' : ''}${hasDirectOffer ? '\n- ИСКЛЮЧЕНИЕ: для пары «прямой оффер/выгода» болевая конкретика в заголовке **не обязательна**; ядро — **-50%** (+эмодзи + короткая срочность). **Не выдумывай** «2-й пакет / вторая упаковка / полцены» без данных в задании — **-50% это просто -50%.**' : ''}${hasAuthorityExpertise ? '\n- Пара «авторитет/экспертиза»: заголовок держит information gap — без ингредиентов и без прямого названия механизма; состав и «как это работает» — только в тексте пары' : ''}
|
|
490
|
+
- НЕ упоминай название продукта — заголовок = боль + триггер${hasUrgencyScarcity ? ' (кроме пары «срочность/дефицит»: там заголовок = только дефицит/дедлайн, без продукта и без боли)' : ''}${hasSocialProof ? '\n- Исключение: в паре «социальное доказательство» название продукта в заголовке допустимо, если оно входит в цельную фразу про массовый выбор (например «Уже N тысяч человек выбрали [продукт]» на языке GEO)' : ''}
|
|
491
|
+
- Звучит как живая рекламная фраза, а не строка ключевых слов
|
|
492
|
+
|
|
493
|
+
ТРЕБОВАНИЯ К ТЕКСТУ:
|
|
494
|
+
- 150–280 символов (testimonial — до 300)${hasDirectOffer ? '; для пары «прямой оффер/выгода» достаточно **120–200** символов, если текст = **-50%** + срочность + CTA без воды' : ''}
|
|
495
|
+
- Та же тема, что в заголовке пары: конкретика боли/ситуации или выгоды в нише продукта (для «срочность/дефицит» в тексте допустимо слабее, если весь фокус — на лимите оффера)${hasDirectOffer ? '; для «прямой оффер/выгода» болевая конкретика **не обязательна** — фокус на **-50%** и CTA' : ''}
|
|
496
|
+
- Сильный явный CTA в конце («кликни», «попробуй сейчас», «закажи», «не жди»)${hasFearInaction ? '\n- ИСКЛЮЧЕНИЕ: для пары «страх бездействия» финальная фраза — не заказ, а забота о себе / начать сейчас; без «закажи», «купи», «оформи заказ» в конце' : ''}
|
|
497
|
+
- Короткие рубленые фразы, императивы, FOMO допустим${hasTestimonial ? '\n- Testimonial: строго от первого лица, начинается с «Имя, возраст:», конкретный результат с таймингом; тема результата = та же, что в продукте из задания; не минус кг, если продукт не про вес' : ''}
|
|
498
|
+
- Ингредиенты и состав из доп. информации — только в углах «авторитет/экспертиза» (и сходных); в «болевой точке» и чисто эмоциональных углах состав не перечислять
|
|
499
|
+
${deadlineNote}
|
|
500
|
+
|
|
501
|
+
ОБЩИЕ ТРЕБОВАНИЯ:
|
|
502
|
+
- Язык: ${geo} — все тексты строго на этом языке
|
|
503
|
+
- Релевантность продукту из пользовательского сообщения: не подменяй категорию и не смешивай симптоматику разных вертикалей. **Не делай главным мотивом −кг и весы**, если в задании нет явного похудения.
|
|
504
|
+
- Естественный человеческий тон, без академизма и AI-звучания
|
|
505
|
+
- Разные психологические триггеры в каждой паре, минимальное пересечение
|
|
506
|
+
${getDelicateTopicsAndQuantitativeClaimsRule()}
|
|
507
|
+
- Верни ТОЛЬКО пары в указанном формате, без объяснений и комментариев`;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Пользовательский промпт для генерации пар «заголовок + текст»
|
|
511
|
+
*/
|
|
512
|
+
function getPairsUserPrompt(product, geo, additionalInfo, noOverride, count = 3, selectedIndices) {
|
|
513
|
+
const n = selectedIndices && selectedIndices.length >= 1
|
|
514
|
+
? selectedIndices.length
|
|
515
|
+
: Math.min(10, Math.max(2, count));
|
|
516
|
+
if (!noOverride) {
|
|
517
|
+
const override = (0, promptOverrides_1.getPromptOverride)('getPairsUserPrompt');
|
|
518
|
+
if ((override === null || override === void 0 ? void 0 : override.enabled) && override.customPrompt) {
|
|
519
|
+
_debugLog('✅ Using CUSTOM getPairsUserPrompt');
|
|
520
|
+
return override.customPrompt
|
|
521
|
+
.replace(/\$\{product\}/g, product)
|
|
522
|
+
.replace(/\$\{geo\}/g, geo)
|
|
523
|
+
.replace(/\$\{additionalInfo\}/g, additionalInfo.trim() || '')
|
|
524
|
+
.replace(/\$\{count\}/g, String(n))
|
|
525
|
+
.replace(/\$\{n\}/g, String(n));
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return `Продукт: ${product}
|
|
529
|
+
Локация: ${geo}${additionalInfo.trim() ? `\n\nДополнительная информация:\n${additionalInfo}` : ''}
|
|
530
|
+
|
|
531
|
+
Создай ${n} пар «заголовок + текст» для рекламы в Facebook.`;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Блок, который приложение добавляет **перед** текстом `getValidationPrompt`, когда в запрос к модели
|
|
535
|
+
* уходят два изображения: сначала креатив, затем эталон `product.png`/`product.jpg`/`product.webp`.
|
|
536
|
+
* В кастомном override этого текста нет — он всё равно префиксуется в рантайме при наличии референса.
|
|
537
|
+
*/
|
|
538
|
+
function getValidationProductReferencePreamble() {
|
|
539
|
+
return `ИЗОБРАЖЕНИЯ (строгий порядок после этого текста):
|
|
540
|
+
1) Первое изображение — готовый рекламный креатив для проверки.
|
|
541
|
+
2) Второе изображение — эталонная фотография упаковки/товара (тот же файл, что использовался при генерации).
|
|
542
|
+
|
|
543
|
+
СВЕРКА С ЭТАЛОНОМ:
|
|
544
|
+
- Убедись, что товар на креативе — тот же продукт/упаковка, что на эталоне: бренд, форма, характерные цвета и узнаваемые элементы дизайна.
|
|
545
|
+
- Допустимы другой ракурс, крупность, свет, фон, отражения и рекламная обработка; не требуй пиксель-в-пиксель.
|
|
546
|
+
- Ошибка (отдельным пунктом в списке ОШИБОК), только если на креативе визуально другой товар или настолько сильное расхождение, что покупатель спутает продукт.
|
|
547
|
+
- Текст на этикетке упаковки по общим правилам ниже не валидируй на язык; эталон не отменяет остальные шаги проверки макета.
|
|
548
|
+
|
|
549
|
+
---
|
|
550
|
+
`;
|
|
551
|
+
}
|
|
552
|
+
function getValidationPromptBulletAddendum(expectNoBullets) {
|
|
553
|
+
if (expectNoBullets === undefined)
|
|
554
|
+
return '';
|
|
555
|
+
if (expectNoBullets) {
|
|
556
|
+
return `
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
АВТО — БУЛЛЕТЫ ДЛЯ ЭТОГО КРЕО (подмешано приложением):
|
|
560
|
+
- Отдельный вертикальный список из трёх выгод с «галочками»/иконками **не** требуется. Не пиши ОШИБКИ «нет 3 буллетов», «нужен список выгод», «недостаточно буллетов».
|
|
561
|
+
- Не добавляй в список ОШИБОК пункты по вертикальности, «ровно 3», иконкам у буллетов, читаемости буллетов.`;
|
|
562
|
+
}
|
|
563
|
+
return `
|
|
564
|
+
|
|
565
|
+
---
|
|
566
|
+
АВТО — БУЛЛЕТЫ ДЛЯ ЭТОГО КРЕО (подмешано приложением):
|
|
567
|
+
- Должны быть **три** отдельные короткие выгоды: вертикальный список **или** горизонтальный ряд из трёх плашек, с визуальными галочками/иконками, **вне** банки/упаковки. **ОШИБКА**, если визуально **нет** такого блока или **меньше трёх** отдельных читаемых выгод (не путай с ценой/скидкой). **Не** требуй вертикали: три в ряд — норма.`;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Approach-специфичные исключения валидатора. Подмешивается **после** базового промпта
|
|
571
|
+
* (в т.ч. при включённом кастомном override getValidationPrompt) и имеет приоритет над
|
|
572
|
+
* общими правилами — иначе исключения shop_window/quiz/screenshot молча теряются при override.
|
|
573
|
+
*/
|
|
574
|
+
function getValidationPromptApproachAddendum(opts) {
|
|
575
|
+
if (opts.isShopWindow) {
|
|
576
|
+
return `
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
АВТО — ИСКЛЮЧЕНИЯ ПОДХОДА «${opts.shopWindowDisplayName}» (подмешано приложением; **имеют приоритет** над общими правилами выше):
|
|
580
|
+
- **CTA-кнопка НЕ обязательна.** НЕ ставь ОШИБКУ «нет CTA» / «нужна кнопка призыва» / «кнопка не выглядит как кнопка». Оффер несёт витринный стикер, отдельная кнопка не требуется.
|
|
581
|
+
- **Старая зачёркнутая цена НЕ обязательна.** НЕ ставь ОШИБКУ «нужны две суммы» / «нет старой цены» / «одна цена» / «математика скидки не сходится». Обязательны только: читаемая **новая** цена + бейдж **«-50%»**.
|
|
582
|
+
- Средовой текст витрины (вывеска магазина, ценники/постеры внутри витрины, брендинг на стенах) — **декор среды**: НЕ считай «лишним текстом» и НЕ проверяй его язык. Строго на языке ${opts.geo} — только HOOK, «-50%» и новая цена.`;
|
|
583
|
+
}
|
|
584
|
+
if (opts.isQuizAgeChoice) {
|
|
585
|
+
return `
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
АВТО — ИСКЛЮЧЕНИЯ ПОДХОДА «${opts.quizApproachDisplayName}» (подмешано приложением; **имеют приоритет**):
|
|
589
|
+
- Блок 3–4 псевдо-кнопок возрастных диапазонов («18–30», «30–45», «45–60», «60+») — штатный контент квиза: НЕ считай «лишним текстом»/OTHER_TEXT. Цифры диапазонов — не ошибка языка.
|
|
590
|
+
- trust/urgency-печати НЕ требуются; их отсутствие — не ошибка.`;
|
|
591
|
+
}
|
|
592
|
+
if (opts.isScreenshotReviews) {
|
|
593
|
+
return `
|
|
594
|
+
|
|
595
|
+
---
|
|
596
|
+
АВТО — ИСКЛЮЧЕНИЯ ПОДХОДА «Скрин отзывов» (подмешано приложением; **имеют приоритет**):
|
|
597
|
+
- Блок отзывов (аватары, имена, звёзды, текст) — штатный контент, НЕ «лишний текст».
|
|
598
|
+
- Короткие англоязычные подписи имитации UI приложения («Reviews», бейдж стора) — НЕ ошибка языка. Тело отзывов — строго на языке ${opts.geo}.`;
|
|
599
|
+
}
|
|
600
|
+
return '';
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Промпт для валидации рекламных креативов.
|
|
604
|
+
* `keywords` — только для подстановки в кастомный override (${keywords}); в дефолтном тексте не используется.
|
|
605
|
+
* `options.expectNoBullets` — true: не требовать 3 буллета; false: требовать три отдельные выгоды (вертикально или в ряд). undefined: как «true» (как раньше).
|
|
606
|
+
*/
|
|
607
|
+
function getValidationPrompt(product, geo, keywords, approachName, noOverride,
|
|
608
|
+
/** Краткий эталон цен из приложения (новая + ожидаемая старая при -50%); пусто — без сверки чисел */
|
|
609
|
+
priceBrief, options) {
|
|
610
|
+
var _a, _b;
|
|
611
|
+
const expectNoBullets = (options === null || options === void 0 ? void 0 : options.expectNoBullets) !== false;
|
|
612
|
+
const approachLine = (approachName === null || approachName === void 0 ? void 0 : approachName.trim()) ? `\nПОДХОД: ${approachName.trim()}\n` : '\n';
|
|
613
|
+
// Резолв подхода ДО override-ветки: иначе кастомный промпт валидации минует все
|
|
614
|
+
// approach-исключения (shop_window/quiz/screenshot) и они молча перестают работать.
|
|
615
|
+
const approachBaseName = (approachName === null || approachName === void 0 ? void 0 : approachName.trim())
|
|
616
|
+
? getCreoApproachBaseNameFromImageLabel(approachName)
|
|
617
|
+
: '';
|
|
618
|
+
const resolvedApproach = approachBaseName
|
|
619
|
+
? findCreoApproachByName(approachBaseName)
|
|
620
|
+
: undefined;
|
|
621
|
+
const validatorKey = resolvedApproach === null || resolvedApproach === void 0 ? void 0 : resolvedApproach.validatorKey;
|
|
622
|
+
const isScreenshotReviews = validatorKey === 'screenshot_reviews';
|
|
623
|
+
const isQuizAgeChoice = validatorKey === 'quiz_age';
|
|
624
|
+
const isShopWindow = validatorKey === 'shop_window';
|
|
625
|
+
const quizApproachDisplayName = (_a = resolvedApproach === null || resolvedApproach === void 0 ? void 0 : resolvedApproach.name) !== null && _a !== void 0 ? _a : exports.QUIZ_AGE_APPROACH;
|
|
626
|
+
const shopWindowDisplayName = (_b = resolvedApproach === null || resolvedApproach === void 0 ? void 0 : resolvedApproach.name) !== null && _b !== void 0 ? _b : 'Реалистичная витрина';
|
|
627
|
+
const approachAddendum = getValidationPromptApproachAddendum({
|
|
628
|
+
isShopWindow,
|
|
629
|
+
isQuizAgeChoice,
|
|
630
|
+
isScreenshotReviews,
|
|
631
|
+
shopWindowDisplayName,
|
|
632
|
+
quizApproachDisplayName,
|
|
633
|
+
geo,
|
|
634
|
+
});
|
|
635
|
+
if (!noOverride) {
|
|
636
|
+
const override = (0, promptOverrides_1.getPromptOverride)('getValidationPrompt');
|
|
637
|
+
if ((override === null || override === void 0 ? void 0 : override.enabled) && override.customPrompt) {
|
|
638
|
+
const base = override.customPrompt
|
|
639
|
+
.replace(/\$\{product\}/g, product)
|
|
640
|
+
.replace(/\$\{geo\}/g, geo)
|
|
641
|
+
.replace(/\$\{keywords\}/g, keywords.join(', '))
|
|
642
|
+
.replace(/\$\{approachLine\}/g, approachLine)
|
|
643
|
+
.replace(/\$\{priceBrief\}/g, (priceBrief === null || priceBrief === void 0 ? void 0 : priceBrief.trim()) || 'В приложении бриф цены не задан — сверяй визуально: обязательны новая цена и бейдж «-50%»; старую цену не требуй.');
|
|
644
|
+
return base + approachAddendum + getValidationPromptBulletAddendum(options === null || options === void 0 ? void 0 : options.expectNoBullets);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
const step0QuizAgeHint = isQuizAgeChoice
|
|
648
|
+
? 'AGE_BUTTONS: ["..."] (3–4 псевдо-кнопки возрастных диапазонов; штатный контент подхода — не включай в OTHER_TEXT)\n'
|
|
649
|
+
: '';
|
|
650
|
+
const step0OtherTextHint = isQuizAgeChoice
|
|
651
|
+
? 'OTHER_TEXT: ["..."] (любой другой рекламный текст ВНЕ упаковки и ВНЕ HOOK/AGE_BUTTONS/PRICE/DISCOUNT/CTA; псевдо-кнопки возрастов НЕ сюда; название/бренд на упаковке НЕ включай)'
|
|
652
|
+
: 'OTHER_TEXT: ["..."] (любой другой рекламный текст на макете ВНЕ упаковки и ВНЕ элементов выше; название/бренд на упаковке НЕ включай)';
|
|
653
|
+
const quizValidationNote = isQuizAgeChoice
|
|
654
|
+
? `- **Подход «${quizApproachDisplayName}»:** псевдо-кнопки возрастных диапазонов («18–30», «30–45», «45–60», «60+» и т.п.) — штатный контент квиза, **не** OTHER_TEXT и **не** «лишний текст». Цифры диапазонов допустимы; одно короткое слово на языке GEO рядом — не ошибка языка.\n`
|
|
655
|
+
: '';
|
|
656
|
+
const shopWindowValidationNote = isShopWindow
|
|
657
|
+
? `- **Подход «${shopWindowDisplayName}»:** вывеска магазина, постеры/ценники внутри витрины, брендинг на стенах — декор среды, **не** рекламный оффер; язык этого декора не проверяй (см. ШАГ 5). HOOK, стикер «-50%» и новая цена — строго язык GEO. Отдельная CTA-кнопка не обязательна.\n`
|
|
658
|
+
: '';
|
|
659
|
+
const step0BulletsHint = expectNoBullets
|
|
660
|
+
? 'BULLETS: кратко опиши, что видишь (для справки). Для **этого** крео отдельные три benefit-строки с «галочками» **не** обязательны; не используй для вердикта требований «ровно 3».'
|
|
661
|
+
: 'BULLETS: укажи, видишь ли **три** отдельные короткие выгоды (вертикально **или** в одном горизонтальном ряду из трёх блоков, иконки/✓) вне банки. Если **нет** трёх различимых выгод — явно напиши «< 3» или «нет блока».';
|
|
662
|
+
const step2Bullets = expectNoBullets
|
|
663
|
+
? `ШАГ 2 — БУЛЛЕТЫ:
|
|
664
|
+
- Не проверяй и не оценивай количество, отсутствие или наличие буллетов. 0, 1, 2, 3 и больше — всё допустимо.
|
|
665
|
+
- НЕ добавляй в финальный список ошибок ни одного пункта, связанного с буллетами (вертикальность, «ровно 3», иконки, читаемость буллетов и т.п.).`
|
|
666
|
+
: `ШАГ 2 — БУЛЛЕТЫ (жёстко для этого крео):
|
|
667
|
+
- Должны присутствовать **три** отдельные короткие выгоды с иконками/галочками, **вне** упаковки/банки. Оформление: **либо** вертикальный список из трёх строк, **либо** три отдельные ячейки/плашки **в одном горизонтальном ряду** (одна линия под крупным HOOK) — оба варианта **ОК**, не требуй строго вертикали.
|
|
668
|
+
- **ОШИБКА**, если визуально **нет** такого блока, **меньше трёх** читаемых отдельных выгод, или неразличимы 3 смысла. **ЗАПРЕЩЕНО** отклонять креатив **только** из‑за горизонтального ряда вместо вертикального — это не нарушение. Не путай с ценой, скидкой и CTA.
|
|
669
|
+
- **ОШИБКА**, если выгоды печатны **на** банке/этикетке (должны быть в рекламном слое, не на продукте).`;
|
|
670
|
+
const priceBriefTrim = (priceBrief === null || priceBrief === void 0 ? void 0 : priceBrief.trim()) || '';
|
|
671
|
+
const bulgariaValidationCurrencyNote = isBulgariaGeo(geo)
|
|
672
|
+
? `- **Болгария:** с 2026 года рынок только на **евро**; **лв**, BGN, «лев» на ценнике — **ОШИБКА, НУЖНА ПЕРЕСБОРКА** (устаревшая валюта), даже если цифры выглядят правдоподобно.\n`
|
|
673
|
+
: '';
|
|
674
|
+
const stepPriceBrief = priceBriefTrim
|
|
675
|
+
? `ШАГ P — ЦЕНЫ (сначала макет, потом бриф):
|
|
676
|
+
Эталон из приложения (сверяй **новую** цену и валюту; текст про «ожидаемую старую» — справка для генератора, **не** требование наличия старой на макете):
|
|
677
|
+
${priceBriefTrim}
|
|
678
|
+
|
|
679
|
+
1) ОБЯЗАТЕЛЬНО на макете (два **независимых** факта; **ОШИБКА**, если нет хотя бы одного):
|
|
680
|
+
- Читаемая **новая** (акционная) цена — в валюте брифа (см. п. 1a и п. 2).
|
|
681
|
+
- Читаемый бейдж **«-50%»** в зоне оффера (см. ШАГ 4). Это маркетинговый акцент — **всегда** обязателен, **независимо** от наличия старой цены.
|
|
682
|
+
|
|
683
|
+
2) **НЕ проверять** (отсутствие — **не** ошибка и **не** рекомендация):
|
|
684
|
+
- Наличие старой зачёркнутой цены.
|
|
685
|
+
- Математическую согласованность старой и новой («58→29 = -50%», «старая ≈ 2× новой», толщину зачёркивания и т.п.). **ЗАПРЕЩЕНО** отклонять креатив за «несогласованную пару цен» или «скидку не на чём проверить».
|
|
686
|
+
|
|
687
|
+
3) **ОШИБКА** по ценам только если:
|
|
688
|
+
- Нет читаемой **новой** цены, **ИЛИ**
|
|
689
|
+
- Нет читаемого **«-50%»**, **ИЛИ**
|
|
690
|
+
- **Неверная валюта** относительно брифа (п. 1a), **ИЛИ**
|
|
691
|
+
- Валюта совпадает с брифом, а число **новой** цены явно другое (не в пределах округления).
|
|
692
|
+
|
|
693
|
+
4) Префикс «2×»/«2x»/«x2» перед суммой — **ОШИБКА**, если эта сумма **присутствует** на макете (см. ШАГ 4).
|
|
694
|
+
|
|
695
|
+
1a) ВАЛЮТА ОБЯЗАТЕЛЬНО КАК В БРИФЕ (критично):
|
|
696
|
+
- В брифе указана конкретная валюта (например EUR). На макете в блоке цен должна быть **именно она** (символ €, код EUR, или привычное для GEO написание «евро» **как валюта цены**, если это явно евро). **ОШИБКА, НУЖНА ПЕРЕСБОРКА**, если читается **иная** национальная валюта или её сокращение: при брифе EUR — **лв**, **лв.**, BGN, **лев**, руб/₽, zł, lei, kn, Kč и любые другие явные обозначения **не евро** рядом с суммами.
|
|
697
|
+
${bulgariaValidationCurrencyNote}- Если валюту на макете нельзя прочитать уверенно — не гадай в пользу OK: при явном брифе с кодом валюты лучше отметь риск; при двусмысленности между двумя валютами — **ОШИБКА** или явное требование пересборки с читаемой валютой из брифа.
|
|
698
|
+
|
|
699
|
+
5) Сверка **новой** цены с брифом (только когда сопоставимо):
|
|
700
|
+
- Сравнивай число **НОВОЙ** цены с брифом ТОЛЬКО если валюта на макете явно та же, что в брифе. Допускается разное оформление числа (пробелы тысяч, запятая/точка).
|
|
701
|
+
|
|
702
|
+
6) Цена не должна быть оформлена как строка буллета с галочкой — отдельный блок.`
|
|
703
|
+
: `ШАГ P — ЦЕНЫ (бриф числом не задан):
|
|
704
|
+
- **ОБЯЗАТЕЛЬНО:** читаемая новая цена **и** читаемый бейдж «-50%». **ОШИБКА**, если нет новой цены **или** нет «-50%».
|
|
705
|
+
- **НЕ проверять:** старую зачёркнутую цену (отсутствие OK); математику «старая/новая = -50%».
|
|
706
|
+
- Префикс «2×» перед суммой — **ОШИБКА**, если сумма есть (см. ШАГ 4).
|
|
707
|
+
${bulgariaValidationCurrencyNote}`;
|
|
708
|
+
let step3OtherText;
|
|
709
|
+
if (isShopWindow) {
|
|
710
|
+
step3OtherText = `ШАГ 3 — Подход «${shopWindowDisplayName}»:
|
|
711
|
+
- Средовой текст витрины (вывеска магазина, постеры/ценники внутри, брендинг на стенах) — декор среды, не считай лишним OTHER_TEXT и не отклоняй за «слишком много текста»; язык этого декора — см. ШАГ 5.
|
|
712
|
+
- Не требуй trust/urgency/отдельную CTA-кнопку — для этого подхода они не нужны; отсутствие CTA не ошибка.
|
|
713
|
+
- Оффер достаточно в виде витринного стикера «-50%» + новая цена (старая зачёркнутая не требуется).`;
|
|
714
|
+
}
|
|
715
|
+
else if (isScreenshotReviews) {
|
|
716
|
+
step3OtherText = `ШАГ 3 — Подход «Скрин отзывов»:
|
|
717
|
+
- Блок отзывов (аватары, имена, звёзды, текст) — это нормальный контент креатива, не считай его лишним OTHER_TEXT.
|
|
718
|
+
- Английские подписи только в имитации шапки приложения («Reviews» и т.п.) — см. исключение в ШАГ 5 и блок ВАЖНО про UI телефона; не смешивай с языком тел отзыва.`;
|
|
719
|
+
}
|
|
720
|
+
else if (isQuizAgeChoice) {
|
|
721
|
+
step3OtherText = `ШАГ 3 — Подход «${quizApproachDisplayName}»:
|
|
722
|
+
- Блок 3–4 псевдо-кнопок с возрастными диапазонами — штатный контент квиза, не считай лишним OTHER_TEXT и не отклоняй за «слишком много текста».
|
|
723
|
+
- Не требуй trust/urgency — для этого подхода они не нужны, но их отсутствие не ошибка.
|
|
724
|
+
- Язык HOOK/CTA и коротких подписей на псевдо-кнопках — по ШАГ 5; цифры диапазонов («18–30» и т.п.) — не ошибка.`;
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
step3OtherText = `ШАГ 3 — Доп. текст, бейджи, печати:
|
|
728
|
+
- Не валидируй объём текста и не отклоняй креатив за «слишком много элементов», punch vs не punch, количество плашек или пустоту OTHER_TEXT.
|
|
729
|
+
- Не требуй отсутствия trust/urgency/подписей — для любого подхода это не ошибка.
|
|
730
|
+
- Язык рекламного текста (включая бейджи) — по-прежнему ШАГ 5. Неясные срочности вроде «24h» — по-прежнему ШАГ 6.`;
|
|
731
|
+
}
|
|
732
|
+
return `Ты — СТРОГИЙ валидатор рекламных креативов (1:1). Не улучшай и не предлагай идеи — только проверка и вердикт.
|
|
733
|
+
Продукт: ${product}. GEO/язык: ${geo}.${approachLine}
|
|
734
|
+
(Строка ПОДХОД может содержать суффикс « (1:1)» / « (2:3)» — ветки валидатора по validatorKey определяются по **базовому** имени подхода без суффикса.)
|
|
735
|
+
|
|
736
|
+
ВАЖНО:
|
|
737
|
+
- Проверяй язык ТОЛЬКО для рекламного текста на макете (заголовок/CTA/цена/скидка/разрешённые бейджи из OTHER_TEXT; если есть буллеты — и их текст). Текст на самой упаковке/этикетке игнорируй (включая название/бренд вроде "${product}").
|
|
738
|
+
- **Имитация UI телефона / приложения** (рамка смартфона, скрин отзывов): короткие англоязычные подписи «как в интерфейсе» — заголовок окна («Reviews», «Ratings»), служебные метки шапки магазина приложений — **не** считай нарушением языка GEO: это декор интерфейса, не рекламный оффер. Тексты самих отзывов внутри карточек по-прежнему должны быть на языке GEO (если видны как контент отзыва). HOOK креатива, CTA, цены, буллеты **вне** рамки телефона — строго язык GEO.
|
|
739
|
+
${isShopWindow ? `- **Реалистичная витрина:** вывеска магазина, постеры/ценники внутри витрины, брендинг на стенах — декор среды, не рекламный оффер; язык этого декора **не** проверяй. HOOK, стикер «-50%» и новая цена — строго язык GEO.\n` : ''}- **Круглые trust‑печати (местные/европейские стандарты)**: мелкий текст по ободу — не валидируй на читабельность и не требуй его наличия (напротив, приветствуется чистая графика без мелкого текста); отдельные подписи в футере рядом с печатью — по ШАГ 5–6.
|
|
740
|
+
- **Международные знаки сертификации/стандартов** (GMP, ISO, CE, EU, FDA, HACCP, NON‑GMO, «GMP CERTIFIED», «ISO STANDARD», «CERTIFIED», «QUALITY CONTROL» и подобные — на самих trust‑печатях/значках): это **глобальные стандартные термины**, которые в рекламе принято показывать латиницей/по‑английски даже на локализованном макете. Их наличие на печатях — **НЕ** смешение языков и **НЕ** ошибка, даже если текст читается. Правило GEO по‑прежнему действует для **переводимых** маркетинговых слов как **отдельная подпись‑строка** рядом с печатью («NATURAL», «QUALITY» → должны быть на языке GEO).
|
|
741
|
+
- **Реквизит экспертной сцены** (подпись «LAB REPORT», «REPORT», заголовки бумаг/бланков, метки на медицинском планшете, диаграммах, рецептурном блокноте): это декор среды «Эксперт / Авторитет», а не рекламный оффер — язык этого реквизита **не** проверяй (как UI телефона или вывеску витрины).
|
|
742
|
+
- Если сомневаешься, мелкий текст на банке — этикетка или нет: для языка считай этикеткой и не валидируй. Исключение: **нижний оффер-блок** макета (новая цена, «-50%», кнопка CTA в одной полосе/ряду под картинкой продукта) — это всегда рекламный слой **вне упаковки**, даже рядом с фото банки; цены и скидку оттуда учитывай в PRICE/DISCOUNT и не считай «на упаковке».
|
|
743
|
+
- Если текст плохо читается/микрошрифт — это ошибка.
|
|
744
|
+
${getMaleVerticalValidationToneNote()}
|
|
745
|
+
${quizValidationNote}${shopWindowValidationNote}
|
|
746
|
+
ШАГ 0 — Сначала выпиши распознанный текст (как ты его видишь на макете):
|
|
747
|
+
HOOK/HEADLINE: "..." (верхний крупный текст)
|
|
748
|
+
${step0BulletsHint}
|
|
749
|
+
${step0QuizAgeHint}PRICE: "..." (если нет — "нет")
|
|
750
|
+
DISCOUNT: "..." (если нет — "нет")
|
|
751
|
+
CTA: "..." (если нет — "нет")
|
|
752
|
+
${step0OtherTextHint}
|
|
753
|
+
(опционально, для ясности): URGENCY_BADGE, TRUST_BADGES — перечисли, если есть
|
|
754
|
+
|
|
755
|
+
ШАГ 1 — HOOK/HEADLINE (критично):
|
|
756
|
+
- Должен быть ВЫШЕ всех элементов и читабелен (хорошо читается на телефоне)
|
|
757
|
+
- Допускается 1–4 строки (это НЕ ошибка). Ошибка только если текст нечитабелен или есть разрыв/перенос внутри слова.
|
|
758
|
+
- Смысл: релевантно проблеме/выгоде продукта. Допускаются и боль/дискомфорт, и обещание/выгода (например «станет легче день ото дня» — смысл на языке GEO). НЕ считай ошибкой формулировки обещаний результата или клеймы.
|
|
759
|
+
- Заголовок должен **совпадать по теме с продуктом** из брифа (та же потребность/проблемная зона/обещание, что в описании продукта). ОШИБКА, если заголовок явно про другую вертикаль здоровья или другую боль, чем следует из брифа. ОШИБКА, если заголовок настолько общий, что его нельзя однозначно отнести к заявленному продукту (одни абстрактные «легче/лучше/решение» без привязки к нише).${keywords.length ? ` Ориентир по словам (не выносить в другую нишу): ${keywords.join(', ')}.` : ''}
|
|
760
|
+
- ОШИБКА (соцдоказательство без нише): если текст HOOK по сути **только** массовое доверие/рейтинг («тысячи доверяют», «98% pozytywnych opinii», «10 000 confían» как главный посыл) и **нет** ни одного узнаваемого маркера **темы продукта из брифа** (не абстрактное «организм/здоровье» — нужны слова уровня назначения: слим → тело/фигура/вес; детокс/очищение/паразиты → соответствующая лексика на языке GEO и т.д.), так что заголовок подошёл бы любому БАДу — **НУЖНА ПЕРЕСБОРКА**. Отдельная строка скидки не считается привязкой к нише.
|
|
761
|
+
- Проверь вторую часть заголовка. Если она состоит только из абстрактных слов («легче», «лучше», «решение», «помощь» без конкретики на языке GEO) без конкретного бенефита — отметь: РЕКОМЕНДАЦИЯ: заголовок можно усилить конкретикой (но если одновременно срабатывает пункт про «только соцдоказательство» выше — ставь ОШИБКА, не рекомендацию)
|
|
762
|
+
- Если заголовок слишком общий/абстрактный («легче», «лучше» без конкретики), но не попадает под «только соцдоказательство» — отметь как РЕКОМЕНДАЦИЯ к улучшению (не ошибка, но слабо)
|
|
763
|
+
- РЕКОМЕНДАЦИЯ (CTR): верхний текст лучше делать как HOOK — ОЧЕНЬ крупный, жирный, ВСЕ БУКВЫ ПРОПИСНЫЕ, на яркой контрастной плашке. Если это не так — не ошибка, но отметь рекомендацией
|
|
764
|
+
|
|
765
|
+
${step2Bullets}
|
|
766
|
+
|
|
767
|
+
${stepPriceBrief}
|
|
768
|
+
|
|
769
|
+
ШАГ 2.5 — CLAIMS CHECK:
|
|
770
|
+
- Клеймы по результату **качественные** (жёсткие/абсолютные или мягкие) — НЕ проверяются и НЕ запрещаются. Не блокируй за формулировки обещаний результата.
|
|
771
|
+
- Прямая лексика симптома/результата для **мужской вертикали** из брифа (${exports.MALE_VERTICAL_CRITERIA}) — не ошибка; послабление тона для мужской вертикали не отменяет остальные проверки (язык, новая цена, «-50%»).
|
|
772
|
+
|
|
773
|
+
${step3OtherText}
|
|
774
|
+
${isShopWindow ? `
|
|
775
|
+
ШАГ 3.5 — ИНСТАЛЛЯЦИЯ ВИТРИНЫ (критично для «${shopWindowDisplayName}»):
|
|
776
|
+
- Витрина должна нести **доминирующий** нишевый визуальный крючок (инсталляция-метафора), тематически связанный с продуктом из брифа — читатель за ~1 секунду связывает декор с нишей оффера.
|
|
777
|
+
- **ОШИБКА, НУЖНА ПЕРЕСБОРКА**, если это просто продукт на полке **без** нишевой метафоры, или метафора явно из **другой** вертикали, чем бриф (как HOOK без якоря нише).
|
|
778
|
+
- Абстрактная нишевая метафора результата (энергия / лёгкость / чистота / уверенность по смыслу оффера) — **засчитывается**; буквальный предмет не требуй.
|
|
779
|
+
- **Мужская вертикаль** (${exports.MALE_VERTICAL_CRITERIA}): **ОШИБКА, НУЖНА ПЕРЕСБОРКА** только при **сексуализированной / обнажённой / анатомически-акцентированной** инсталляции или суггестивной позе (акцент на паху/торсе, эротика, женщина-«приз», намёк на половой акт). Нейтральный **атлетичный силуэт-символ / героическая фигура / контур человека как метафора силы/формы** (без откровенности) — **РАЗРЕШЁН**, это допустимая абстрактная символика силы; наряду с абстрактными символами энергии / уверенности / пары. НЕ отклоняй за сам факт человеческого контура.
|
|
780
|
+
- Если выглядит как обычный баннер с плашками поверх фона, а не реалистичная витрина магазина — **РЕКОМЕНДАЦИЯ** (не ошибка).
|
|
781
|
+
- Оффер: достаточно витринного стикера «-50%» + новая цена (старая зачёркнутая не требуется).
|
|
782
|
+
` : ''}
|
|
783
|
+
ШАГ 4 — CTA и визуал цены/скидки (критично):
|
|
784
|
+
${isShopWindow ? `- CTA: для подхода «${shopWindowDisplayName}» (shop_window) отдельная кнопка **НЕ обязательна**. Если кнопка есть — на языке ${geo}, читабельна. Отсутствие CTA — **не** ошибка.` : `- CTA: на языке ${geo}, хорошо заметная кнопка (позиция НЕ важна). **ОШИБКА**, если CTA **нет**.`}
|
|
785
|
+
- **Новая цена:** **ОБЯЗАТЕЛЬНА**, читаемая (сверка с брифом — ШАГ P). **ОШИБКА**, если нет читаемой новой цены.
|
|
786
|
+
- **«-50%»:** **ОБЯЗАТЕЛЕН** всегда — отдельный видимый бейдж/надпись в зоне оффера (плашка, круг, стикер, строка на витрине и т.п.). **ОШИБКА**, если «-50%» не читается. Наличие старой цены **не** влияет на это требование.
|
|
787
|
+
- **Старая цена:** если есть — не проверяй наличие, зачёркивание и соотношение с новой. Если **нет** — **не** ошибка.
|
|
788
|
+
- Оформление сумм: у **новой** цены — **только число и валюта**. Если старая **присутствует** — у неё тоже только число и валюта. **ОШИБКА**, если перед **любой** суммой «2×» / «2x» / «x2». Исключение — бриф «2 шт.» / «pack x2».
|
|
789
|
+
- Если на макете указан процент скидки **и** он явно **не** «-50%» (напр. «-30%») — **ОШИБКА**.
|
|
790
|
+
- **ЗАПРЕЩЕНО** ставить ошибки «нужны две суммы», «нет второй цены», «одна цена», «скидка не на чём проверить», «несогласованная пара цен».
|
|
791
|
+
- Если в ШАГ 0 в DISCOUNT указано «-50%» — **не** дублируй ошибку «скидка не отображается».
|
|
792
|
+
- Не считать ошибкой, если скидка/цена конкурируют с CTA по акценту — допустимо, пока CTA (если обязателен) остаётся заметной.
|
|
793
|
+
|
|
794
|
+
ШАГ 5 — ЯЗЫК (критично):
|
|
795
|
+
- В рекламном тексте (HOOK/HEADLINE, текст на буллетах если есть, CTA, PRICE, OTHER_TEXT) НЕТ произвольных английских слов и фраз. Если есть — ошибка.
|
|
796
|
+
- **ИСКЛЮЧЕНИЕ — бейдж скидки (DISCOUNT):** на малой плашке с процентом допустимы привычные глобальные маркеры **OFF**, **SALE** рядом с «-50%» / числом процента (например «-50% OFF», «SALE −50%») — **не** считать смешением языков и **не** ставить ОШИБКУ только из‑за этих слов **в этом блоке скидки**. HOOK, CTA, буллеты и прочий рекламный текст по-прежнему строго на языке GEO.
|
|
797
|
+
- ИСКЛЮЧЕНИЕ: внутри **графики интерфейса телефона** (шапка окна приложения, подпись вкладки вроде «Reviews», «App Store»-стиль бейджа в углу рамки) английские слова **не** считать ошибкой — это имитация ОС/магазина, не рекламный текст баннера. Ошибкой остаётся английский в HOOK над макетом, в CTA, в буллетах, на строках **сумм** (кроме кода валюты ISO и символа €/$ и т.п.), в теле отзыва как пользовательском тексте (не в подписи UI). Бейдж скидки — см. исключение OFF/SALE выше.
|
|
798
|
+
- **ИСКЛЮЧЕНИЕ — международные знаки сертификации/стандартов на trust‑печатях:** GMP, ISO, CE, EU, FDA, HACCP, NON‑GMO и связки «GMP CERTIFIED», «CERTIFIED ISO STANDARD», «CERTIFIED», «QUALITY CONTROL» — это глобальные стандартные термины (латиница по всему миру), **не** считать смешением языков и **не** ставить ОШИБКУ, даже если читаются. Аналогично **реквизит экспертной сцены** (подписи на бумагах/планшете вроде «LAB REPORT», «REPORT», заголовки бланков) — декор среды, язык не проверять. Правило GEO остаётся для переводимых маркетинговых слов как отдельная подпись у печати («NATURAL», «QUALITY»).
|
|
799
|
+
${isShopWindow ? `- ИСКЛЮЧЕНИЕ — **реалистичная витрина:** вывеска магазина, постеры/ценники внутри витрины, брендинг на стенах — декор среды; язык этого декора **не** проверяй. Строго на GEO: HOOK, стикер «-50%» и новая цена.\n` : ''}- ЗАПРЕЩЁННЫЕ служебные подписи на макете (частая ошибка модели): слова HOOK, CTA, CAPS, BULLET, HEADLINE, PRICE, DISCOUNT как видимый текст на плашках или кнопке — ОШИБКА (это метки из брифа, не для читателя).
|
|
800
|
+
- Все слова соответствуют GEO/языку ${geo}. Смешение языков — ошибка, **кроме** исключений выше (OFF/SALE на бейдже скидки; UI телефона${isShopWindow ? '; декор витрины' : ''}).
|
|
801
|
+
- ПСЕВДОСЛОВА И ОПЕЧАТКИ: если на плашке скидки или в буллетах видно **несуществующее** или явно ошибочное слово для языка GEO (не словарное), либо «калька» под английский без нормы (пример для испанского: «DISCONTA» вместо «DESCUENTO»; на буллете англ. «COMFORT» вместо исп. «CONFORT»/«COMODIDAD») — ОШИБКА языка (приземлённая формулировка в строке ОШИБКА).
|
|
802
|
+
|
|
803
|
+
ШАГ 6 — КОМПОЗИЦИЯ:
|
|
804
|
+
- Если креатив без человека (lifestyle/clean), проверь наличие контекста использования (кухня, стол, тумбочка, и т.д.). Продукт на полностью пустом/белом фоне без контекста — РЕКОМЕНДАЦИЯ к улучшению (не критичная ошибка, но слабый визуал)
|
|
805
|
+
- КОНТРАСТ ПЛАШЕК: если HOOK, CTA или блок цен визуально сливается с фоном и текст плохо читается — это ОШИБКА. (Контраст буллетов не проверяй.)
|
|
806
|
+
- Цена не должна быть оформлена как элемент списка с галочкой в стиле бенефитов.
|
|
807
|
+
- TRUST‑печати (круги и т.п., отражающие соответствие местным/европейским стандартам): приветствуется чистая графика без мелкого нечитаемого текста. Если мелкий/неразборчивый текст всё же сгенерировался на самой печати — **не** считай это ОШИБКОЙ (декоративный слой). Короткая **отдельная подпись** рядом с печатью в футере («FÓRMULA NATURAL», «CALIDAD PREMIUM»), если видна как строка — проверь язык GEO и явные опечатки; если разобрать нельзя — не выдумывай нарушение.
|
|
808
|
+
- СКИДКА «-50%»: **обязательна** всегда (см. ШАГ 4); если DISCOUNT в ШАГ 0 заполнен — не дублируй ошибку.
|
|
809
|
+
- Бейджи срочности: «24h» и подобные неясные формулировки — ОШИБКА (непонятно что означает). Ясные («только сегодня», «последние штуки») — ок.
|
|
810
|
+
|
|
811
|
+
ФИНАЛ:
|
|
812
|
+
Выведи строго:
|
|
813
|
+
СТАТУС: OK / НУЖНА ПЕРЕСБОРКА
|
|
814
|
+
Затем список ошибок, каждая строка начинается с "ОШИБКА:" (кратко, по делу). Одну и ту же проблему не повторяй — не больше одной строки на один тип нарушения. Если СТАТУС: НУЖНА ПЕРЕСБОРКА — ОБЯЗАТЕЛЬНО минимум одна конкретная строка "ОШИБКА: ..." (что именно не так); нельзя писать только "ОШИБКА: нет". Если ошибок нет — СТАТУС: OK и "ОШИБКА: нет".
|
|
815
|
+
Затем список рекомендаций (если есть), каждая строка начинается с "РЕКОМЕНДАЦИЯ:" (кратко, по делу). Если рекомендаций нет — напиши "РЕКОМЕНДАЦИЯ: нет".
|
|
816
|
+
Не блокируй за клеймы по результату или формулировки обещаний.`;
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Базовый промпт для генерации изображений креативов
|
|
820
|
+
*/
|
|
821
|
+
function getImageGenerationBasePrompt(generateGeo, generatePrice, generateCurrency, noOverride, aspectRatio, imageApproachCounts) {
|
|
822
|
+
var _a;
|
|
823
|
+
if (!noOverride) {
|
|
824
|
+
const override = (0, promptOverrides_1.getPromptOverride)('getImageGenerationBasePrompt');
|
|
825
|
+
_debugLog('getImageGenerationBasePrompt override:', `exists=${!!override}`, `enabled=${override === null || override === void 0 ? void 0 : override.enabled}`, `hasCustomPrompt=${!!(override === null || override === void 0 ? void 0 : override.customPrompt)}`, `len=${(_a = override === null || override === void 0 ? void 0 : override.customPrompt) === null || _a === void 0 ? void 0 : _a.length}`);
|
|
826
|
+
if ((override === null || override === void 0 ? void 0 : override.enabled) && override.customPrompt) {
|
|
827
|
+
_debugLog('✅ Using CUSTOM getImageGenerationBasePrompt');
|
|
828
|
+
const generateOldPrice = formatDoubledPriceForPrompt(generatePrice);
|
|
829
|
+
return override.customPrompt
|
|
830
|
+
.replace(/\$\{generateGeo\}/g, generateGeo)
|
|
831
|
+
.replace(/\$\{generatePrice\}/g, generatePrice)
|
|
832
|
+
.replace(/\$\{generateOldPrice\}/g, generateOldPrice)
|
|
833
|
+
.replace(/\$\{generateCurrency\}/g, generateCurrency);
|
|
834
|
+
}
|
|
835
|
+
_debugLog('⚠️ Using DEFAULT getImageGenerationBasePrompt');
|
|
836
|
+
}
|
|
837
|
+
// Подходы без буллитов — из подходов с count > 0 (умолчание + per-approach + глобал)
|
|
838
|
+
const counts = imageApproachCounts !== null && imageApproachCounts !== void 0 ? imageApproachCounts : (0, promptOverrides_1.getImageApproachCounts)();
|
|
839
|
+
const selectedApproaches = exports.CREO_APPROACHES.filter((_, i) => counts[i] > 0);
|
|
840
|
+
const noBulletsCond = selectedNoBulletsCond(selectedApproaches);
|
|
841
|
+
const strictNoBulletsCond = selectedStrictNoBulletsCond(selectedApproaches);
|
|
842
|
+
const ageButtonsCond = selectedAgeButtonsCond(selectedApproaches);
|
|
843
|
+
const extraTextNonQuizCond = selectedExtraTextNonQuizCond(selectedApproaches);
|
|
844
|
+
const windowStickerCond = selectedWindowStickerCond(selectedApproaches);
|
|
845
|
+
const humanApproachesList = creoHumanAllowedNamesList();
|
|
846
|
+
const totalApproaches = counts.reduce((a, b) => a + b, 0);
|
|
847
|
+
const textLimitExceptions = joinPromptLines(ageButtonsCond &&
|
|
848
|
+
`- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${ageButtonsCond} → дополнительно разрешён блок 3–4 псевдо-кнопок с возрастными диапазонами (короткие: «18–30», «30–45», «45–60», «60+» + опционально одно слово на ${generateGeo}); это часть механики квиза, не «лишний текст»`, strictNoBulletsCond &&
|
|
849
|
+
`- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${strictNoBulletsCond} → кроме HOOK, цены, скидки, CTA — НИКАКОГО другого текста. Буллиты запрещены. Other_text/urgency/trust‑печати запрещены`, extraTextNonQuizCond &&
|
|
850
|
+
`- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${extraTextNonQuizCond} → дополнительно разрешён вертикальный стек 2–3 крупных числовых плашек (только цифры/формулировки из брифа или допустимого пула: срок «7 дней», «-50%», «9 из 10», порции — на языке ${generateGeo}); это штатный элемент подхода, не буллеты и не «лишний текст». Запрещены выдуманные измеримые обещания (+390%, см, «N раз за ночь» — см. «КОЛИЧЕСТВЕННЫЕ КЛЕЙМЫ»)`, windowStickerCond &&
|
|
851
|
+
`- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${windowStickerCond} → дополнительно допустим реалистичный средовой текст витрины (вывеска магазина, постеры/ценники внутри, брендинг на стенах) — декор среды, не «лишний текст». Буллиты запрещены`, ageButtonsCond &&
|
|
852
|
+
`- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${ageButtonsCond} → кроме HOOK (вопрос-фильтр), псевдо-кнопок возрастов, цены, скидки, CTA — НИКАКОГО другого текста. Буллиты/urgency/trust‑печати запрещены`);
|
|
853
|
+
const showOnlyExceptions = joinPromptLines(strictNoBulletsCond &&
|
|
854
|
+
`- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${strictNoBulletsCond} → показывай только: HOOK + PRICE + DISCOUNT + CTA. Буллиты/urgency/trust‑печати запрещены`, extraTextNonQuizCond &&
|
|
855
|
+
`- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${extraTextNonQuizCond} → показывай: HOOK + вертикальный стек 2–3 крупных числовых плашек (только из брифа/пула) + PRICE + DISCOUNT + CTA. Буллиты/urgency/trust‑печати запрещены. Числовой стек — штатный элемент, не «лишний текст»`, windowStickerCond &&
|
|
856
|
+
`- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${windowStickerCond} → показывай: HOOK + обязательная нишевая инсталляция-метафора + продукт на подиуме + витринный стикер («-50%» + новая цена) + средовой декор витрины. Буллиты/urgency/trust‑печати запрещены. Отдельная CTA-кнопка НЕ обязательна; старая зачёркнутая цена НЕ обязательна`, ageButtonsCond &&
|
|
857
|
+
`- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${ageButtonsCond} → показывай: HOOK (вопрос-фильтр) + блок 3–4 псевдо-кнопок возрастных диапазонов + PRICE + DISCOUNT + CTA. Буллиты/urgency/trust‑печати запрещены. Псевдо-кнопки — часть механики квиза, не «лишний текст»`);
|
|
858
|
+
const autoCheckExceptions = joinPromptLines(ageButtonsCond &&
|
|
859
|
+
`- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${ageButtonsCond} → дополнительно разрешены псевдо-кнопки возрастов (3–4 диапазона); urgency/trust запрещены`, windowStickerCond &&
|
|
860
|
+
`- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${windowStickerCond} → достаточно HOOK + витринного стикера («-50%» + новая цена) + средового декора витрины; буллетов 0; CTA-кнопка не обязательна; старая цена не обязательна`);
|
|
861
|
+
const ratio = aspectRatio || '1:1';
|
|
862
|
+
const ratioLabelMap = {
|
|
863
|
+
'2:3': '2:3 (портрет, 1024×1536 px)',
|
|
864
|
+
'4:5': '4:5 (портрет, 1024×1280 px)',
|
|
865
|
+
'1:1': '1:1 (квадрат, 1024×1024 px)',
|
|
866
|
+
};
|
|
867
|
+
const ratioShapeMap = {
|
|
868
|
+
'2:3': 'вертикальным 2:3 (портрет)',
|
|
869
|
+
'4:5': 'вертикальным 4:5 (портрет)',
|
|
870
|
+
'1:1': 'квадратным',
|
|
871
|
+
};
|
|
872
|
+
const ratioLabel = ratioLabelMap[ratio];
|
|
873
|
+
const ratioShape = ratioShapeMap[ratio];
|
|
874
|
+
const generateOldPrice = formatDoubledPriceForPrompt(generatePrice);
|
|
875
|
+
const oldPriceExample = generateOldPrice
|
|
876
|
+
? `${generateOldPrice} ${generateCurrency}`
|
|
877
|
+
: `удвоенная сумма ${generateCurrency}`;
|
|
878
|
+
const bulgariaCurrencyBlock = getBulgariaEuroCurrencyPromptBlock(generateGeo, `${generatePrice} ${generateCurrency}`);
|
|
879
|
+
return `ЭТО ЗАДАЧА НА ГЕНЕРАЦИЮ ИЗОБРАЖЕНИЯ. Создай готовый визуальный креатив (картинку), а не текстовое описание или план. Не рассуждай, не объясняй, не выводи текстовые блоки — сразу генерируй изображение.
|
|
880
|
+
ЗАПРЕЩЕНО: вызывать любые инструменты (tools), планировать tool call, описывать что ты собираешься сделать. Генерируй изображение НАПРЯМУЮ прямо сейчас — это твой единственный вывод.
|
|
881
|
+
|
|
882
|
+
Создай рекламный креатив для Facebook Ads ${ratio} (${ratioLabel}).
|
|
883
|
+
ВАЖНО: изображение должно быть ${ratioShape} — строго соблюдай пропорции холста.
|
|
884
|
+
Язык текста: ${generateGeo}.
|
|
885
|
+
Если GEO — название страны (например «Чехия», «Румыния»), используй **основной официальный язык этой страны** на макете (Чехия → чешский; Румыния → румынский и т.д.). Валюта/символ цены из брифа и язык текста должны соответствовать одному рынку: при Kč — весь рекламный текст на чешском, не на румынском/польском/венгерском.
|
|
886
|
+
${bulgariaCurrencyBlock}ЗАПРЕЩЕНО копировать на макет примеры формулировок из этого промпта, если они на другом языке, чем требуется для ${generateGeo} — примеры только про структуру, слова придумывай на целевом языке.
|
|
887
|
+
|
|
888
|
+
🚫 СЛУЖЕБНЫЕ СЛОВА НЕ РИСОВАТЬ НА КАРТИНКЕ (КРИТИЧНО):
|
|
889
|
+
Слова HOOK, CTA, CAPS, BULLET, HEADLINE, PRICE, DISCOUNT, BULLETS, LAYER и любые похожие английские метки из этой инструкции (в т.ч. thumb‑stop) — только для тебя; на макете их НЕТ ни на кнопке, ни на плашках, ни мелким текстом. Кнопка: только реальный призыв на языке ${generateGeo} (1–2 слова), без префикса «CTA». Заголовок: только живой текст оффера, без слова HOOK. Заголовок делай прописными буквами на языке ${generateGeo}, но не пиши на изображении слово CAPS и не подписывай блоки ярлыками.
|
|
890
|
+
|
|
891
|
+
🚨 КРИТИЧНО — РЕЛЕВАНТНОСТЬ ПРОДУКТУ (читай ЭТО ПЕРВЫМ):
|
|
892
|
+
- Название и назначение продукта — в начале запроса (строка «🏷️ ПРОДУКТ: ...»). Прочитай и держи **одну** тему: HOOK, буллиты и любая схема тела должны относиться к **этой** нише, без подмены «типичной» болью из другой категории.
|
|
893
|
+
- HOOK и буллиты отражают только проблему/выгоду, которые читатель свяжет с **данным** продуктом. Не переносай симптоматику и органы соседних вертикалей.
|
|
894
|
+
- ЗАПРЕТ на «склейку» вертикалей: без явного повода в брифе/упаковке не используй для буллитов и HOOK клише **других** ниш — суставы и подвижность, «лёгкость движения», общую «боль», желудок/вздутие, зрение, слух, вес/кг, кожу/дерматологию — если оффер про другое. Если оффер про **мужскую вертикаль** (${exports.MALE_VERTICAL_CRITERIA}) — формулируй в **прямой** лексике этой ниши на языке ${generateGeo} (эрекция, потенция, либидо, влечение, простата, выносливость и т.п.), уверенный тон; не сглаживай до абстрактного «энергия/ритм/пара» без привязки к симптому/результату и не переноси клише из суставов, ЖКТ или слима.
|
|
895
|
+
- Иконки и схемы тела — только то, что логично для этого оффера; если сомневаешься — lifestyle без анатомической схемы предпочтительнее, чем неверная зона тела.
|
|
896
|
+
- НЕ копируй примеры из промпта — они только показывают формат. Все слова HOOK/буллитов придумывай под конкретный продукт.
|
|
897
|
+
- Это правило ВАЖНЕЕ ВСЕХ остальных правил промпта. Нарушение = полностью нерелевантный креатив.
|
|
898
|
+
|
|
899
|
+
Используй предоставленный рендер упаковки продукта как есть (форма/цвет без изменений). На упаковке запрещены текст/цена/буллеты/стикеры.
|
|
900
|
+
|
|
901
|
+
CRITICAL RULES (это ВАЛИДАЦИЯ, не рекомендации; если нарушено — УДАЛИ ЛИШНЕЕ и ПЕРЕСОБЕРИ МАКЕТ):
|
|
902
|
+
РОЛЬ ЭЛЕМЕНТОВ (маркетинговая логика):
|
|
903
|
+
- HOOK (верхний текст / HEADLINE) = зацепка боли (реальный дискомфорт/состояние) + направление облегчения **в нише этого продукта**
|
|
904
|
+
- Буллеты = свойства ИЛИ ощущаемые преимущества **в теме оффера** (комфорт, уверенность, срок, состав — что уместно для брифа, не «универсальная боль» соседней категории)
|
|
905
|
+
- Цена/скидка = триггер "сейчас"
|
|
906
|
+
- CTA = финальный шаг к действию
|
|
907
|
+
|
|
908
|
+
❗ ЦЕНА (КРИТИЧНО — НЕ ПРОПУСКАЙ):
|
|
909
|
+
- ОБЯЗАТЕЛЬНО ДВЕ цены: старая (до скидки) + новая (${generatePrice} ${generateCurrency}). Одна цена = ОШИБКА.
|
|
910
|
+
${windowStickerCond ? `- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${windowStickerCond} → достаточно новой цены + «-50%» на витринном стикере; старая зачёркнутая НЕ требуется; отдельная CTA-кнопка НЕ требуется.\n` : ''}- Математика для тебя: при -50% сумма «старой» цены должна быть **вдвое** больше новой — но на макете печатай **только цифры и символ валюты**, например новая **${generatePrice} ${generateCurrency}**, старая **удвоенная сумма + ${generateCurrency}** (без каких‑либо слов-множителей).
|
|
911
|
+
- ЗАПРЕЩЕНО писать на ценниках префиксы **«2×», «2x», «x2», «double»** перед суммой — это служебная логика промпта, не надпись для покупателя. Неправильно: «2× ${oldPriceExample}», «2x ${generatePrice} ${generateCurrency}». Правильно: старая строка **«${oldPriceExample}»**, новая **«${generatePrice} ${generateCurrency}»**. Не копируй числа из примеров — только суммы из брифа выше.
|
|
912
|
+
- Новая — выразительно, крупно. Старая — зачёркнута.
|
|
913
|
+
- Зачёркивание: ТОЛСТАЯ линия (не тонкая!), контрастная, хорошо видимая. Тонкая/незаметная линия = ОШИБКА.
|
|
914
|
+
|
|
915
|
+
ЯЗЫК + ТОН:
|
|
916
|
+
- ВСЕ слова строго на языке ${generateGeo} (HOOK/буллеты/CTA/скидка/опциональный бейдж срочности; отдельные читаемые подписи рядом с trust‑печатью если есть). Микротекст по кругу декоративной печати можно не разбирать — не смешивай с рекламным текстом. Английские слова в основном слое запрещены. Исключений нет.
|
|
917
|
+
- НЕ выноси на макет англоязычное **описание/слоган/подзаголовок продукта из брифа** (например «natural joint support for mobility, flexibility and everyday comfort») как рекламный текст — это самая частая причина смешения языков. Такую строку либо **переведи по смыслу на ${generateGeo}**, либо не добавляй вовсе. Английским может остаться **только** бренд-нейм, физически напечатанный **на самой упаковке** продукта; любой текст в рекламном слое (HOOK, подзаголовок под HOOK, буллеты, оффер, CTA) — строго на языке ${generateGeo}.
|
|
918
|
+
- Тон: убедительный, но честный. Лёгкая эмоция и срочность — ок.
|
|
919
|
+
${getMaleVerticalImageToneBlock(generateGeo)}
|
|
920
|
+
|
|
921
|
+
ЛЕКСИКА И ОРФОГРАФИЯ ЦЕЛЕВОГО ЯЗЫКА (КРИТИЧНО — частая ошибка генераторов):
|
|
922
|
+
- На макете допустимы только **обычные словарные слова** языка ${generateGeo}. Запрещены выдуманные формы и «склейки» под слово («DISCONTA», «DESCOUNTO» и любые несуществующие варианты вместо нормального слова «скидка» — ОШИБКА).
|
|
923
|
+
- Если нужна подпись рядом со скидкой кроме «-50%»: используй **одно короткое проверенное слово** языка рынка (например для испанского — «DESCUENTO» / «OFERTA»). Если не уверен в написании — не пиши слово на бейдж: оставь на красной/яркой плашке только крупное «-50%» и процент без длинного текста.
|
|
924
|
+
- Не подставляй **английские слова вместо перевода** и не оставляй «ложных друзей»: на испаноязычном макете не «COMFORT», «CONTROL» в значении «контроль» под английским влиянием и т.п. — только нормальная лексика целевого языка (для комфорта на испанском чаще «CONFORT», «COMODIDAD», «BIENESTAR» и т.д., по контексту).
|
|
925
|
+
- Идеи из англоязычного «пула смыслов» ниже берёшь только как смысл; **на картинке печатаешь полностью переведённые фразы на ${generateGeo}**, без английских корней в видимом тексте.
|
|
926
|
+
|
|
927
|
+
HOOK / HEADLINE (строгое правило):
|
|
928
|
+
- 1–4 строки; до 12 слов. Без переноса внутри слова
|
|
929
|
+
- **ЯКОРЬ НИШИ (минимум один в HOOK):** читатель по заголовку должен понять **какую зону** закрывает продукт, а не «абстрактное здоровье». Возьми **хотя бы одно** предметное слово/короткую отсылку из темы брифа (на языке ${generateGeo}). Примеры уровня смысла (не копируй на другом языке): для слима/контроля веса — фигура, вес, живот, обмен веществ, силуэт, лишние килограммы; для ЖКТ — живот, лёгкость после еды; для суставов — подвижность, колени и т.д. **ЗАПРЕЩЕНО** делать HOOK только из «мета-формулировок» без предмета: одни «эксперты знают», «специалисты советуют», «ключ — это путь/метод/периметр», «целенаправленный маршрут», intriga без указания **чего** это касается — такой текст подойдёт любому БАДу и провалит проверку. Если угол «авторитет/врач» — всё равно добавь предметный маркер нише + можно экспертизу вторым хвостом.
|
|
930
|
+
- Явная привязка к теме продукта из брифа: узнаваемая боль, ситуация или конкретная выгода **в той же нише**, не общий слоган и не тема другого оффера. Иначе — ОШИБКА
|
|
931
|
+
- ЗАПРЕТ НА «ПУСТОЕ» СОЦДОКАЗАТЕЛЬСТВО В HOOK: нельзя делать заголовок **только** из массового доверия/рейтинга и срочности **без** явных маркеров **назначения продукта из брифа** (возьми короткие слова из темы задания: что лечим/что улучшаем — не общие «организм», «поддержка», «лучше»). Читатель по первой строке HOOK должен понять категорию оффера; для другой ниши — свои маркеры на языке ${generateGeo} (слим: figura/peso/…; детокс/очищение/паразиты: очищение/детокс/кишечник/… по смыслу брифа). Соцдоказательство — **вторая строка** или буллеты; верхний HOOK — сначала нишевая боль/результат.
|
|
932
|
+
- НЕ ТАК: только «98% POZYTYWNYCH OPINII — TYLKO DZIŚ!» без слов про очищение/детокс/паразитов из брифа. НЕ ТАК: только «¡MÁS DE 10.000 CONFÍAN…!» + «-50%» без привязки к теме. ТАК: первая строка HOOK с маркером нише из брифа; проценты/«N tys.» при желании второй строкой или в буллете.
|
|
933
|
+
- HOOK ВЫШЕ всех элементов (продукт, буллеты, CTA, цена). Самый крупный текстовый элемент на креативе
|
|
934
|
+
- HOOK должен быть ВИЗУАЛЬНО “тяжёлым”: ОЧЕНЬ крупный, ТОЛСТЫЙ/жирный шрифт, весь текст заголовка ПРОПИСНЫМИ буквами на языке ${generateGeo}, на яркой контрастной плашке/подложке. Это верхний главный элемент, цепляющий внимание в ленте
|
|
935
|
+
- Можно (не обязательно) включить СРОК прямо в HOOK (например «7 дней», «14 дней» — перенеси число и слово «дней» на язык ${generateGeo}) как триггер
|
|
936
|
+
- Заголовок должен быть РЕЗКИМ и призывным: короткие рубленые фразы, вопросы и предупреждения допустимы. Можно использовать обращение на «ты» (естественное для языка ${generateGeo}) и вопросительный знак
|
|
937
|
+
- заголовок НЕ должен быть абстрактным слоганом/лозунгом или метафорой без конкретной боли. Допускается «thumb‑stop» стиль (вызов/вопрос/предупреждение), если это конкретно и в теме продукта из брифа **и** выполнен пункт про якорь нише выше
|
|
938
|
+
- если не влезает: сначала измени композицию (расширь блок/переставь элементы), затем перепиши короче. НЕЛЬЗЯ уменьшать шрифт. HOOK всегда остаётся выше всех остальных элементов
|
|
939
|
+
- Не повторяй один и тот же заголовок в разных подходах: для текущего подхода придумай новый, уникальный заголовок. Варьируй: угол боли, формулировку, акцент (проблема vs облегчение)
|
|
940
|
+
- Вторая часть заголовка = конкретное улучшение, не абстрактное слово. ПРАВИЛЬНО (структура; на макете — только язык ${generateGeo}): боль/вопрос + конкретное облегчение. НЕ ТАК: размытые «легче», «лучше», «решение» без конкретики
|
|
941
|
+
- Специфические медицинские термины или диагнозы разрешены в заголовке, но не обязательны. Для **мужской вертикали** (${exports.MALE_VERTICAL_CRITERIA}) — прямые формулировки симптома/результата предпочтительны. Для остальных вертикалей варьируй между прямыми формулировками (если уместно для продукта) и мягкими формулировками, фокусирующимися на симптомах и дискомфорте, для разных креативов. Не используй один и тот же термин во всех креативах
|
|
942
|
+
ПРИМЕР структуры (русский — только ритм; на макете строго язык ${generateGeo}, формулировки подбирай по смыслу продукта, не копируй чужие ниши из инструкции):
|
|
943
|
+
- НЕ ТАК: общий лозунг без узнаваемой боли/ситуации из темы продукта
|
|
944
|
+
- ТАК: короткая цепочка «узнаваемая боль или ситуация → надежда/облегчение» в **той же теме**, что и продукт
|
|
945
|
+
❗ Если заголовок > 12 слов, похож на длинное предложение или остаётся абстрактным без привязки к нише продукта — ОШИБКА → пересоздай вариант.
|
|
946
|
+
❗ Если HOOK — только доверие/рейтинг без нишеевого крючка (см. «ЗАПРЕТ НА ПУСТОЕ СОЦДОКАЗАТЕЛЬСТВО») — ОШИБКА → пересоздай.
|
|
947
|
+
|
|
948
|
+
BULLETS (жёсткое правило, ровно 3):
|
|
949
|
+
- По умолчанию: ровно 3 буллета
|
|
950
|
+
- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${noBulletsCond} → буллиты ЗАПРЕЩЕНЫ (0 буллитов). Не добавляй буллет‑блок вообще
|
|
951
|
+
- каждый 2–3 слова (макс 4); без запятых; буллет НЕ должен выглядеть как предложение
|
|
952
|
+
- ВИЗУАЛ БУЛЛЕТОВ: крупные, с иконками/галочками (✓), на контрастных подложках. Буллеты ВНЕ упаковки/банки — не на продукте.
|
|
953
|
+
- Буллиты: **либо** столбиком, **либо** три плашки **в одном горизонтальном ряду** — оба варианта допустимы. Минимальный размер шрифта — читались на экране телефона без зума
|
|
954
|
+
|
|
955
|
+
❗ ВЫБОР БУЛЛЕТОВ (КРИТИЧНО): Если выше по промпту задан блок «ОБЯЗАТЕЛЬНЫЕ БУЛЛЕТЫ» — используй его как **три опорных смысла**: переведи на язык ${generateGeo} коротко (2–4 слова), но **перепиши формулировки под тему продукта из брифа**, если исходный смысл не совпадает с нишей (тип выгоды сохрани — «срок / соцдоказательство / состав / комфорт» — слова подставь свои под оффер). Если такого блока нет — выбери 3 смысла из нейтрального пула ниже и тоже адаптируй под продукт; пул только для категории смысла, на макете **ноль английского**. Не копируй дословно строки пула, если они тянут в другую медицинскую вертикаль. **Минимум один** буллет должен содержать явную лексику назначения (как HOOK-якорь): для слима не оставляй все три на уровне «поддержка / качество / тысячи выбрали» без слова про тело/вес/результат — иначе макет выглядит «общим».
|
|
956
|
+
|
|
957
|
+
ПУЛ СМЫСЛОВ — нейтральный, без нишевых якорей (английский не печатать; переписать на ${generateGeo}, 2–4 слова каждый; смысл должен совпасть с продуктом из «🏷️ ПРОДУКТ»):
|
|
958
|
+
• Action/benefit: daily body support, everyday comfort, gentle formula support, noticeable wellness support, for regular use, natural support, visible difference over time, more self-confidence
|
|
959
|
+
• Time/speed: effect in 7–14 days, effect in 2 weeks, fast perceived result, support from day one, effect in 7 days, noticeable soon, from first days of use
|
|
960
|
+
• Social proof: 9 of 10 recommend, 9 of 10 men recommend, thousands already chose, 8 of 10 satisfied with results, high buyer ratings
|
|
961
|
+
• Formula: natural formula, natural ingredients, no unnecessary harsh additives, carefully selected composition, thoughtful ingredient blend
|
|
962
|
+
• Quality of life: calmer every day, more energy, more confidence, steadier well-being, supports what matters to you
|
|
963
|
+
|
|
964
|
+
❗ Если хоть один буллет > 4 слов или похож на предложение/обещание — ОШИБКА → пересоздай.
|
|
965
|
+
|
|
966
|
+
TEXT LIMIT:
|
|
967
|
+
- кроме: HOOK, 3 буллетов, цены, скидки, кнопки — ЛЮБОЙ другой текст запрещён (ярлыки/подписи/дисклеймеры/пояснения)
|
|
968
|
+
${textLimitExceptions}- ДОПУСКАЕТСЯ (не обязательно) ОДИН бейдж срочности: только ясные формулировки («только сегодня», «последние штуки», «акция до конца дня»). ЗАПРЕЩЕНО: «24h» — непонятно что означает.
|
|
969
|
+
- ДОПУСКАЕТСЯ (не обязательно) 1–3 trust‑печати: цветные, яркие лаконичные иконки/бейджи, показывающие соответствие местным (например, европейским) стандартам качества (EU Standard, GMP, ISO-стиль). Строго избегай мелкого, нечитаемого текста и ломаных букв (кракозябр) по ободу и внутри печатей — используй чистые графические символы (звёзды, листья, галочки, флаг ЕС) или исключительно крупные чёткие слова на языке ${generateGeo}. Если делаешь **отдельную** короткую подпись рядом с печатью (не на круге) — только на языке ${generateGeo}, без английского («NATURAL», «QUALITY» и т.д.).
|
|
970
|
+
- HOOK + буллеты <= 24 слова суммарно (HOOK до 12, буллеты до 12); если больше — ОШИБКА → пересоздай
|
|
971
|
+
- Если хочешь добавить ощущение срочности — делай это через формулировки в HOOK/BULLETS, через реквизит/иконки, ИЛИ (не обязательно) через один короткий бейдж срочности. Только ясные формулировки на языке ${generateGeo} (уровень смысла: «последние штуки», «только сегодня», «акция до конца дня»). ЗАПРЕЩЕНО «24h» — непонятно что означает.
|
|
972
|
+
|
|
973
|
+
CTA > PRICE:
|
|
974
|
+
${windowStickerCond ? `- ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${windowStickerCond} → отдельная CTA-кнопка НЕ обязательна; оффер = витринный стикер на стекле («-50%» + новая цена). Новая цена и «-50%» обязательны.\n` : ''}- кнопка CTA (1–2 слова на языке ${generateGeo}) — главный якорь нижнего блока (самый контрастный элемент внизу)
|
|
975
|
+
- цена и скидка видны, но слабее CTA; скидка «-50%» ОБЯЗАТЕЛЬНА и не должна конкурировать с кнопкой
|
|
976
|
+
- ЦЕНА: ОБЯЗАТЕЛЬНО ДВЕ — старая зачёркнута ТОЛСТОЙ линией (не тонкой!), новая выразительно. Одна цена или тонкое зачёркивание — ОШИБКА. Цена не должна выглядеть как буллет.
|
|
977
|
+
❗ Если цена/скидка/бейдж по контрасту или размеру равны или сильнее кнопки — ОШИБКА → ослабь цену/скидку или усили CTA и пересоздай.
|
|
978
|
+
❗ ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${noBulletsCond} → цена и «-50%» могут быть более крупными и заметными, но CTA всё равно должен оставаться очень заметным и выглядеть как кнопка (не теряется на фоне)
|
|
979
|
+
|
|
980
|
+
ПОКАЗЫВАЙ ТОЛЬКО ЭТИ ТЕКСТОВЫЕ ЭЛЕМЕНТЫ:
|
|
981
|
+
- HOOK (1–4 строки; выше всех элементов; самый крупный; прописные буквы; жирный; на яркой контрастной подложке; якорь нише из брифа в тексте — см. «ЯКОРЬ НИШИ», не абстрактная «экспертиза без темы»)
|
|
982
|
+
- 3 буллета (крупные, с иконками/галочками ✓, на контрастных подложках, НЕ на банке/упаковке)
|
|
983
|
+
- Цена: ОБЯЗАТЕЛЬНО ДВЕ — старая **только как число + валюта** (сумма вдвое больше новой; при новой ${generatePrice} ${generateCurrency} на макете старая — удвоенное число и тот же символ валюты) зачёркнута ТОЛСТОЙ контрастной линией + новая ${generatePrice} ${generateCurrency} выразительно. **Без** «2×»/«2x» перед суммой. Одна цена = ОШИБКА. Тонкая линия зачёркивания = ОШИБКА. Без слов. Не на упаковке.
|
|
984
|
+
- Скидка: «-50%» ОБЯЗАТЕЛЬНО отдельным видимым бейджем (не только в цене!). Процент скидки должен быть явно читаем. Ярко, заметно, строго НЕ на банке/упаковке, визуально слабее CTA. На этом бейдже допустимо только «-50%» и при необходимости одно короткое **словарное** слово языка ${generateGeo} для «скидки» — без выдуманных написаний; если сомневаешься — только «-50%»
|
|
985
|
+
- Кнопка CTA (1-2 слова)
|
|
986
|
+
- Опционально: 1 короткий бейдж срочности (ясные формулировки: «только сегодня», «последние штуки»; ЗАПРЕЩЕНО «24h»). Бейдж в углу кадра, контрастный, но меньше CTA. НЕ обязателен
|
|
987
|
+
- Опционально: 1–3 trust‑печати (цветные, яркие, показывающие соответствие местным/европейским стандартам качества). Строго без мелкого нечитаемого текста и ломаных букв (только чистая графика: звёзды, листья, галочки, флаг ЕС). Опционально одна-две короткие подписи рядом строкой футера на ${generateGeo} («натуральный», «европейское качество»); не «NATURAL», «QUALITY». НЕ обязательны
|
|
988
|
+
${showOnlyExceptions}
|
|
989
|
+
ВИЗУАЛ:
|
|
990
|
+
- Иерархия: HOOK ВЫШЕ всех элементов (продукт, буллеты, CTA, цена). HOOK — самый крупный текстовый элемент
|
|
991
|
+
- Буллеты: крупные, с иконками/галочками (✓), на контрастных подложках. Строго ВНЕ упаковки/банки.
|
|
992
|
+
- Цена: ОБЯЗАТЕЛЬНО ДВЕ — старая зачёркнута ТОЛСТОЙ линией (не тонкой!), новая выразительно. Одна цена или тонкое зачёркивание = ОШИБКА. Визуально ОТЛИЧНА от буллитов.
|
|
993
|
+
- Скидка «-50%»: ярко, заметно, на контрастной подложке. Строго ВНЕ упаковки/банки.
|
|
994
|
+
- Текст на контрастных плашках, читабельно на телефоне. Допускается мультяшная/комиксовая стилистика текста (не обязательно)
|
|
995
|
+
- КОНТРАСТ ПЛАШЕК: каждая текстовая плашка (HOOK, буллеты, CTA, цена) должна иметь высокий контраст с фоном — светлый текст на тёмной подложке ИЛИ тёмный текст на светлой. Плашка, сливающаяся с фоном = ОШИБКА → добавь подложку или измени цвет фона/плашки.
|
|
996
|
+
- АНГЛИЙСКИЙ НА УПАКОВКЕ: если на этикетке продукта есть английский текст (например название/описание на упаковке) — не приближай её настолько, чтобы эти надписи были читабельны как отдельный контент. Упаковка = визуальный объект; мелкий этикеточный текст должен быть нечитабелен или едва различим.
|
|
997
|
+
- Без ссылок/доменов и мелкого текста
|
|
998
|
+
- LIFESTYLE/CLEAN: продукт в контексте использования, который читатель свяжет с **этим** продуктом по брифу (момент приёма, быт, активность — по смыслу оффера). Просто продукт на белом фоне — НЕ допускается
|
|
999
|
+
- Цвета и композиция должны быть «thumb‑stop»: высокий контраст, яркий акцент на продукте (луч света/подсветка/обводка/глоу), избегай бледных пастельных сцен
|
|
1000
|
+
- ЛЮДИ: человек допускается ТОЛЬКО для подходов ${humanApproachesList}. Для всех остальных — БЕЗ человека.
|
|
1001
|
+
- Если «Эмоция / Портрет»: женский/нейтральный оффер → женщина. **Мужская вертикаль** (${exports.MALE_VERTICAL_CRITERIA}) → допустимы ДВА варианта: (1) мужчина-ЦА — уверенный, энергичный; (2) привлекательная женщина как «желаемый образ» результата — уверенная, довольная; ассоциация с близостью/партнёрством (${MALE_VERTICAL_DESIRED_IMAGE_BOUNDS}). Прямой взгляд в камеру. Эмоция: облегчение/надежда; для мужской вертикали с мужским портретом — допустим более уверенный/энергичный регистр. Возраст подбери под ЦА из брифа (часто 50–60; если продукт явно для более молодой аудитории — 35–55). Этнически соответствует GEO/рынку.
|
|
1002
|
+
- Если «Врач / Эксперт»: пол врача по вертикали продукта из брифа — **мужская вертикаль** (${exports.MALE_VERTICAL_CRITERIA}) → врач-мужчина 40–55 лет; иначе по умолчанию → женщина-врач 40–55 лет. Внешность и этничность СТРОГО соответствуют GEO/рынку (локал — врач выглядит как местный специалист).
|
|
1003
|
+
- Если «Сплит До/После»: допускаются ДВА человека в кадре одновременно — before/after одной модели по типажу (один пол, схожая внешность, этничность и возраст под GEO/ЦА из брифа). Слева «до» (уставшая/расстроенная, тускло), справа «после» (довольная, подтянутая, ярко, с продуктом в руке). Два человека в кадре — норма именно для этого подхода; не своди композицию к одному портрету.
|
|
1004
|
+
- Для **мужской вертикали** (${exports.MALE_VERTICAL_CRITERIA}) во всех трёх человеческих подходах выше: в HOOK допускается прямая лексика симптома/результата на языке ${generateGeo}; количественные выдуманные клеймы на макете по-прежнему запрещены (см. «КОЛИЧЕСТВЕННЫЕ КЛЕЙМЫ» выше).
|
|
1005
|
+
|
|
1006
|
+
ANTI-TEMPLATE DIVERSITY (КРИТИЧНО):
|
|
1007
|
+
- Ты сейчас создаёшь ОДИН креатив для текущего подхода. В проекте будет серия из ${totalApproaches} креативов, поэтому у каждого подхода должна быть своя узнаваемая композиция.
|
|
1008
|
+
- Для ЭТОГО креатива НЕ используй универсальный шаблон. Обязательно вариируй: (1) крупность/кроп (close-up vs medium vs flat-lay), (2) угол камеры (прямо vs сверху vs диагональ), (3) расположение блоков HOOK/BULLETS/CTA/PRICE/DISCOUNT, (4) свет/фон (но без лишнего текста).
|
|
1009
|
+
- Ориентируйся на строку «🎯 ПОДХОД: ...» и примени соответствующую раскладку ниже (только одну, соответствующую текущему подходу):
|
|
1010
|
+
* 🎯 ПОДХОД: Эксперт / Авторитет → БЕЗ человека. Профессиональный контекст с реквизитом экспертизы вокруг продукта. Продукт в центре. HOOK сверху справа, BULLETS справа ниже, CTA снизу справа, PRICE/DISCOUNT рядом с CTA (слабее CTA). Trust‑печати (если есть) — компактно по низу; круг должен быть чистым, без мелкого нечитаемого текста.
|
|
1011
|
+
* 🎯 ПОДХОД: Lifestyle / Момент приёма → FLAT-LAY/СВЕРХУ или 3/4 сверху на столе/тумбочке. Продукт в центре, реквизит "момент приёма" вокруг. HOOK сверху по центру, BULLETS сбоку (вертикально, шрифт достаточно крупный для чтения на телефоне без зума), CTA снизу по центру, PRICE/DISCOUNT рядом (слабее CTA). Urgency‑бейдж (если есть) — в углу, только ясные формулировки, НЕ «24h». Trust‑печати (если есть) — компактно по низу, без мелкого нечитаемого текста.
|
|
1012
|
+
* 🎯 ПОДХОД: Эмоция / Портрет → Один из трёх подходов с человеком. Для мужской вертикали — портрет мужчины-ЦА ИЛИ женщины как «желаемого образа» (рекламно-приемлемо, ${MALE_VERTICAL_DESIRED_IMAGE_BOUNDS}); иначе пол по ЦА. ОЧЕНЬ крупный портрет лица (thumb‑stop), взгляд в камеру — лицо занимает верхние 2/3 кадра. Продукт в руке или у подбородка. HOOK сверху по центру. BULLETS, CTA, PRICE/DISCOUNT, trust‑печати — в нижней трети.
|
|
1013
|
+
* 🎯 ПОДХОД: Визуализация проблемы → Инфографика/схема: слева проблема (иконка или схема, уместная для продукта по брифу), справа решение + продукт. HOOK сверху по центру, BULLETS справа или снизу (вертикально), CTA снизу справа, PRICE/DISCOUNT возле CTA. Trust‑печати (если есть) — компактно по низу, без мелкого нечитаемого текста. Красный акцент только на проблеме.
|
|
1014
|
+
* 🎯 ПОДХОД: Power / Сила решения → БЕЗ человека. ДИНАМИЧНЫЙ комикс‑кадр, диагональная композиция. Продукт как “герой” + power‑иконки (щит/молния/бёрст). HOOK сверху слева на яркой плашке, BULLETS слева ниже, CTA снизу справа, PRICE/DISCOUNT возле CTA. Trust‑печати (если есть) — компактно по низу, без мелкого нечитаемого текста.
|
|
1015
|
+
* 🎯 ПОДХОД: Минимализм / Clean Big Text → Белый/градиентный фон, минимум элементов. ОГРОМНЫЙ HOOK занимает верх/центр, продукт крупно (центр/право), CTA снизу по центру, PRICE/DISCOUNT рядом (слабее CTA). Trust‑печати (если есть) — по желанию, чистые, без мелкого нечитаемого текста.
|
|
1016
|
+
* 🎯 ПОДХОД: Problem Visual Punch → БЕЗ человека. Яркий сплошной фон (красный/оранжевый) или агрессивный градиент. В центре КРУПНАЯ иконка/схема проблемы, уместная для продукта по брифу, с красным свечением. Продукт крупно рядом. HOOK 1–4 строки, до 12 слов, огромный прописной текст, выше всех. БЕЗ буллитов. Две цены + «-50%» крупно и заметно. Кнопка призыва контрастная (только текст на языке ${generateGeo}, без слова CTA)
|
|
1017
|
+
* 🎯 ПОДХОД: Любительский Примитивизм → БЕЗ человека. Чёрный или кислотный сплошной фон. Продукт по центру или справа без декора. HOOK сверху — 1–4 строки, до 12 слов, крупный, грубый bold/рукописный, прописные буквы, выше всех. Крупные надписи цены/скидки вокруг продукта. Кнопка призыва — плоская, без градиентов (только короткая фраза на языке ${generateGeo}). БЕЗ буллитов, бейджей, теней, иконок.
|
|
1018
|
+
* 🎯 ПОДХОД: Врач / Эксперт → Врач (пол по вертикали: мужская → мужчина, иначе женщина), локал по GEO. Продукт в руках или рядом. Профессиональный фон. HOOK сверху, BULLETS сбоку/снизу, CTA и PRICE/DISCOUNT внизу. Врач и продукт — главные элементы.
|
|
1019
|
+
* 🎯 ПОДХОД: Скрин отзывов → Имитация скриншота: блок отзывов (аватарки, имена, возраст, 5 звёзд, текст на языке GEO). HOOK ОБЯЗАТЕЛЕН — выше отзывов или поверх, крупно. Продукт виден. CTA, PRICE, DISCOUNT внизу.
|
|
1020
|
+
* 🎯 ПОДХОД: Сплит До/После → вертикальный сплит-экран пополам. Слева "до", справа "после", метки сторон на языке GEO. HOOK сверху по центру (крупная дельта результата). Продукт на стыке половин или в руке "после"-модели. BULLETS в нижней трети или сбоку, CTA и PRICE/DISCOUNT в нижнем блоке. Красный/тусклый акцент только на стороне "до".
|
|
1021
|
+
* 🎯 ПОДХОД: Квиз / Выбор возраста → имитация опрос-экрана. Крупный вопрос-фильтр капсом сверху/по центру (HOOK). Ниже — ряд/сетка 3–4 псевдо-кнопок возрастов (декор, контрастные плашки). Продукт сбоку или под квиз-блоком. Цена/скидка/CTA — в нижнем блоке. Фон яркий/нативный, минимум глянца. Без буллетов, без trust-печатей.
|
|
1022
|
+
* 🎯 ПОДХОД: Числовой панч → БЕЗ человека. Агрессивный фон (огонь/градиент/яркий сплошной). Вертикальный стек 2–3 ОГРОМНЫХ числовых плашек справа или по центру — только цифры из брифа/пула (срок, «-50%», «9 из 10» и т.п. на языке ${generateGeo}; без выдуманных +390%/см/N раз). Продукт крупно. HOOK сверху. БЕЗ буллитов. PRICE/DISCOUNT/CTA внизу (CTA сильнее цены).
|
|
1023
|
+
* 🎯 ПОДХОД: Реалистичная витрина → фотореалистичная витрина магазина; ОБЯЗАТЕЛЬНАЯ нишевая инсталляция-метафора доминирует по площади; продукт крупно на подиуме, встроен в инсталляцию; брендовая вывеска/среда вокруг; оффер = стикер «-50%»+цена на стекле; HOOK на стекле/баннере; без буллитов, без агрессивного оффер-блока и без обязательной кнопки; средовой текст витрины = декор.
|
|
1024
|
+
AUTO-CHECK (перед финалом):
|
|
1025
|
+
- HOOK: 1–4 строки, до 12 слов, прописные буквы, жирный на контрастной плашке, выше всех элементов, привязка к теме продукта (боль/ситуация), **есть предметный якорь нише** (см. «ЯКОРЬ НИШИ»), не абстракция и не один только «экспертный» мета-текст, язык ${generateGeo} без английских слов (включая метки HOOK/CTA/CAPS). Не только «тысячи доверяют / N из 10» без маркеров нише; не «абстрактный процент подтверждений» без связи с темой продукта
|
|
1026
|
+
- Скидка/буллеты: нет псевдослов и «английского под видом локали»; на бейдже скидки либо только «-50%», либо словарное слово; буллеты — только реальная лексика ${generateGeo}
|
|
1027
|
+
- Буллеты: по умолчанию ровно 3, каждый <= 4 слов, без запятых, не предложения; смысл **строго в нише продукта из брифа**, без перекрёста с другими вертикалями (суставы/ЖКТ/«боль» без повода и т.п.). ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${noBulletsCond} → буллетов 0 (запрещены)
|
|
1028
|
+
- Нет лишнего текста кроме: HOOK, буллетов, цены, скидки, кнопки (+ опционально 1 бейдж срочности + опционально 1–3 trust‑печати)
|
|
1029
|
+
${autoCheckExceptions}- Есть скидка «-50%» (вне упаковки) и она слабее CTA
|
|
1030
|
+
- Цена: ОБЯЗАТЕЛЬНО ДВЕ (старая + новая). Старая зачёркнута ТОЛСТОЙ контрастной линией. Одна цена = ОШИБКА. Тонкая/незаметная линия зачёркивания = ОШИБКА. На ценниках **нет** префикса «2×»/«2x» у суммы
|
|
1031
|
+
- CTA визуально сильнее цены/скидки
|
|
1032
|
+
- Контраст: каждая текстовая плашка читабельна на телефоне — ни одна не сливается с фоном
|
|
1033
|
+
Если хоть один пункт нарушен — пересоздай креатив.
|
|
1034
|
+
|
|
1035
|
+
ВАЖНО: Твой ответ — это ИЗОБРАЖЕНИЕ, не текст. Не пиши план, не перечисляй элементы текстом, не рассуждай, не вызывай tools. Сразу генерируй визуальный креатив как картинку.`;
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Развёрнутый список задач крео: каждый подход повторяется N раз (0–10), N = imageApproachCounts[i].
|
|
1039
|
+
* poolIndex — индекс строки в CREO_APPROACHES (0-based); в UI таблице это номер строки poolIndex + 1 (1–14).
|
|
1040
|
+
*/
|
|
1041
|
+
function getCreoApproachExpandedTasks(imageApproachCounts) {
|
|
1042
|
+
const counts = imageApproachCounts !== null && imageApproachCounts !== void 0 ? imageApproachCounts : (0, promptOverrides_1.getImageApproachCounts)();
|
|
1043
|
+
const result = [];
|
|
1044
|
+
for (let i = 0; i < exports.CREO_APPROACHES.length && i < counts.length; i++) {
|
|
1045
|
+
const approach = exports.CREO_APPROACHES[i];
|
|
1046
|
+
if (!approach)
|
|
1047
|
+
continue;
|
|
1048
|
+
const override = (0, promptOverrides_1.getCreoApproachOverride)(approach.name);
|
|
1049
|
+
const effNoBullets = getEffectiveCreoNoBullets(approach);
|
|
1050
|
+
const resolved = (override === null || override === void 0 ? void 0 : override.enabled)
|
|
1051
|
+
? Object.assign(Object.assign({}, approach), { noBullets: effNoBullets, prompt: override.customPrompt || approach.prompt, headlineAngle: override.customHeadlineAngle || approach.headlineAngle, bulletsFocus: override.customBulletsFocus || approach.bulletsFocus }) : Object.assign(Object.assign({}, approach), { noBullets: effNoBullets });
|
|
1052
|
+
if (override === null || override === void 0 ? void 0 : override.enabled) {
|
|
1053
|
+
_debugLog(`✅ Using CUSTOM approach: ${approach.name}`, `hasPrompt=${!!override.customPrompt}`, `hasHeadline=${!!override.customHeadlineAngle}`, `hasBullets=${!!override.customBulletsFocus}`);
|
|
1054
|
+
}
|
|
1055
|
+
for (let k = 0; k < counts[i]; k++) {
|
|
1056
|
+
result.push({ approach: resolved, poolIndex: i });
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
return result;
|
|
1060
|
+
}
|
|
1061
|
+
/** Плоский список подходов (без индекса строки) — для обратной совместимости. */
|
|
1062
|
+
function getCreoApproaches() {
|
|
1063
|
+
return getCreoApproachExpandedTasks().map(t => t.approach);
|
|
1064
|
+
}
|
|
1065
|
+
exports.CREO_APPROACHES = [
|
|
1066
|
+
// Порядок = стабильные номера 1–N в UI/статистике. Новые подходы — ТОЛЬКО в конец массива.
|
|
1067
|
+
{
|
|
1068
|
+
name: 'Эксперт / Авторитет',
|
|
1069
|
+
prompt: `ЭКСПЕРТ / АВТОРИТЕТ (без человека): стиль “рекомендация эксперта”, но БЕЗ человека. Профессиональный контекст — аптечные полки на фоне / медицинский планшет / стетоскоп / рецептурный блокнот как реквизит рядом с продуктом. Продукт в центре как “рекомендованное решение”. Чистый профессиональный фон, высокий контраст. Trust‑печати (1–3 шт): цветные, яркие лаконичные иконки соответствия местным/европейским стандартам качества (EU Quality, GMP, ISO), строго без мелкого нечитаемого текста и ломаных букв (только чистая графика: звёзды, листья, галочки, флаг ЕС); опционально короткие подписи рядом строкой на языке GEO.`,
|
|
1070
|
+
headlineAngle: `HOOK: угол «предупреждение / интрига / специалисты знают». Формат: вопрос‑предупреждение ИЛИ “специалисты знают/используют” (адаптируй под GEO). **Обязательно** в той же фразе или соседней строке HOOK — предметное слово нише из брифа (для слима: вес/фигура/живот/метаболизм на языке GEO и т.п.); недостаточно одних «экспертов/ключа/периметра/пути». 1–4 строки, до 12 слов, прописные буквы, не абстракция.`,
|
|
1071
|
+
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (действие + срок + соц.доказательство/формула) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор для этого подхода — не повторяй комбинации из других креативов.`
|
|
1072
|
+
},
|
|
1073
|
+
{
|
|
1074
|
+
name: 'Lifestyle / Момент приёма',
|
|
1075
|
+
prompt: `LIFESTYLE / МОМЕНТ ПРИЁМА: продукт в контексте использования (кухня/стол/спальня/тумбочка). Без человека, но с "историей" (стакан воды, чай, тарелка, будильник/часы/календарь). Срочность: реквизит (часы/таймер‑иконка) и/или опциональный urgency‑бейдж (1–3 слова) в углу кадра — только ясные формулировки («только сегодня», «последние штуки»), ЗАПРЕЩЕНО «24h». Высокий контраст, яркий акцент на продукте. Опционально: 1–3 trust‑печати по низу (лаконичные иконки/бейджи соответствия европейским/местным стандартам качества, строго без мелкого нечитаемого текста и ломаных букв). ВАЖНО: буллиты располагаются вертикально и всегда читабельны на экране телефона без зума — даже если уходят вбок, минимальный размер шрифта буллитов не уменьшается. Если буллиты не вмещаются сбоку с нужным шрифтом — переставь их вниз.`,
|
|
1076
|
+
headlineAngle: `HOOK: угол «цифры + срочность». Формат: число/процент + ограничение времени/“сейчас/сегодня” (адаптируй под GEO), 1–4 строки, до 12 слов, прописные буквы, привязка к теме продукта (боль/ситуация), не абстракция.`,
|
|
1077
|
+
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (срок + цифра + действие/формула) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов.`
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
name: 'Эмоция / Портрет',
|
|
1081
|
+
hasHuman: true,
|
|
1082
|
+
prompt: `ЭМОЦИЯ / ПОРТРЕТ: один из трёх подходов с человеком в серии. Используй максимально: ОЧЕНЬ крупный план лица (thumb‑stop), прямой взгляд в камеру.
|
|
1083
|
+
- ПОЛ / ТИПАЖ: женский или нейтральный оффер → женщина.
|
|
1084
|
+
- **Мужская вертикаль** (${exports.MALE_VERTICAL_CRITERIA}) → допустимы ДВА варианта (выбери один):
|
|
1085
|
+
1) мужчина-ЦА — уверенный, энергичный;
|
|
1086
|
+
2) привлекательная женщина как «желаемый образ» результата — уверенная, довольная; ассоциация с близостью/партнёрством. ${MALE_VERTICAL_DESIRED_IMAGE_BOUNDS}.
|
|
1087
|
+
- Возраст подбери под ЦА из брифа: по умолчанию 50–60; если продукт явно для более молодой аудитории — допускается 35–55.
|
|
1088
|
+
- Эмоция: основа — облегчение/надежда (без широкой стоковой улыбки); для **мужской вертикали** с мужским портретом допустим более уверенный/энергичный регистр (уверенность, энергия, сильное самоощущение); для женского «желаемого образа» — уверенная, довольная, дружелюбная подача; прямая лексика симптома/результата на языке GEO допустима в HOOK/буллетах.
|
|
1089
|
+
- ЛОКАЛИЗАЦИЯ: этничность и типаж под GEO/рынок — человек выглядит как местный житель целевого рынка, не стоковое универсальное лицо.
|
|
1090
|
+
- Продукт в руке на уровне лица или рядом, хорошо виден. Свет "тень → свет" на лице допустим. Минимум отвлекающих деталей, высокий контраст. Опционально: 1–3 trust‑печати по низу (лаконичные иконки соответствия европейским/местным стандартам, без мелкого нечитаемого текста). ИЕРАРХИЯ: лицо — главный и доминирующий визуальный элемент (верхние 2/3 кадра). Все текстовые блоки (HOOK исключение — сверху) уходят в нижнюю треть. Буллиты, цена, CTA НЕ перекрывают лицо и НЕ конкурируют с ним по визуальному весу — они заметно меньше и ниже.`,
|
|
1091
|
+
headlineAngle: `HOOK: угол «персонально на “ты” + результат/облегчение». 1–4 строки, до 12 слов, прописные буквы, привязка к теме продукта (боль/ситуация), не абстракция. Тон максимально личный и прямой.`,
|
|
1092
|
+
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (качество жизни + действие + срок/цифра) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов.`
|
|
1093
|
+
},
|
|
1094
|
+
{
|
|
1095
|
+
name: 'Визуализация проблемы',
|
|
1096
|
+
prompt: `ВИЗУАЛИЗАЦИЯ ПРОБЛЕМЫ (без человека): схема или иконка проблемы, которую читатель свяжет с **этим** продуктом по брифу, + мягкий красный акцент на зоне дискомфорта (не шок‑контент, без графики). Рядом продукт как решение. Можно добавить простую стрелку/переход “проблема → облегчение” как графику (без лишнего текста). Чистый фон, высокая читабельность. Опционально: 1–3 trust‑печати по низу (чистые лаконичные иконки соответствия европейским/местным стандартам, без мелкого нечитаемого текста). БЕЗ человека.`,
|
|
1097
|
+
headlineAngle: `HOOK: прямой вопрос о боли/дискомфорте в теме продукта. 1–4 строки, до 12 слов, прописные буквы, без абстрактного слогана, вопросительный знак допустим.`,
|
|
1098
|
+
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (действие + срок + соц.доказательство) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов.`
|
|
1099
|
+
},
|
|
1100
|
+
{
|
|
1101
|
+
name: 'Power / Сила решения',
|
|
1102
|
+
prompt: `POWER / СИЛА РЕШЕНИЯ (без человека): метафоры силы и победы над проблемой: щит, молния, энергия, взрыв‑бёрст, мощные стикеры/иконки. Продукт как “герой” в центре, высокая энергия, контрастные агрессивные цвета. Можно комикс/anti‑design подачу, но всё должно быть читабельно. Без лишнего текста. Опционально: 1–3 trust‑печати по низу (чистые лаконичные иконки соответствия европейским/местным стандартам, без мелкого нечитаемого текста). БЕЗ человека. Только продукт + power‑иконки.`,
|
|
1103
|
+
headlineAngle: `HOOK: угол «было → стало / победа над проблемой». Можно использовать стрелку “→” как часть перехода. 1–4 строки, до 12 слов, прописные буквы, привязка к теме продукта (боль/ситуация), не абстракция.`,
|
|
1104
|
+
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (действие + скорость + цифра) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов.`
|
|
1105
|
+
},
|
|
1106
|
+
{
|
|
1107
|
+
name: 'Минимализм / Clean Big Text',
|
|
1108
|
+
prompt: `МИНИМАЛИЗМ / CLEAN BIG TEXT (без человека): белый или мягкий градиентный фон, премиальное ощущение. ОГРОМНЫЙ HOOK как главный элемент (прописные буквы, жирный, на контрастной плашке). Продукт крупно, минимум реквизита, минимум шума. Тени/премиальные материалы допустимы, но без лишнего текста. БЕЗ человека. Urgency и trust‑печати в этом подходе НЕ рекомендуются — они нарушают чистоту и ощущение премиальности. Если всё же добавляешь одну печать — допускается чистая лаконичная медаль без мелкого нечитаемого текста.`,
|
|
1109
|
+
headlineAngle: `HOOK: одна максимально простая сильная фраза (коротко и ясно), 1–4 строки, до 12 слов, прописные буквы, привязка к теме продукта (боль/ситуация), не абстракция.`,
|
|
1110
|
+
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (действие + срок + формула/цифра) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов.`
|
|
1111
|
+
},
|
|
1112
|
+
{
|
|
1113
|
+
name: 'Problem Visual Punch',
|
|
1114
|
+
bulletsMode: 'none',
|
|
1115
|
+
prompt: `PROBLEM VISUAL PUNCH (без человека): максимально агрессивный и простой креатив.
|
|
1116
|
+
- Фон: яркий сплошной цвет (красный/оранжевый) или агрессивный градиент
|
|
1117
|
+
- Центр: КРУПНАЯ иконка/схема проблемы, уместная для продукта по брифу, с красным свечением
|
|
1118
|
+
- Продукт: крупно рядом
|
|
1119
|
+
- HOOK: 1–4 строки, до 12 слов, огромный, прописные буквы, привязка к теме продукта (боль/ситуация), не абстракция
|
|
1120
|
+
- БЕЗ буллитов
|
|
1121
|
+
- Цена + скидка: крупно, заметно
|
|
1122
|
+
- CTA: контрастная яркая кнопка
|
|
1123
|
+
|
|
1124
|
+
Цель: считывание за 1 секунду. Минимум текста, максимум визуального удара.
|
|
1125
|
+
БЕЗ человека. Никаких trust‑печатей/urgency бейджей — только HOOK + PRICE + -50% + CTA.`,
|
|
1126
|
+
headlineAngle: `HOOK: «ПРОЩАЙ/КОНЕЦ/СТОП + [проблема]!». Эмоция победы/избавления. 1–4 строки, до 12 слов, прописные буквы, привязка к теме продукта (боль/ситуация), не абстракция.`,
|
|
1127
|
+
bulletsFocus: `БУЛЛИТЫ: ЗАПРЕЩЕНЫ. Вся информация — в HOOK и крупных надписях.`
|
|
1128
|
+
},
|
|
1129
|
+
{
|
|
1130
|
+
name: 'Любительский Примитивизм',
|
|
1131
|
+
bulletsMode: 'none',
|
|
1132
|
+
prompt: `ЛЮБИТЕЛЬСКИЙ ПРИМИТИВИЗМ (без человека): намеренно грубый «анти-дизайн» — эффект честной простой народной рекламы. Вызывает доверие через отказ от маркетингового лоска.
|
|
1133
|
+
- Фон: чёрный или кислотный однотонный (яркий жёлтый / зелёный / красный) — без градиентов
|
|
1134
|
+
- Шрифт: очень крупный bold, как будто написан от руки или набран в MS Paint; грубые засечки или рукописный стиль
|
|
1135
|
+
- Цвета: только базовые — красный, жёлтый, зелёный, белый, чёрный. Без теней, градиентов, глоу
|
|
1136
|
+
- Продукт (банка/упаковка) без декора, без подсветки и обводки — просто и крупно
|
|
1137
|
+
- Элементы выглядят «вырезанными и приклеенными»: неровные края, отсутствие выравнивания по сетке
|
|
1138
|
+
- Крупные текстовые надписи рядом с продуктом: цена, скидка; допустимо одно короткое слово-восклицание («РАБОТАЕТ!», «ПРОВЕРЕНО!») на языке GEO
|
|
1139
|
+
- Кнопка CTA: плоская, без градиентов, контрастный сплошной цвет
|
|
1140
|
+
- НИКАКИХ буллитов, trust‑печатей, urgency‑бейджей, иконок — только продукт и текст`,
|
|
1141
|
+
headlineAngle: `HOOK: максимально прямолинейный — короткий, грубый, без украшений. 1–4 строки, до 12 слов, прописные буквы, привязка к теме продукта (боль/ситуация), не абстракция, как объявление на столбе. Никакого маркетингового лоска, никаких абстрактных слоганов.`,
|
|
1142
|
+
bulletsFocus: `БУЛЛИТЫ: ЗАПРЕЩЕНЫ. Всё — в HOOK и крупных надписях вокруг продукта (цена, скидка, одно слово-восклицание).`
|
|
1143
|
+
},
|
|
1144
|
+
{
|
|
1145
|
+
name: 'Врач / Эксперт',
|
|
1146
|
+
hasHuman: true,
|
|
1147
|
+
prompt: `ВРАЧ / ЭКСПЕРТ (с человеком): врач как авторитет, рекомендующий продукт. Один из трёх подходов с человеком в серии.
|
|
1148
|
+
- ПОЛ ВРАЧА (по вертикали из брифа): по умолчанию (нейтральная или женская вертикаль) — женщина-врач 40–55 лет; если продукт относится к **мужской вертикали** (${exports.MALE_VERTICAL_CRITERIA}) — врач-мужчина 40–55 лет.
|
|
1149
|
+
- Врач: профессиональный вид (медицинский халат, планшет/стетоскоп/рецептурный блокнот). Уверенная, располагающая поза.
|
|
1150
|
+
- ЛОКАЛИЗАЦИЯ (КРИТИЧНО): врач НЕ generic — явно угадывается регион/GEO. Черты лица, тип кожи, причёска — характерные для целевого рынка. RO → румынский тип; PL → польский; HU → венгерский; ES → испанский/латино; IT → итальянский. Врач = местный специалист, не стоковое универсальное лицо.
|
|
1151
|
+
- Продукт: в руках врача или на столе/планшете рядом, хорошо виден.
|
|
1152
|
+
- Фон: профессиональный (кабинет, аптечные полки, медицинский контекст). Высокий контраст, читабельность.
|
|
1153
|
+
- Опционально: 1–3 trust‑печати по низу (чистые лаконичные иконки соответствия европейским/местным стандартам, без мелкого нечитаемого текста).
|
|
1154
|
+
- ИЕРАРХИЯ: врач + продукт — главные элементы. HOOK сверху, BULLETS сбоку или снизу, CTA и PRICE/DISCOUNT в нижнем блоке.`,
|
|
1155
|
+
headlineAngle: `HOOK: угол «врач/специалист рекомендует» или «эксперты знают». **Плюс** явный маркер темы продукта в HOOK (см. базовый блок «ЯКОРЬ НИШИ»): не делай заголовок только из «доверия к врачу» без слова про то, **что** улучшают (вес, комфорт ЖКТ и т.д. по брифу). 1–4 строки, до 12 слов, прописные буквы, не абстракция.`,
|
|
1156
|
+
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (действие + срок + соц.доказательство) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов.`
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
name: 'Скрин отзывов',
|
|
1160
|
+
bulletsMode: 'none',
|
|
1161
|
+
validatorKey: 'screenshot_reviews',
|
|
1162
|
+
prompt: `СКРИН ОТЗЫВОВ: имитация реалистичного скриншота с положительными благодарными отзывами и оценками 5 звёзд.
|
|
1163
|
+
- Визуал: реалистичный стиль — как скриншот приложения/сайта отзывов (App Store, Google Play, или страница отзывов). Высокое качество, читабельный текст.
|
|
1164
|
+
- Шапка окна / подписи интерфейса внутри рамки телефона: допускаются короткие англоязычные метки как у реального UI («Reviews», бейдж стора) — это не рекламный текст баннера.
|
|
1165
|
+
- Отзывы: 2–4 отзыва с аватарками, именами и возрастом (формат «Имя, 45 лет»), ОБЯЗАТЕЛЬНО 5 звёзд (★★★★★) в каждом, короткий текст благодарности. Текст отзывов СТРОГО на языке GEO — без английского в теле отзыва. Релевантен категории продукта.
|
|
1166
|
+
- HOOK ОБЯЗАТЕЛЕН: крупно, выше блока отзывов или поверх, прописные буквы, на яркой подложке. Ключевое слово проблемы явно.
|
|
1167
|
+
- Продукт: виден в кадре (рядом со скрином или интегрирован в композицию).
|
|
1168
|
+
- Цена, скидка «-50%», CTA — в нижней части. БЕЗ буллитов — отзывы заменяют их.
|
|
1169
|
+
- Стиль: не мультяшный, не комикс — максимально реалистичный скрин.`,
|
|
1170
|
+
headlineAngle: `HOOK: угол «тысячи довольны» / «9 из 10 рекомендуют» / «реальный результат». 1–4 строки, до 12 слов, прописные буквы, привязка к теме продукта (боль/ситуация), не абстракция.`,
|
|
1171
|
+
bulletsFocus: `БУЛЛИТЫ: ЗАПРЕЩЕНЫ. Вся информация — в HOOK, отзывах (с 5 звёздами), цене и CTA.`
|
|
1172
|
+
},
|
|
1173
|
+
{
|
|
1174
|
+
name: 'Сплит До/После',
|
|
1175
|
+
hasHuman: true,
|
|
1176
|
+
prompt: `СПЛИТ ДО/ПОСЛЕ (с человеком): вертикальный сплит-экран пополам — слева «до» (проблема, тускло, крупнее), справа «после» (результат, ярко/светло). Продукт как медиатор между состояниями.
|
|
1177
|
+
- ОСНОВНАЯ ВЕТКА (предпочтительно): два реальных человека — одна и та же по типажу модель «до» и «после»: один пол, схожая внешность, чтобы читалось как один человек. Слева — расстроенная/уставшая; справа — довольная, подтянутая, держит продукт в руке на уровне груди/лица. Этничность и возраст под GEO/ЦА из брифа.
|
|
1178
|
+
- ЗАПАСНАЯ ВЕТКА (реже, если фото неуместны): два силуэта тела вместо фото — слева объёмный тёмный/красный, справа стройный синий/светлый глоу; продукт по центру на стыке половин.
|
|
1179
|
+
- Подписи сторон: короткие метки «до»/«после» на языке GEO под каждой стороной; допустима дельта веса рядом с меткой (−кг для слим-вертикали).
|
|
1180
|
+
- Разделение половин: чёткая вертикальная граница или градиент по центру. Фон — контраст «тускло слева → ярко справа».
|
|
1181
|
+
- Опционально: 1–3 trust‑печати по низу (чистые иконки, без мелкого текста).
|
|
1182
|
+
- Два человека в кадре одновременно — норма именно для этого подхода.`,
|
|
1183
|
+
headlineAngle: `HOOK: угол «результат-дельта + снятие условия». Ядро — крупная дельта результата в теме продукта: для слим/веса цифры −кг уместны (продукт про вес); плюс снятие привычной жертвы («без диеты», «без голода» на языке GEO). Для не-весовых офферов дельта = симптомный/комфортный результат, без кг. 1–4 строки, до 12 слов, прописные, не абстракция. Якорь нише выполняется автоматически через дельту.`,
|
|
1184
|
+
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (результат + срок + соц.доказательство/формула) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов. Минимум один буллет с явной лексикой результата нише.`
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
name: 'Квиз / Выбор возраста',
|
|
1188
|
+
bulletsMode: 'none',
|
|
1189
|
+
allowsAgeButtons: true,
|
|
1190
|
+
allowsExtraText: true,
|
|
1191
|
+
validatorKey: 'quiz_age',
|
|
1192
|
+
prompt: `КВИЗ / ВЫБОР ВОЗРАСТА (без человека): имитация квиз-экрана / опросника — статичная картинка, НЕ реальная интерактивность, только визуальный шаблон опроса.
|
|
1193
|
+
- Центральный элемент: крупный вопрос-фильтр КАПСОМ на языке GEO, релевантный теме продукта из брифа (узнаваемая боль/симптом в нише; для **мужской вертикали** — прямая лексика, см. общий блок мужской вертикали).
|
|
1194
|
+
- Ниже вопроса: ряд или сетка из 3–4 псевдо-кнопок с возрастными диапазонами («18–30», «30–45», «45–60», «60+» — цифры универсальны; подписи при необходимости — на языке GEO). Псевдо-кнопки — контрастные кликабельные плашки (декор, не настоящие кнопки).
|
|
1195
|
+
- Продукт виден в кадре (сбоку или под квиз-блоком).
|
|
1196
|
+
- Фон: яркий/кислотный однотонный или простой, в духе нативного «непрофессионального» поста — считывается как настоящий опрос, не глянцевая реклама.
|
|
1197
|
+
- Внизу: две цены (стандарт), скидка «-50%», финальная CTA-кнопка.
|
|
1198
|
+
- БЕЗ человека. БЕЗ trust‑печатей. БЕЗ буллитов.`,
|
|
1199
|
+
headlineAngle: `HOOK: угол «вопрос-фильтр + микро-вовлечение». HOOK = сам вопрос-фильтр: узнаваемая боль/ситуация в нише продукта + приглашение «узнай, что тебе подходит / что делать» на языке GEO. Крупно, капсом, якорь нише обязателен. 1–4 строки, до 12 слов. Дельта/цифры не обязательны — ядро в вопросе и приглашении.`,
|
|
1200
|
+
bulletsFocus: `БУЛЛИТЫ: ЗАПРЕЩЕНЫ. Вся информация — в вопросе-фильтре, псевдо-кнопках возрастов, цене и CTA.`
|
|
1201
|
+
},
|
|
1202
|
+
{
|
|
1203
|
+
name: 'Числовой панч',
|
|
1204
|
+
bulletsMode: 'none',
|
|
1205
|
+
allowsExtraText: true,
|
|
1206
|
+
prompt: `ЧИСЛОВОЙ ПАНЧ (без человека): агрессивный креатив — композиция и ритм через стек крупных числовых плашек.
|
|
1207
|
+
- Фон: огонь / агрессивный градиент / сплошной яркий цвет (красный, оранжевый, жёлтый)
|
|
1208
|
+
- Справа или по центру: вертикальный стек из 2–3 КРУПНЫХ контрастных числовых плашек — главный визуальный удар
|
|
1209
|
+
- Числа в стеке: ТОЛЬКО из брифа или допустимого пула — срок («7 дней», «14 дней»), «-50%», «9 из 10», порции/упаковки и т.п.; формулировки на языке GEO
|
|
1210
|
+
- ЗАПРЕТ (см. общий блок «КОЛИЧЕСТВЕННЫЕ КЛЕЙМЫ»): выдуманные измеримые обещания результата — проценты прироста («+390%»), сантиметры («+3–5 см»), «N раз за ночь» и любые измеримые обещания, которых нет в брифе
|
|
1211
|
+
- Продукт: крупно в кадре (слева или на стыке с числовым стеком)
|
|
1212
|
+
- HOOK: сверху, 1–4 строки, до 12 слов, прописные буквы; для **мужской вертикали** (${exports.MALE_VERTICAL_CRITERIA}) — прямая лексика ниши в HOOK разрешена
|
|
1213
|
+
- БЕЗ буллитов — числовой стек заменяет их
|
|
1214
|
+
- Цена (две суммы) + скидка «-50%» + CTA — в нижнем блоке
|
|
1215
|
+
- БЕЗ человека. Trust/urgency минимум — акцент на числовом стеке`,
|
|
1216
|
+
headlineAngle: `HOOK: угол «результат крупными числами» — цифры из брифа как главный визуальный удар в связке с текстом HOOK; якорь нише обязателен (см. «ЯКОРЬ НИШИ»). 1–4 строки, до 12 слов, прописные буквы, не абстракция.`,
|
|
1217
|
+
bulletsFocus: `БУЛЛИТЫ: ЗАПРЕЩЕНЫ. Числовой стек из 2–3 плашек заменяет буллеты; числа только из брифа/допустимого пула.`
|
|
1218
|
+
},
|
|
1219
|
+
{
|
|
1220
|
+
name: 'Реалистичная витрина',
|
|
1221
|
+
bulletsMode: 'none',
|
|
1222
|
+
offerMode: 'window_sticker',
|
|
1223
|
+
allowsExtraText: true,
|
|
1224
|
+
validatorKey: 'shop_window',
|
|
1225
|
+
prompt: `РЕАЛИСТИЧНАЯ ВИТРИНА (без человека): фотореалистичная витрина ритейл-магазина (снаружи или изнутри) — продукт представлен как товар в настоящем магазине. Носитель доверия — офлайн-легитимность («продаётся в реальном магазине»).
|
|
1226
|
+
- ЯДРО ВИТРИНЫ — ОБЯЗАТЕЛЬНАЯ тематическая инсталляция-метафора ниши: крупный доминирующий по площади объект/декор, который читатель за 1 секунду свяжет с нишей продукта из брифа. Просто продукт на полке БЕЗ нишевой метафоры для этого подхода НЕ допускается (ошибка, как HOOK без якоря нише). Примеры уровня смысла (НЕ копировать буквально, подобрать под конкретный оффер, текст на языке GEO): слим/вес — мерные ленты, весы, силуэт фигуры, лишние сантиметры; суставы/подвижность — свободное движение, лёгкость шага; детокс/ЖКТ — чистота, вода, зелень; сон — спокойствие, ночь. Метафора СТРОГО из ниши продукта; переносить метафору чужой вертикали ЗАПРЕЩЕНО.
|
|
1227
|
+
- МУЖСКАЯ ВЕРТИКАЛЬ (${exports.MALE_VERTICAL_CRITERIA}) — инсталляция = абстрактные символы силы/энергии/уверенности/пары; допустим и нейтральный атлетичный силуэт-символ / героическая фигура (контур человека как метафора силы/формы, без откровенности). ЗАПРЕЩЕНО только сексуализированное/обнажённое/анатомически-акцентированное/суггестивное (акцент на паху/торсе, эротика, «объект желания»). ВАРЬИРУЙ символ между генерациями, не по умолчанию «стрелка вверх»: восходящая динамика (стрелка/график), механизм восстановления (шестерни), молекула/ДНК-спираль (для аптеки/науки предпочтительнее), энергия/разряд, два силуэта-пары, восходящее пламя/свет.
|
|
1228
|
+
- ПРЕДОХРАНИТЕЛЬ: если для ниши трудно построить ясную приличную буквальную метафору — используй абстрактную нишевую метафору результата (энергия/лёгкость/уверенность/чистота по смыслу оффера) как инсталляцию. Полностью «пустая» премиальная витрина без нишевого крючка не проходит; но и вымученный буквальный символ не нужен — достаточно, чтобы тема ниши считывалась.
|
|
1229
|
+
- ПРОДУКТ: крупно на переднем плане (подиум / фокус витрины, встроен в инсталляцию в тон декору), хорошо читается — не на дальней полке. Масштаб правдоподобный для витрины (не гигантская коробка во всю витрину), но главный за счёт подсветки и центрального размещения. ОПЦИОНАЛЬНО (если уместно): несколько упаковок выложены ритейл-мерчандайзингом — аккуратная пирамидка/стопка/симметричная композиция на подиуме, как промо-выкладка в реальном магазине; передняя упаковка в фокусе и читаема. Не обязательно — одиночная упаковка тоже ок.
|
|
1230
|
+
- ОФФЕР: стикер физически наклеен НА стекло витрины — «-50%» + новая цена (сумма и валюта из брифа): с лёгким бликом/отражением на поверхности стикера, мягкой тенью на стекло, чуть заметным краем наклейки; НЕ парит в воздухе перед витриной. Отдельная агрессивная кнопка-CTA не нужна. ВЕСЬ текст (HOOK, оффер) — на физическом носителе: винил/наклейка на стекле, подсвеченный баннер в витрине, табличка на подиуме или вывеска; текст НЕ левитирует в пустоте. HOOK крупно (для мужской вертикали — прямая лексика ниши). Средовой текст витрины (вывеска, постеры/ценники внутри, брендинг на стенах) реалистичен и допустим как ДЕКОР.
|
|
1231
|
+
- ФОТО-РЕАЛИЗМ: направленный акцентный свет на продукт и инсталляцию (премиальный ритейл-мерчандайзинг), фон мягко затемнён — не плоский равномерный свет. Ракурс — взгляд прохожего с улицы через стекло: лёгкие отражения улицы/неба на стекле, рама витрины по краям кадра. Тип магазина согласован с нишей (для БАД/здоровья — аптека/парафармация/велнес с упаковками на полках, не одежда/электроника).
|
|
1232
|
+
- БЕЗ буллитов. БЕЗ человека (по умолчанию). Стиль под нишу: премиально-чистый или яркий.`,
|
|
1233
|
+
headlineAngle: `HOOK: угол «легитимность + доступность» — продукт доступен / продаётся здесь + якорь нише (см. «ЯКОРЬ НИШИ»). Крупно на витринном стекле или баннере, не абстракция. 1–4 строки, до 12 слов, прописные буквы.`,
|
|
1234
|
+
bulletsFocus: `БУЛЛИТЫ: ЗАПРЕЩЕНЫ. Оффер = витринный стикер («-50%» + новая цена); носитель — реалистичная витрина + обязательная нишевая инсталляция-метафора.`
|
|
1235
|
+
}
|
|
1236
|
+
];
|
|
1237
|
+
function findCreoApproachByName(approachLabel) {
|
|
1238
|
+
const base = getCreoApproachBaseNameFromImageLabel(approachLabel.trim());
|
|
1239
|
+
return exports.CREO_APPROACHES.find(a => a.name === base);
|
|
1240
|
+
}
|
|
1241
|
+
function creoHumanAllowedNamesList() {
|
|
1242
|
+
return exports.CREO_APPROACHES.filter(a => a.hasHuman).map(a => `«${a.name}»`).join(', ');
|
|
1243
|
+
}
|