.
This commit is contained in:
@@ -668,46 +668,84 @@ public class MarketingAnalysisService {
|
||||
+ " - проценты/строки формата \"76/100\", \"+27%\", \"1.34x\" => string\n"
|
||||
+ " - monthly_online_index.* => number (double)\n"
|
||||
+ " - funnel_metrics.leads/bookings/payments => integer\n"
|
||||
+ "5) Пиши на русском языке.\n\n"
|
||||
+ "Ниже пример правильной структуры (пример для ориентира; цифры должны быть основаны на evidence):\n"
|
||||
+ "5) Пиши на русском языке.\n"
|
||||
+ "6) НИКОГДА не копируй значения из примера. В примере намеренно стоят плейсхолдеры, "
|
||||
+ "которые начинаются с 'EXAMPLE__' и числа -9999/-9999.0 — в твоем ответе их быть НЕ должно.\n\n"
|
||||
+ "Ниже пример правильной структуры (пример только для формы/полей; все значения должны быть заменены на значения из evidence):\n"
|
||||
+ exampleJson;
|
||||
|
||||
String contextJson = objectMapper.writeValueAsString(Map.of(
|
||||
"request", request,
|
||||
"evidence", researchPack));
|
||||
|
||||
// 3) Call OpenAI (sleep to reduce 429 rate-limit bursts)
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
// 3) Call OpenAI (sleep to reduce 429 rate-limit bursts) + guard against
|
||||
// copying placeholders
|
||||
String lastCleaned = null;
|
||||
for (int attempt = 1; attempt <= 2; attempt++) {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
String attemptInstruction = instruction;
|
||||
if (attempt > 1) {
|
||||
attemptInstruction = instruction
|
||||
+ "\n\nКРИТИЧЕСКИ: В ПРЕДЫДУЩЕМ ОТВЕТЕ БЫЛИ ПЛЕЙСХОЛДЕРЫ."
|
||||
+ " Перегенерируй ответ, полностью заменив любые строки, содержащие 'EXAMPLE__',"
|
||||
+ " и любые числа -9999 / -9999.0 на реальные значения."
|
||||
+ " Верни ТОЛЬКО JSON.";
|
||||
}
|
||||
|
||||
String aiResponse = openAIAnalyticsService.generateWithInstructionWithModel(
|
||||
contextJson,
|
||||
attemptInstruction,
|
||||
"ru",
|
||||
textModelName,
|
||||
systemPrompt,
|
||||
15000,
|
||||
180000L);
|
||||
|
||||
if (aiResponse == null || aiResponse.isBlank()) {
|
||||
throw new IllegalStateException("OpenAI returned empty response for analysis v2");
|
||||
}
|
||||
|
||||
// 4) Clean + validate placeholders + parse
|
||||
String cleaned = cleanJsonFromMarkdown(aiResponse);
|
||||
if (cleaned != null) {
|
||||
cleaned = cleaned.replace("\uFEFF", "").trim();
|
||||
}
|
||||
lastCleaned = cleaned;
|
||||
|
||||
if (containsV2ExamplePlaceholders(cleaned)) {
|
||||
logger.warn("generateAnalysisV2: LLM output still contains placeholders (attempt {}/2). Retrying.",
|
||||
attempt);
|
||||
continue;
|
||||
}
|
||||
|
||||
return objectMapper.readValue(cleaned, MarketingAnalysisResponseV2.class);
|
||||
}
|
||||
|
||||
String aiResponse = openAIAnalyticsService.generateWithInstructionWithModel(
|
||||
contextJson,
|
||||
instruction,
|
||||
"ru",
|
||||
textModelName,
|
||||
systemPrompt,
|
||||
15000,
|
||||
180000L);
|
||||
|
||||
if (aiResponse == null || aiResponse.isBlank()) {
|
||||
throw new IllegalStateException("OpenAI returned empty response for analysis v2");
|
||||
}
|
||||
|
||||
// 4) Clean + parse
|
||||
String cleaned = cleanJsonFromMarkdown(aiResponse);
|
||||
if (cleaned != null) {
|
||||
cleaned = cleaned.replace("\uFEFF", "").trim();
|
||||
}
|
||||
return objectMapper.readValue(cleaned, MarketingAnalysisResponseV2.class);
|
||||
throw new IllegalStateException(
|
||||
"OpenAI returned response containing placeholder tokens for analysis v2: " + lastCleaned);
|
||||
} catch (Exception e) {
|
||||
logger.error("generateAnalysisV2: Failed to generate/parse v2 response: {}", e.getMessage(), e);
|
||||
throw new RuntimeException("Не удалось сгенерировать marketing analysis v2", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean containsV2ExamplePlaceholders(String json) {
|
||||
if (json == null || json.isBlank()) {
|
||||
return true;
|
||||
}
|
||||
// Explicit placeholder tokens from buildAnalysisV2ExampleForPrompt()
|
||||
if (json.contains("EXAMPLE__")) {
|
||||
return true;
|
||||
}
|
||||
// Numeric placeholders from buildAnalysisV2ExampleForPrompt()
|
||||
return json.contains("-9999");
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерирует анализ v2 и сохраняет его в MongoDB
|
||||
*
|
||||
@@ -797,213 +835,217 @@ public class MarketingAnalysisService {
|
||||
*/
|
||||
private MarketingAnalysisResponseV2 buildAnalysisV2ExampleForPrompt() {
|
||||
MarketingAnalysisResponseV2 response = new MarketingAnalysisResponseV2();
|
||||
response.setReportTitle("Маркетинговый анализ для интернет-продвижения");
|
||||
response.setReportTitle("EXAMPLE__REPORT_TITLE");
|
||||
|
||||
MarketingAnalysisResponseV2.Sections sections = new MarketingAnalysisResponseV2.Sections();
|
||||
|
||||
// market_overview
|
||||
MarketingAnalysisResponseV2.MarketOverview marketOverview = new MarketingAnalysisResponseV2.MarketOverview();
|
||||
marketOverview.setTitle("Обзор рынка");
|
||||
marketOverview.setTitle("EXAMPLE__MARKET_OVERVIEW_TITLE");
|
||||
MarketingAnalysisResponseV2.MarketOverviewMetrics moMetrics = new MarketingAnalysisResponseV2.MarketOverviewMetrics();
|
||||
moMetrics.setOnlineDemandIndex("76/100");
|
||||
moMetrics.setOnlinePotential("Высокий");
|
||||
moMetrics.setDemandGrowthRateYoy("+27%");
|
||||
moMetrics.setSeasonalityCoefficientSpring("1.34x");
|
||||
moMetrics.setSeasonalityRange("1.29 - 1.38");
|
||||
moMetrics.setOnlineDemandIndex("EXAMPLE__ONLINE_DEMAND_INDEX");
|
||||
moMetrics.setOnlinePotential("EXAMPLE__ONLINE_POTENTIAL");
|
||||
moMetrics.setDemandGrowthRateYoy("EXAMPLE__DEMAND_GROWTH_RATE_YOY");
|
||||
moMetrics.setSeasonalityCoefficientSpring("EXAMPLE__SEASONALITY_COEFFICIENT_SPRING");
|
||||
moMetrics.setSeasonalityRange("EXAMPLE__SEASONALITY_RANGE");
|
||||
marketOverview.setMetrics(moMetrics);
|
||||
MarketingAnalysisResponseV2.MonthlyOnlineIndex monthlyOnlineIndex = new MarketingAnalysisResponseV2.MonthlyOnlineIndex();
|
||||
monthlyOnlineIndex.setMarch(1.32);
|
||||
monthlyOnlineIndex.setApril(1.34);
|
||||
monthlyOnlineIndex.setMay(1.38);
|
||||
monthlyOnlineIndex.setMarch(-9999.0);
|
||||
monthlyOnlineIndex.setApril(-9999.0);
|
||||
monthlyOnlineIndex.setMay(-9999.0);
|
||||
marketOverview.setMonthlyOnlineIndex(monthlyOnlineIndex);
|
||||
marketOverview.setGeography("Казахстан (анализ по регионам представлен на тепловой карте)");
|
||||
marketOverview.setConclusion(
|
||||
"Онлайн-спрос показывает устойчивый рост в течение года, весной достигая пика. Интернет-продвижение даст максимальный эффект.");
|
||||
marketOverview.setGeography("EXAMPLE__GEOGRAPHY");
|
||||
marketOverview.setConclusion("EXAMPLE__MARKET_OVERVIEW_CONCLUSION");
|
||||
sections.setMarketOverview(marketOverview);
|
||||
|
||||
// target_audience
|
||||
MarketingAnalysisResponseV2.TargetAudience targetAudience = new MarketingAnalysisResponseV2.TargetAudience();
|
||||
targetAudience.setTitle("Целевая аудитория");
|
||||
targetAudience.setTitle("EXAMPLE__TARGET_AUDIENCE_TITLE");
|
||||
MarketingAnalysisResponseV2.TargetAudienceMetrics taMetrics = new MarketingAnalysisResponseV2.TargetAudienceMetrics();
|
||||
taMetrics.setTotalAudienceSize("1.8 млн человек");
|
||||
taMetrics.setLeadingSegmentShare("29%");
|
||||
taMetrics.setAboveAverageIncomeShare("35%");
|
||||
taMetrics.setTotalAudienceSize("EXAMPLE__TOTAL_AUDIENCE_SIZE");
|
||||
taMetrics.setLeadingSegmentShare("EXAMPLE__LEADING_SEGMENT_SHARE");
|
||||
taMetrics.setAboveAverageIncomeShare("EXAMPLE__ABOVE_AVERAGE_INCOME_SHARE");
|
||||
targetAudience.setMetrics(taMetrics);
|
||||
targetAudience.setSegments(List.of(
|
||||
new MarketingAnalysisResponseV2.AudienceSegment("Женщины, 25–34 года", "29%"),
|
||||
new MarketingAnalysisResponseV2.AudienceSegment("Мужчины, 25–44 года", "24%"),
|
||||
new MarketingAnalysisResponseV2.AudienceSegment("Доход выше среднего", "35%")));
|
||||
new MarketingAnalysisResponseV2.AudienceSegment("EXAMPLE__AUDIENCE_SEGMENT_1",
|
||||
"EXAMPLE__AUDIENCE_SEGMENT_SHARE_1"),
|
||||
new MarketingAnalysisResponseV2.AudienceSegment("EXAMPLE__AUDIENCE_SEGMENT_2",
|
||||
"EXAMPLE__AUDIENCE_SEGMENT_SHARE_2"),
|
||||
new MarketingAnalysisResponseV2.AudienceSegment("EXAMPLE__AUDIENCE_SEGMENT_3",
|
||||
"EXAMPLE__AUDIENCE_SEGMENT_SHARE_3")));
|
||||
Map<String, String> ageStructure = new LinkedHashMap<>();
|
||||
ageStructure.put("18-24", "10%");
|
||||
ageStructure.put("25-34", "29%");
|
||||
ageStructure.put("35-44", "Высокая доля (визуально на графике)");
|
||||
ageStructure.put("45-54", "15-24%");
|
||||
ageStructure.put("55_plus", "Низкая доля");
|
||||
ageStructure.put("18-24", "EXAMPLE__AGE_18_24_SHARE");
|
||||
ageStructure.put("25-34", "EXAMPLE__AGE_25_34_SHARE");
|
||||
ageStructure.put("35-44", "EXAMPLE__AGE_35_44_SHARE");
|
||||
ageStructure.put("45-54", "EXAMPLE__AGE_45_54_SHARE");
|
||||
ageStructure.put("55_plus", "EXAMPLE__AGE_55_PLUS_SHARE");
|
||||
targetAudience.setAgeStructure(ageStructure);
|
||||
targetAudience.setConclusion(
|
||||
"Основную ценность представляют мужчины и женщины 25–44 лет с доходом выше среднего (до 35% аудитории).");
|
||||
targetAudience.setConclusion("EXAMPLE__TARGET_AUDIENCE_CONCLUSION");
|
||||
sections.setTargetAudience(targetAudience);
|
||||
|
||||
// competitive_environment
|
||||
MarketingAnalysisResponseV2.CompetitiveEnvironment competitiveEnvironment = new MarketingAnalysisResponseV2.CompetitiveEnvironment();
|
||||
competitiveEnvironment.setTitle("Конкурентная среда");
|
||||
competitiveEnvironment.setTitle("EXAMPLE__COMPETITIVE_ENVIRONMENT_TITLE");
|
||||
MarketingAnalysisResponseV2.CompetitiveEnvironmentMetrics ceMetrics = new MarketingAnalysisResponseV2.CompetitiveEnvironmentMetrics();
|
||||
ceMetrics.setMarketShareTraffic("16%");
|
||||
ceMetrics.setVisibilityRank("#3");
|
||||
ceMetrics.setCompetitorShareInContextAds("27%");
|
||||
ceMetrics.setBenchmarkAstana("13-25%");
|
||||
ceMetrics.setMarketShareTraffic("EXAMPLE__MARKET_SHARE_TRAFFIC");
|
||||
ceMetrics.setVisibilityRank("EXAMPLE__VISIBILITY_RANK");
|
||||
ceMetrics.setCompetitorShareInContextAds("EXAMPLE__COMPETITOR_SHARE_IN_CONTEXT_ADS");
|
||||
ceMetrics.setBenchmarkAstana("EXAMPLE__BENCHMARK_ASTANA");
|
||||
competitiveEnvironment.setMetrics(ceMetrics);
|
||||
Map<String, Integer> digitalVisibilityBenchmarks = new LinkedHashMap<>();
|
||||
digitalVisibilityBenchmarks.put("competitor_a", 1050);
|
||||
digitalVisibilityBenchmarks.put("your_business", 600);
|
||||
digitalVisibilityBenchmarks.put("lead", 300);
|
||||
digitalVisibilityBenchmarks.put("payment", 450);
|
||||
digitalVisibilityBenchmarks.put("others", 680);
|
||||
digitalVisibilityBenchmarks.put("competitor_a", -9999);
|
||||
digitalVisibilityBenchmarks.put("your_business", -9999);
|
||||
digitalVisibilityBenchmarks.put("lead", -9999);
|
||||
digitalVisibilityBenchmarks.put("payment", -9999);
|
||||
digitalVisibilityBenchmarks.put("others", -9999);
|
||||
competitiveEnvironment.setDigitalVisibilityBenchmarks(digitalVisibilityBenchmarks);
|
||||
Map<String, List<String>> competitorStrengths = new LinkedHashMap<>();
|
||||
competitorStrengths.put("your_business", List.of("Цена", "Оффер"));
|
||||
competitorStrengths.put("competitor_a", List.of("Отзывы", "Рекламный бюджет"));
|
||||
competitorStrengths.put("competitor_b", List.of("Контент", "Соцсети", "Экспириенс"));
|
||||
competitorStrengths.put("competitor_c", List.of("Контент", "Сайт"));
|
||||
competitorStrengths.put("your_business", List.of("EXAMPLE__STRENGTH_1", "EXAMPLE__STRENGTH_2"));
|
||||
competitorStrengths.put("competitor_a", List.of("EXAMPLE__COMP_A_STRENGTH_1", "EXAMPLE__COMP_A_STRENGTH_2"));
|
||||
competitorStrengths.put("competitor_b", List.of("EXAMPLE__COMP_B_STRENGTH_1", "EXAMPLE__COMP_B_STRENGTH_2"));
|
||||
competitorStrengths.put("competitor_c", List.of("EXAMPLE__COMP_C_STRENGTH_1", "EXAMPLE__COMP_C_STRENGTH_2"));
|
||||
competitiveEnvironment.setCompetitorStrengths(competitorStrengths);
|
||||
competitiveEnvironment.setConclusion(
|
||||
"Ваш бизнес занимает 3-е место по видимости. Основные преимущества конкурентов — соцдоказательства и контент. Ценовая борьба не является оптимальной.");
|
||||
competitiveEnvironment.setConclusion("EXAMPLE__COMPETITIVE_ENVIRONMENT_CONCLUSION");
|
||||
sections.setCompetitiveEnvironment(competitiveEnvironment);
|
||||
|
||||
// demand_and_behavior
|
||||
MarketingAnalysisResponseV2.DemandAndBehavior demandAndBehavior = new MarketingAnalysisResponseV2.DemandAndBehavior();
|
||||
demandAndBehavior.setTitle("Спрос и поведение");
|
||||
demandAndBehavior.setTitle("EXAMPLE__DEMAND_AND_BEHAVIOR_TITLE");
|
||||
MarketingAnalysisResponseV2.DemandAndBehaviorMetrics dabMetrics = new MarketingAnalysisResponseV2.DemandAndBehaviorMetrics();
|
||||
dabMetrics.setSearchVolumeGrowth("+62%");
|
||||
dabMetrics.setInteractionsBeforePurchase("3-4");
|
||||
dabMetrics.setRepeatRefusalProbability("54%");
|
||||
dabMetrics.setSearchVolumeGrowth("EXAMPLE__SEARCH_VOLUME_GROWTH");
|
||||
dabMetrics.setInteractionsBeforePurchase("EXAMPLE__INTERACTIONS_BEFORE_PURCHASE");
|
||||
dabMetrics.setRepeatRefusalProbability("EXAMPLE__REPEAT_REFUSAL_PROBABILITY");
|
||||
demandAndBehavior.setMetrics(dabMetrics);
|
||||
Map<String, String> searchQueryTypes = new LinkedHashMap<>();
|
||||
searchQueryTypes.put("direct_interest_catalog", "52%");
|
||||
searchQueryTypes.put("question_based_articles", "28%");
|
||||
searchQueryTypes.put("competitors_reviews", "13%");
|
||||
searchQueryTypes.put("problem_solving_hot_promo", "7%");
|
||||
searchQueryTypes.put("direct_interest_catalog", "EXAMPLE__QUERY_TYPE_DIRECT");
|
||||
searchQueryTypes.put("question_based_articles", "EXAMPLE__QUERY_TYPE_QUESTION");
|
||||
searchQueryTypes.put("competitors_reviews", "EXAMPLE__QUERY_TYPE_COMPETITORS");
|
||||
searchQueryTypes.put("problem_solving_hot_promo", "EXAMPLE__QUERY_TYPE_PROMO");
|
||||
demandAndBehavior.setSearchQueryTypes(searchQueryTypes);
|
||||
Map<String, String> decisionFactors = new LinkedHashMap<>();
|
||||
decisionFactors.put("promo_discount", "43%");
|
||||
decisionFactors.put("review_recommendation", "36%");
|
||||
decisionFactors.put("warranty_quality", "33%");
|
||||
decisionFactors.put("convenience_service", "25%");
|
||||
decisionFactors.put("availability", "21%");
|
||||
decisionFactors.put("price", "19%");
|
||||
decisionFactors.put("promo_discount", "EXAMPLE__FACTOR_PROMO");
|
||||
decisionFactors.put("review_recommendation", "EXAMPLE__FACTOR_REVIEWS");
|
||||
decisionFactors.put("warranty_quality", "EXAMPLE__FACTOR_WARRANTY");
|
||||
decisionFactors.put("convenience_service", "EXAMPLE__FACTOR_CONVENIENCE");
|
||||
decisionFactors.put("availability", "EXAMPLE__FACTOR_AVAILABILITY");
|
||||
decisionFactors.put("price", "EXAMPLE__FACTOR_PRICE");
|
||||
demandAndBehavior.setDecisionFactors(decisionFactors);
|
||||
Map<String, String> reasonsForRefusal = new LinkedHashMap<>();
|
||||
reasonsForRefusal.put("high_price", "37%");
|
||||
reasonsForRefusal.put("no_reviews_social_proof", "34%");
|
||||
reasonsForRefusal.put("choice_difficulty_unclear_offer", "29%");
|
||||
reasonsForRefusal.put("high_price", "EXAMPLE__REFUSAL_HIGH_PRICE");
|
||||
reasonsForRefusal.put("no_reviews_social_proof", "EXAMPLE__REFUSAL_NO_REVIEWS");
|
||||
reasonsForRefusal.put("choice_difficulty_unclear_offer", "EXAMPLE__REFUSAL_UNCLEAR_OFFER");
|
||||
demandAndBehavior.setReasonsForRefusal(reasonsForRefusal);
|
||||
demandAndBehavior.setConclusion(
|
||||
"Основной трафик приходит из поиска. Для отклика ключевую роль играют акции и отзывы.");
|
||||
demandAndBehavior.setConclusion("EXAMPLE__DEMAND_AND_BEHAVIOR_CONCLUSION");
|
||||
sections.setDemandAndBehavior(demandAndBehavior);
|
||||
|
||||
// customer_journey
|
||||
MarketingAnalysisResponseV2.CustomerJourney customerJourney = new MarketingAnalysisResponseV2.CustomerJourney();
|
||||
customerJourney.setTitle("Путь клиента");
|
||||
customerJourney.setTitle("EXAMPLE__CUSTOMER_JOURNEY_TITLE");
|
||||
MarketingAnalysisResponseV2.FunnelMetrics funnelMetrics = new MarketingAnalysisResponseV2.FunnelMetrics();
|
||||
funnelMetrics.setAdTraffic("Реклама");
|
||||
funnelMetrics.setSiteVisitors("Сайт / Лендинг");
|
||||
funnelMetrics.setLeads(5600);
|
||||
funnelMetrics.setBookings(1200);
|
||||
funnelMetrics.setPayments(680);
|
||||
funnelMetrics.setAdTraffic("EXAMPLE__FUNNEL_AD_TRAFFIC");
|
||||
funnelMetrics.setSiteVisitors("EXAMPLE__FUNNEL_SITE_VISITORS");
|
||||
funnelMetrics.setLeads(-9999);
|
||||
funnelMetrics.setBookings(-9999);
|
||||
funnelMetrics.setPayments(-9999);
|
||||
customerJourney.setFunnelMetrics(funnelMetrics);
|
||||
MarketingAnalysisResponseV2.ConversionRates conversionRates = new MarketingAnalysisResponseV2.ConversionRates();
|
||||
conversionRates.setLeadToBooking("21%");
|
||||
conversionRates.setBookingToPayment("57%");
|
||||
conversionRates.setLeadToPaymentTotal("12%");
|
||||
conversionRates.setLeadToBooking("EXAMPLE__LEAD_TO_BOOKING");
|
||||
conversionRates.setBookingToPayment("EXAMPLE__BOOKING_TO_PAYMENT");
|
||||
conversionRates.setLeadToPaymentTotal("EXAMPLE__LEAD_TO_PAYMENT_TOTAL");
|
||||
customerJourney.setConversionRates(conversionRates);
|
||||
MarketingAnalysisResponseV2.FunnelBottlenecks funnelBottlenecks = new MarketingAnalysisResponseV2.FunnelBottlenecks();
|
||||
funnelBottlenecks.setLeadToBooking("Медленная скорость ответа");
|
||||
funnelBottlenecks.setBookingToPayment("Недостаточно касаний / напоминаний");
|
||||
funnelBottlenecks.setLeadToBooking("EXAMPLE__BOTTLENECK_LEAD_TO_BOOKING");
|
||||
funnelBottlenecks.setBookingToPayment("EXAMPLE__BOTTLENECK_BOOKING_TO_PAYMENT");
|
||||
customerJourney.setFunnelBottlenecks(funnelBottlenecks);
|
||||
customerJourney.setConclusion(
|
||||
"Основные потери происходят на этапе лид -> запись (конверсия 21%) из-за медленных ответов менеджеров.");
|
||||
customerJourney.setConclusion("EXAMPLE__CUSTOMER_JOURNEY_CONCLUSION");
|
||||
sections.setCustomerJourney(customerJourney);
|
||||
|
||||
// acquisition_channels
|
||||
MarketingAnalysisResponseV2.AcquisitionChannels acquisitionChannels = new MarketingAnalysisResponseV2.AcquisitionChannels();
|
||||
acquisitionChannels.setTitle("Каналы привлечения");
|
||||
acquisitionChannels.setTitle("EXAMPLE__ACQUISITION_CHANNELS_TITLE");
|
||||
MarketingAnalysisResponseV2.AcquisitionChannelsMetrics acMetrics = new MarketingAnalysisResponseV2.AcquisitionChannelsMetrics();
|
||||
acMetrics.setSearchTrafficShare("48%");
|
||||
acMetrics.setAverageLeadCost("37 P");
|
||||
acMetrics.setGrowthPotential("+21%");
|
||||
acMetrics.setSearchTrafficShare("EXAMPLE__SEARCH_TRAFFIC_SHARE");
|
||||
acMetrics.setAverageLeadCost("EXAMPLE__AVERAGE_LEAD_COST");
|
||||
acMetrics.setGrowthPotential("EXAMPLE__GROWTH_POTENTIAL");
|
||||
acquisitionChannels.setMetrics(acMetrics);
|
||||
Map<String, String> channelShares = new LinkedHashMap<>();
|
||||
channelShares.put("seo", "48%");
|
||||
channelShares.put("yandex_direct", "31%");
|
||||
channelShares.put("retargeting", "13%");
|
||||
channelShares.put("vkontakte", "6%");
|
||||
channelShares.put("seo", "EXAMPLE__SHARE_SEO");
|
||||
channelShares.put("yandex_direct", "EXAMPLE__SHARE_YANDEX_DIRECT");
|
||||
channelShares.put("retargeting", "EXAMPLE__SHARE_RETARGETING");
|
||||
channelShares.put("vkontakte", "EXAMPLE__SHARE_VKONTAKTE");
|
||||
acquisitionChannels.setChannelShares(channelShares);
|
||||
Map<String, MarketingAnalysisResponseV2.ChannelEfficiency> channelEfficiency = new LinkedHashMap<>();
|
||||
channelEfficiency.put("seo", new MarketingAnalysisResponseV2.ChannelEfficiency("25 P", "Эффективен"));
|
||||
channelEfficiency.put("yandex", new MarketingAnalysisResponseV2.ChannelEfficiency("45 P", "Эффективен"));
|
||||
channelEfficiency.put("seo",
|
||||
new MarketingAnalysisResponseV2.ChannelEfficiency("EXAMPLE__CPL_SEO", "EXAMPLE__EFF_SEO"));
|
||||
channelEfficiency.put("yandex",
|
||||
new MarketingAnalysisResponseV2.ChannelEfficiency("EXAMPLE__CPL_YANDEX", "EXAMPLE__EFF_YANDEX"));
|
||||
channelEfficiency.put("retargeting",
|
||||
new MarketingAnalysisResponseV2.ChannelEfficiency("40 P", "Удовлетворительно"));
|
||||
channelEfficiency.put("vkontakte", new MarketingAnalysisResponseV2.ChannelEfficiency("57 P", "Завышено"));
|
||||
channelEfficiency.put("youtube", new MarketingAnalysisResponseV2.ChannelEfficiency("63 P", "Завышено"));
|
||||
channelEfficiency.put("instagram", new MarketingAnalysisResponseV2.ChannelEfficiency("77 P", "Завышено"));
|
||||
new MarketingAnalysisResponseV2.ChannelEfficiency("EXAMPLE__CPL_RETARGETING",
|
||||
"EXAMPLE__EFF_RETARGETING"));
|
||||
channelEfficiency.put("vkontakte",
|
||||
new MarketingAnalysisResponseV2.ChannelEfficiency("EXAMPLE__CPL_VK", "EXAMPLE__EFF_VK"));
|
||||
channelEfficiency.put("youtube",
|
||||
new MarketingAnalysisResponseV2.ChannelEfficiency("EXAMPLE__CPL_YOUTUBE", "EXAMPLE__EFF_YOUTUBE"));
|
||||
channelEfficiency.put("instagram",
|
||||
new MarketingAnalysisResponseV2.ChannelEfficiency("EXAMPLE__CPL_INSTAGRAM", "EXAMPLE__EFF_INSTAGRAM"));
|
||||
acquisitionChannels.setChannelEfficiency(channelEfficiency);
|
||||
acquisitionChannels.setConclusion(
|
||||
"Основной источник лидов — SEO. VK, Youtube и Instagram требуют оптимизации из-за завышенной стоимости лида.");
|
||||
acquisitionChannels.setConclusion("EXAMPLE__ACQUISITION_CHANNELS_CONCLUSION");
|
||||
sections.setAcquisitionChannels(acquisitionChannels);
|
||||
|
||||
// marketing_economics
|
||||
MarketingAnalysisResponseV2.MarketingEconomics marketingEconomics = new MarketingAnalysisResponseV2.MarketingEconomics();
|
||||
marketingEconomics.setTitle("Экономика маркетинга");
|
||||
marketingEconomics.setTitle("EXAMPLE__MARKETING_ECONOMICS_TITLE");
|
||||
MarketingAnalysisResponseV2.MarketingEconomicsMetrics meMetrics = new MarketingAnalysisResponseV2.MarketingEconomicsMetrics();
|
||||
meMetrics.setCustomerAcquisitionCostCac("2900 P");
|
||||
meMetrics.setRepeatSalesConversion("32%");
|
||||
meMetrics.setRoi("3.5x");
|
||||
meMetrics.setCustomerAcquisitionCostCac("EXAMPLE__CAC");
|
||||
meMetrics.setRepeatSalesConversion("EXAMPLE__REPEAT_SALES_CONVERSION");
|
||||
meMetrics.setRoi("EXAMPLE__ROI");
|
||||
marketingEconomics.setMetrics(meMetrics);
|
||||
MarketingAnalysisResponseV2.FinancialPerformance financialPerformance = new MarketingAnalysisResponseV2.FinancialPerformance();
|
||||
financialPerformance
|
||||
.setMarketingExpenses(new MarketingAnalysisResponseV2.MonthYearValue("1.97 млн", "23.6 млн"));
|
||||
financialPerformance.setClients(new MarketingAnalysisResponseV2.MonthYearValue("680", "8160"));
|
||||
financialPerformance.setCac(new MarketingAnalysisResponseV2.MonthYearValue("2900 P", "2900 P"));
|
||||
.setMarketingExpenses(
|
||||
new MarketingAnalysisResponseV2.MonthYearValue("EXAMPLE__MARKETING_EXPENSES_MONTH",
|
||||
"EXAMPLE__MARKETING_EXPENSES_YEAR"));
|
||||
financialPerformance.setClients(new MarketingAnalysisResponseV2.MonthYearValue("EXAMPLE__CLIENTS_MONTH",
|
||||
"EXAMPLE__CLIENTS_YEAR"));
|
||||
financialPerformance
|
||||
.setRevenueFromClient(new MarketingAnalysisResponseV2.MonthYearValue("10.200 P", "23.040 P"));
|
||||
financialPerformance.setProfitFromClient(new MarketingAnalysisResponseV2.MonthYearValue("7.300 P", "16.720 P"));
|
||||
.setCac(new MarketingAnalysisResponseV2.MonthYearValue("EXAMPLE__CAC_MONTH", "EXAMPLE__CAC_YEAR"));
|
||||
financialPerformance
|
||||
.setRevenueFromClient(new MarketingAnalysisResponseV2.MonthYearValue("EXAMPLE__REV_PER_CLIENT_MONTH",
|
||||
"EXAMPLE__REV_PER_CLIENT_YEAR"));
|
||||
financialPerformance
|
||||
.setProfitFromClient(new MarketingAnalysisResponseV2.MonthYearValue("EXAMPLE__PROFIT_PER_CLIENT_MONTH",
|
||||
"EXAMPLE__PROFIT_PER_CLIENT_YEAR"));
|
||||
marketingEconomics.setFinancialPerformance(financialPerformance);
|
||||
marketingEconomics.setConclusion(
|
||||
"Экономика digital-маркетинга эффективна: возврат инвестиций 3.5х. Точки роста — повторные продажи и удержание.");
|
||||
marketingEconomics.setConclusion("EXAMPLE__MARKETING_ECONOMICS_CONCLUSION");
|
||||
sections.setMarketingEconomics(marketingEconomics);
|
||||
|
||||
// bottlenecks
|
||||
MarketingAnalysisResponseV2.Bottlenecks bottlenecks = new MarketingAnalysisResponseV2.Bottlenecks();
|
||||
bottlenecks.setTitle("Проблемы и узкие места");
|
||||
bottlenecks.setTitle("EXAMPLE__BOTTLENECKS_TITLE");
|
||||
Map<String, String> statistics = new LinkedHashMap<>();
|
||||
statistics.put("landing_page_issues", "51%");
|
||||
statistics.put("slow_manager_responses", "60%");
|
||||
statistics.put("repeat_interaction_refusal", "36%");
|
||||
statistics.put("landing_page_issues", "EXAMPLE__STAT_LANDING_PAGE_ISSUES");
|
||||
statistics.put("slow_manager_responses", "EXAMPLE__STAT_SLOW_MANAGER_RESPONSES");
|
||||
statistics.put("repeat_interaction_refusal", "EXAMPLE__STAT_REPEAT_INTERACTION_REFUSAL");
|
||||
bottlenecks.setStatistics(statistics);
|
||||
MarketingAnalysisResponseV2.BottlenecksDetails details = new MarketingAnalysisResponseV2.BottlenecksDetails();
|
||||
details.setLanding(List.of("Низкая конверсия (2%)", "Проблемы с формой записи", "Уход посетителей"));
|
||||
details.setLanding(List.of("EXAMPLE__LANDING_ISSUE_1", "EXAMPLE__LANDING_ISSUE_2", "EXAMPLE__LANDING_ISSUE_3"));
|
||||
details.setLeadManagement(
|
||||
List.of("Медленные ответы (30-40+ мин)", "Недостаток напоминаний", "Пропущенные лиды"));
|
||||
details.setRetention(List.of("Недостаток повторных предложений", "Нет прогрева", "Слабая работа с CRM"));
|
||||
List.of("EXAMPLE__LEAD_MGMT_ISSUE_1", "EXAMPLE__LEAD_MGMT_ISSUE_2", "EXAMPLE__LEAD_MGMT_ISSUE_3"));
|
||||
details.setRetention(
|
||||
List.of("EXAMPLE__RETENTION_ISSUE_1", "EXAMPLE__RETENTION_ISSUE_2", "EXAMPLE__RETENTION_ISSUE_3"));
|
||||
bottlenecks.setDetails(details);
|
||||
bottlenecks.setConclusion(
|
||||
"Теряются десятки процентов лидов из-за медленных ответов менеджеров и слабой ретаргетинговой работы.");
|
||||
bottlenecks.setConclusion("EXAMPLE__BOTTLENECKS_CONCLUSION");
|
||||
sections.setBottlenecks(bottlenecks);
|
||||
|
||||
// recommendations
|
||||
MarketingAnalysisResponseV2.Recommendations recommendations = new MarketingAnalysisResponseV2.Recommendations();
|
||||
recommendations.setTitle("Рекомендации (итоги)");
|
||||
recommendations.setTitle("EXAMPLE__RECOMMENDATIONS_TITLE");
|
||||
recommendations.setCorePillars(List.of(
|
||||
new MarketingAnalysisResponseV2.CorePillar("Фокус на эффективных каналах",
|
||||
"Перераспределение бюджета на каналы с устойчивым спросом (Яндекс/SEO)"),
|
||||
new MarketingAnalysisResponseV2.CorePillar("Увеличение повторных касаний",
|
||||
"Усиление удерживающих кампаний и серий касаний с клиентами"),
|
||||
new MarketingAnalysisResponseV2.CorePillar("Приоритет высокоценных аудиторий",
|
||||
"Смещение акцента на платёжеспособные сегменты и B2B"),
|
||||
new MarketingAnalysisResponseV2.CorePillar("Рост эффективности трафика",
|
||||
"Снижение зависимости от дорогих источников и оптимизация каналов")));
|
||||
recommendations.setConclusion(
|
||||
"Рекомендации фокусируют усилия на эффективности интернет-продвижения и служат базой для следующих шагов.");
|
||||
new MarketingAnalysisResponseV2.CorePillar("EXAMPLE__PILLAR_1_TITLE", "EXAMPLE__PILLAR_1_DESC"),
|
||||
new MarketingAnalysisResponseV2.CorePillar("EXAMPLE__PILLAR_2_TITLE", "EXAMPLE__PILLAR_2_DESC"),
|
||||
new MarketingAnalysisResponseV2.CorePillar("EXAMPLE__PILLAR_3_TITLE", "EXAMPLE__PILLAR_3_DESC"),
|
||||
new MarketingAnalysisResponseV2.CorePillar("EXAMPLE__PILLAR_4_TITLE", "EXAMPLE__PILLAR_4_DESC")));
|
||||
recommendations.setConclusion("EXAMPLE__RECOMMENDATIONS_CONCLUSION");
|
||||
sections.setRecommendations(recommendations);
|
||||
|
||||
response.setSections(sections);
|
||||
|
||||
Reference in New Issue
Block a user