Реалізація AI-персоналізації контенту на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація AI-персоналізації контенту на сайті
Складна
~2-4 тижні
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація AI-персоналізації контенту на сайті

Персоналізація — це показувати різним користувачам різний контент на одній сторінці: інший порядок блоків, іншу заголовок, інший CTA, інші товари. AI тут управляє вибором варіантів на основі профілю та контексту користувача.

Рівні персоналізації

Поверхневий — змінні в тексті (ім'я користувача, місто), динамічні заголовки. Без ML.

Сегментний — контент для сегментів (новичок/досвідчений, B2B/B2C, регіон). Правила на основі атрибутів.

Поведінковий — контент на основі історії дій: що переглядав, купував, читав.

Предиктивний — AI передбачає наступну дію та оптимізує контент під конверсію.

Профіль користувача

// Накопиченням профіля в real-time
class UserProfileManager {
  constructor(userId) {
    this.userId = userId;
    this.profileKey = `profile:${userId}`;
  }

  async trackEvent(event) {
    const updates = {};

    switch (event.type) {
      case 'page_view':
        updates[`categories.${event.category}`] = { increment: 1 };
        updates['total_sessions'] = { increment: 1 };
        break;
      case 'purchase':
        updates['purchases_count'] = { increment: 1 };
        updates['total_spent'] = { increment: event.amount };
        updates['last_purchase'] = event.timestamp;
        break;
      case 'content_read':
        updates['read_count'] = { increment: 1 };
        updates[`topics.${event.topic}`] = { increment: event.readTime };
        break;
    }

    await redis.hIncrBy(this.profileKey, updates);
    await redis.expire(this.profileKey, 86400 * 30); // 30 днів
  }

  async getProfile() {
    const raw = await redis.hGetAll(this.profileKey);
    return {
      topCategories: getTopN(raw.categories, 5),
      topTopics: getTopN(raw.topics, 5),
      purchasesCount: parseInt(raw.purchases_count || 0),
      totalSpent: parseFloat(raw.total_spent || 0),
      segment: this.classifySegment(raw),
    };
  }

  classifySegment(profile) {
    if (profile.purchases_count > 10) return 'loyal';
    if (profile.purchases_count > 0) return 'buyer';
    if (profile.total_sessions > 5) return 'engaged';
    return 'new';
  }
}

Персоналізована головна сторінка

// API ендпоінт для персоналізованої головної
async function getHomepageContent(userId, context) {
  const profile = await getUserProfile(userId);
  const geo = context.country || 'UA';
  const device = context.device || 'desktop';

  // Паралельно отримуємо всі блоки
  const [hero, featured, recommendations, cta] = await Promise.all([
    getPersonalizedHero(profile, geo),
    getFeaturedContent(profile.topCategories),
    getPersonalizedProducts(userId, profile, 8),
    getPersonalizedCTA(profile),
  ]);

  return { hero, featured, recommendations, cta };
}

async function getPersonalizedHero(profile, geo) {
  const variants = await getHeroVariants(); // A/B варіанти з CMS

  // Правила вибору варіанту
  if (profile.segment === 'loyal') {
    return variants.find(v => v.segment === 'loyal') || variants[0];
  }
  if (geo === 'UA') {
    return variants.find(v => v.geo === 'UA') || variants[0];
  }
  if (profile.topCategories.includes('sale')) {
    return variants.find(v => v.theme === 'deals') || variants[0];
  }

  return variants[0]; // default
}

LLM-генерація персоналізованого тексту

Для висок оцінених користувачів — динамічні заголовки та описи:

async function generatePersonalizedHeadline(product, userProfile) {
  const cacheKey = `headline:${product.id}:${userProfile.segment}`;
  const cached = await redis.get(cacheKey);
  if (cached) return cached;

  const prompt = `
Згенеруй заголовок карточки товару (до 10 слів) для користувача.
Товар: ${product.name}, категорія: ${product.category}
Профіль: сегмент=${userProfile.segment}, інтереси=${userProfile.topTopics.join(',')}
Тон: професійний, без клішеїв.
Поверни тільки текст заголовка.
`;

  const response = await openai.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: prompt }],
    max_tokens: 30,
    temperature: 0.7,
  });

  const headline = response.choices[0].message.content.trim();
  await redis.setex(cacheKey, 3600 * 6, headline); // кеш 6 годин

  return headline;
}

Динамічні CTA

const CTA_VARIANTS = {
  new: {
    text: 'Почати безплатно',
    subtext: 'Без кредитної карти',
    color: 'blue',
  },
  engaged: {
    text: 'Спробувати Pro',
    subtext: '14 днів безплатно',
    color: 'green',
  },
  buyer: {
    text: 'Оновити тариф',
    subtext: 'Розблокуй всі функції',
    color: 'purple',
  },
  loyal: {
    text: 'Реферальна програма',
    subtext: 'Заробляй за друзів',
    color: 'orange',
  },
};

function PersonalizedCTA({ userId }) {
  const { profile } = useUserProfile(userId);
  const variant = CTA_VARIANTS[profile.segment] || CTA_VARIANTS.new;

  return (
    <button
      className={`cta-button cta-${variant.color}`}
      onClick={() => {
        trackCTAClick(userId, profile.segment);
        navigate(getCtaDestination(profile.segment));
      }}
    >
      {variant.text}
      <span>{variant.subtext}</span>
    </button>
  );
}

Контекстна персоналізація (без авторизації)

Для анонімних користувачів — сигнали з поточної сесії:

function getContextualSignals(request) {
  return {
    referrer: request.headers.referer,         // звідки прийшов
    utm_source: request.query.utm_source,       // рекламний канал
    utm_campaign: request.query.utm_campaign,
    geo: request.headers['cf-ipcountry'],       // Cloudflare geo
    device: detectDevice(request.headers['user-agent']),
    timeOfDay: getTimeOfDay(request.headers['x-forwarded-for']),
    entryPage: request.url,
  };
}

function getPersonalizationForAnonymous(signals) {
  // Прийшов з реклами "знижки" → показати sale-банер
  if (signals.utm_campaign?.includes('sale')) {
    return { hero: 'sale', cta: 'discount' };
  }
  // Мобільний + вечір → показати app download
  if (signals.device === 'mobile' && signals.timeOfDay === 'evening') {
    return { hero: 'mobile-app', cta: 'download' };
  }
  // B2B сигнал з LinkedIn
  if (signals.referrer?.includes('linkedin')) {
    return { hero: 'b2b', cta: 'demo' };
  }

  return { hero: 'default', cta: 'default' };
}

Edge Персоналізація (Cloudflare Workers / Vercel Edge)

Для максимальної швидкості — персоналізація прямо на Edge, до Origin:

// Cloudflare Worker
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const userId = getCookie(request, 'user_id');
    const segment = userId
      ? await env.KV.get(`segment:${userId}`)
      : 'anonymous';

    // Модифікуємо запит до Origin з сегментом
    const newRequest = new Request(request.url, {
      ...request,
      headers: {
        ...Object.fromEntries(request.headers),
        'X-User-Segment': segment || 'new',
        'X-User-Geo': request.cf.country,
      },
    });

    return fetch(newRequest);
  }
};

Вимірювання ефекту

-- Конверсія за сегментами та варіантами персоналізації
SELECT
  p.variant,
  p.segment,
  COUNT(DISTINCT p.user_id) AS shown,
  COUNT(DISTINCT c.user_id) AS converted,
  ROUND(COUNT(DISTINCT c.user_id)::numeric / COUNT(DISTINCT p.user_id) * 100, 2) AS cvr
FROM personalization_events p
LEFT JOIN conversion_events c
  ON c.user_id = p.user_id
  AND c.created_at BETWEEN p.created_at AND p.created_at + INTERVAL '7 days'
WHERE p.created_at >= NOW() - INTERVAL '30 days'
GROUP BY p.variant, p.segment
ORDER BY cvr DESC;

Терміни

  • Сегментна персоналізація (правила) — 3–4 дні
  • Поведінковий профіль + персоналізація рекомендацій — плюс 3–4 дні
  • LLM-генерація динамічних заголовків — плюс 2 дні
  • Edge персоналізація на Cloudflare Workers — плюс 2 дні
  • Повна система з аналітикою, A/B, 5+ варіантами — 3–4 тижні