בעת פיתוח משפך חידון על 1C-Bitrix, אנו נתקלים לעתים קרובות במצב הבא: הלקוח רוצה לשאול שאלות לא-לינאריות כדי לקבץ את הקהל אוטומטית. חידון סטנדרטי רציף אינו מספק את הגמישות הנדרשת — לידים מגיעים ללא מוטיבציה, וההמרה יורדת. משפך מסועף פותר זאת: התשובה לשאלה אחת קובעת את הבאה, ובסוף המשתמש מקבל הצעה מותאמת אישית. לפי הנתונים שלנו, ההמרה לליד מוסמך עולה ב-40%, ועלות הליד יורדת ב-25%.
משפך מסועף עולה על משפך לינארי: ההמרה גבוהה פי 1.5 בזכות פילוח מדויק והתאמה אישית של המסלול. במקביל, אוטומציית הפקת הלידים דרך Bitrix24 נותנת למנהל מיד הקשר למכירה.
אילו קשיים טכניים מתעוררים בעת פיתוח משפך חידון עם הסתעפות?
יישום הסתעפות דורש ארכיטקטורה ברורה. אם גרף המעברים אינו מתוכנן היטב, מתרחשים באגים: המשתמש נתקע בלולאה, מגיע לשאלה שגויה, או מאבד נתונים. הבעיה השנייה היא סקלביליות. בעת הוספת שאלות ותוצאות חדשות, הלוגיקה חייבת להישאר גמישה מבלי לשכתב את הליבה. השלישית היא אינטגרציה עם Bitrix24: יש להעביר את הקשר המשפך כך שהמנהל יוכל לראות מיד את מסלול הלקוח. מבנה שגוי של HL-blocks מוביל לכפילויות נתונים ולשאילתות מורכבות.
כיצד אנו מיישמים לוגיקת הסתעפות
לכל שאלה יש מעברים: כאשר בוחרים אפשרות X, השאלה הבאה היא Y. אם לא הוגדר מעבר, אנו עוברים לשאלה הבאה כברירת מחדל או לשלב הסופי. לאחסון, אנו משתמשים ב-HL-block b_hl_quiz_funnel_questions. תיעוד 1C-Bitrix קובע: "HL-blocks הם דרך לאחסון נתונים שרירותיים עם תמיכת ORM."
class FunnelQuestionTable extends \Bitrix\Main\ORM\Data\DataManager { public static function getTableName(): string { return 'b_hl_quiz_funnel_questions'; } public static function getMap(): array { return [ new IntegerField('ID', ['primary' => true, 'autocomplete' => true]), new IntegerField('FUNNEL_ID'), new StringField('SLUG'), new IntegerField('SORT'), new StringField('TEXT'), new StringField('TYPE'), new TextField('OPTIONS_JSON'), new StringField('DEFAULT_NEXT_SLUG'), new BooleanField('IS_FINAL'), ]; } } מבנה של class FunnelQuestionTable extends \Bitrix\Main\ORM\Data\DataManager { public static function getTableName(): string { return 'b_hl_quiz_funnel_questions'; } public static function getMap(): array { return [ new IntegerField('ID', ['primary' => true, 'autocomplete' => true]), new IntegerField('FUNNEL_ID'), new StringField('SLUG'), new IntegerField('SORT'), new StringField('TEXT'), new StringField('TYPE'), new TextField('OPTIONS_JSON'), new StringField('DEFAULT_NEXT_SLUG'), new BooleanField('IS_FINAL'), ]; } } לשאלה מסועפת:
[ {"id": "opt_a", "text": "Физическое лицо", "next_slug": "q_budget_personal"}, {"id": "opt_b", "text": "Компания (до 50 чел.)", "next_slug": "q_budget_smb"}, {"id": "opt_c", "text": "Крупная компания", "next_slug": "q_budget_enterprise"} ] בצד השרת, אנו בונים את הגרף ומספקים מתודת ניווט:
class FunnelGraph { private array $questions = []; private string $startSlug; public function __construct(int $funnelId) { $rows = FunnelQuestionTable::getList([ 'filter' => ['FUNNEL_ID' => $funnelId], 'order' => ['SORT' => 'ASC'], ])->fetchAll(); foreach ($rows as $row) { $row['OPTIONS'] = json_decode($row['OPTIONS_JSON'], true) ?? []; $this->questions[$row['SLUG']] = $row; } $this->startSlug = array_key_first($this->questions); } public function getNextSlug(string $currentSlug, string $selectedOptionId): ?string { $question = $this->questions[$currentSlug] ?? null; if (!$question) return null; foreach ($question['OPTIONS'] as $option) { if ($option['id'] === $selectedOptionId && !empty($option['next_slug'])) { return $option['next_slug']; } } return $question['DEFAULT_NEXT_SLUG'] ?: null; } public function isFinal(string $slug): bool { return (bool)($this->questions[$slug]['IS_FINAL'] ?? false); } public function toClientJson(): array { $result = []; foreach ($this->questions as $slug => $q) { $result[$slug] = [ 'text' => $q['TEXT'], 'type' => $q['TYPE'], 'options' => $q['OPTIONS'], 'is_final' => $q['IS_FINAL'], ]; } return ['start' => $this->startSlug, 'questions' => $result]; } } לוגיקת ניווט בצד הלקוח
class QuizFunnel { constructor(graphData) { this.questions = graphData.questions; this.currentSlug = graphData.start; this.history = []; this.answers = {}; } selectOption(optionId) { const question = this.questions[this.currentSlug]; this.answers[this.currentSlug] = [optionId]; let nextSlug = null; for (const opt of question.options) { if (opt.id === optionId && opt.next_slug) { nextSlug = opt.next_slug; break; } } if (!nextSlug && question.is_final) { this.showContactForm(); return; } if (nextSlug && this.questions[nextSlug]) { this.history.push(this.currentSlug); this.currentSlug = nextSlug; this.renderQuestion(nextSlug); } else { this.showContactForm(); } } goBack() { if (this.history.length === 0) return; this.currentSlug = this.history.pop(); delete this.answers[this.currentSlug]; this.renderQuestion(this.currentSlug); } renderQuestion(slug) { const q = this.questions[slug]; const el = document.getElementById('quiz-question'); el.querySelector('.quiz-text').textContent = q.text; const optionsEl = el.querySelector('.quiz-options'); optionsEl.innerHTML = q.options.map(opt => `<button class="quiz-option" data-option-id="${opt.id}">${opt.text}</button>` ).join(''); optionsEl.querySelectorAll('.quiz-option').forEach(btn => { btn.addEventListener('click', () => this.selectOption(btn.dataset.optionId)); }); } showContactForm() { document.getElementById('quiz-questions').style.display = 'none'; document.getElementById('quiz-contact-form').style.display = 'block'; } } const funnel = new QuizFunnel(window.FUNNEL_DATA); funnel.renderQuestion(funnel.currentSlug); כיצד מתבצעת התאמת תוצאות?
בסוף המשפך, המשתמש מקבל תוצאה מותאמת אישית התלויה בתשובותיו. לשם כך, אנו משתמשים ב-HL-block OPTIONS_JSON עם כללי התאמה. שירות ResultMatcher עובר על תנאים בפורמט JSON: עבור כל שאלה, מצוינות אפשרויות צפויות. אם כל התנאים תואמים, התוצאה נחשבת נכונה. זה מבטיח פילוח מדויק ומבטל בחירה ידנית.
כיצד מועברים לידים ל-Bitrix24?
לאחר השלמת החידון, אנו יוצרים ליד ב-Bitrix24 דרך REST API ומצרפים את מסלול המשתמש המלא. זה נותן למנהל הקשר למכירה.
$matchedResult = (new ResultMatcher())->match($funnelId, $answers); $resultTitle = $matchedResult['TITLE'] ?? 'Неопределён'; $lead = new \CCrmLead(false); $lead->Add([ 'TITLE' => 'Воронка: ' . $funnelName . ' → ' . $resultTitle . ' — ' . $name, 'NAME' => $name, 'PHONE' => [['VALUE' => $phone, 'VALUE_TYPE' => 'WORK']], 'SOURCE_ID' => 'WEB', 'COMMENTS' => "Результат: {$resultTitle}\nПуть: " . implode(' → ', array_keys($answers)), 'UF_CRM_QUIZ_PATH' => json_encode($answers, JSON_UNESCAPED_UNICODE), ]); השוואת סוגי משפכים
| סוג משפך | גמישות | המרה | מורכבות |
|---|---|---|---|
| לינארי | נמוכה | סטנדרטית | נמוכה |
| עם הסתעפות | גבוהה | +30-50% | בינונית |
| עם בונה | מקסימלית | +50-80% | גבוהה |
תהליך העבודה
- אנליטיקה — חקר תהליכים עסקיים, פלחי קהל, קריטריוני הסמכה.
- עיצוב — פיתוח גרף שאלות ומעברים, הגדרת תוצאות.
- יישום — כתיבת HL-blocks, שירותי backend, לוגיקת לקוח.
- אינטגרציה — חיבור Bitrix24, הגדרת מתודות REST.
- בדיקות — בדיקת כל התרחישים, תיקון באגים.
- פריסה — פריסה לסביבת ייצור, הדרכת צוות.
מה כלול בעבודה
- עיצוב מבנה HL-block וגרף מעברים
- פיתוח backend (FunnelGraph, ResultMatcher)
- לוגיקת צד לקוח ב-JavaScript (ES6+)
- אינטגרציה עם Bitrix24 דרך REST API
- תיעוד והערות קוד
- גישה למאגר עם היסטוריית commits
- הדרכה לעובד האחראי על ניהול המשפך
- תמיכה חינמית למשך 14 יום לאחר המסירה
טעויות יישום אופייניות
- לא מתחשבים ביכולת החזרה (כפתור "חזרה") — יש לשמר היסטוריה.
- שוכחים שלבים סופיים — התוצאה חייבת להיות מוגדרת בקפדנות.
- אחסון JSON גדול ב-OPTIONS — בסדר עד 100 אפשרויות, אחרת יש לעבור לטבלאות משנה.
- לא בודקים כפילויות slugs — הם חייבים להיות ייחודיים בתוך המשפך.
- התעלמות ממטמון גרף — טעינה מ-DB בכל בקשה היא מיותרת. מומלץ לשמור במטמון בזיכרון עם המטמון המתויג של Bitrix.
לוחות זמנים
| אפשרות | היקף | לוח זמנים |
|---|---|---|
| משפך לינארי | ללא הסתעפות, תוצאה אחת | 4–6 ימים |
| משפך עם הסתעפות | גרף מעברים, מספר תוצאות | 8–12 ימים |
| עם בונה | ניהול משפך דרך ממשק משתמש | 15–22 ימים |
המחיר מחושב באופן אישי לפי מורכבות ודרישות. אנו מעריכים את הפרויקט תוך יום עסקים אחד ומציעים אחריות ל-12 חודשים על הקוד. עם ניסיון רב בפיתוח Bitrix, מסרנו מעל 30 פרויקטים, כולל אינטגרציות עם 1C, מערכות תשלום ושירותי משלוחים.
תמיכה חינמית למשך 14 יום לאחר מסירת הפרויקט. צרו קשר לייעוץ בנושא המשימה שלכם. קבלו ייעוץ — נבדוק את הפרויקט בחינם ונציע פתרון שמחזיר את ההשקעה במהירות.







