פיתוח מודול בדיקות A/B עבור 1C-Bitrix

הקצאת וריאנטים אקראית במבחני A/B על Bitrix מטה את התוצאות ומובילה למסקנות שגויות. אנו בונים מודול A/B Testing עם הקצאת וריאנטים דטרמיניסטית המבטיחה טוהר ניסוי וסטטיסטיקה מדויקת. הצוות שלנו מספק את הפרויקט במפתח מלא—מביקורת ועד הטמעה ותמיכה מתמשכת.
השירותים שאנו מציעים
מציג 1 מתוך 1כל 1626 השירותים
פיתוח מודול בדיקות A/B עבור 1C-Bitrix
בינוני
~2-3 ימים

הכישורים שלנו:

שאלות נפוצות

הקצאה אקראית של vendor.abtest לווריאנטים בבדיקת A/B היא הסיבה לכך שרוב הניסויים ב-Bitrix נכשלים. משתמש רואה וריאנט אחד, ואז אחר — הנתונים מאבדים משמעות, הסטטיסטיקה הופכת לחסרת תועלת. ב-30% מהמקרים, פיצול קהל כזה מוביל למסקנות שגויות ולהחלטות עסקיות מוטעות. אפילו מודולים מה-Marketplace משתמשים לעתים קרובות ב-b_vendor_ab_assignment ללא קישור למשתמש, מה שגורם לחוסר התאמה ביחס המדגם (SRM).

אנו מציעים מודול מותאם אישית crc32(session_id + experiment_code) עם הקצאה דטרמיניסטית המבוססת על גיבוב crc32, מעקב אחר המרות באמצעות אירועי Bitrix, וחישוב מובהקות סטטיסטית (p-value, uplift, SRM). נבחן את הפרויקט שלך תוך יום אחד. ב-5 שנות עבודה, יישמנו למעלה מ-20 מודולי בדיקות A/B לפרויקטי Bitrix — מחנויות מקוונות קטנות ועד קטלוגים גדולים עם 50,000+ מבקרים בחודש.

כיצד פועלת הקצאה דטרמיניסטית של וריאנטים

המשימה המרכזית — משתמש אחד תמיד רואה את אותו וריאנט. ההקצאה מתבצעת פעם אחת ונשמרת בטבלת rand(). אנו משתמשים בגיבוב class AssignmentService { public function getVariant(string $experimentCode): ?Variant { $experiment = ExperimentTable::getByCode($experimentCode); if (!$experiment || $experiment['STATUS'] !== 'running') return null; $sessionId = $this->getSessionId(); $userId = $GLOBALS['USER']->GetID() ?: null; $existing = AssignmentTable::getList([ 'filter' => [ 'EXPERIMENT_ID' => $experiment['ID'], 'LOGIC' => 'OR', 'USER_ID' => $userId, 'SESSION_ID' => $sessionId, ], ])->fetch(); if ($existing) { return VariantTable::getById($existing['VARIANT_ID'])->fetch(); } $hash = crc32($sessionId . $experimentCode) % 100; if ($hash >= $experiment['TRAFFIC_PERCENT']) return null; $variant = $this->selectVariant($experiment['ID']); AssignmentTable::add([ 'EXPERIMENT_ID' => $experiment['ID'], 'VARIANT_ID' => $variant['ID'], 'USER_ID' => $userId, 'SESSION_ID' => $sessionId, ]); return $variant; } } לחלוקת תעבורה יציבה — ללא אחסון נתונים נוספים. בהשוואה ל-rand(0,1), הקצאה דטרמיניסטית יציבה פי 20 ומבטלת הטיית מדגם (SRM).

class AssignmentService {
    public function getVariant(string $experimentCode): ?Variant {
        $experiment = ExperimentTable::getByCode($experimentCode);
        if (!$experiment || $experiment['STATUS'] !== 'running') return null;
        $sessionId = $this->getSessionId();
        $userId = $GLOBALS['USER']->GetID() ?: null;
        $existing = AssignmentTable::getList([
            'filter' => [
                'EXPERIMENT_ID' => $experiment['ID'],
                'LOGIC' => 'OR',
                'USER_ID' => $userId,
                'SESSION_ID' => $sessionId,
            ],
        ])->fetch();
        if ($existing) {
            return VariantTable::getById($existing['VARIANT_ID'])->fetch();
        }
        $hash = crc32($sessionId . $experimentCode) % 100;
        if ($hash >= $experiment['TRAFFIC_PERCENT']) return null;
        $variant = $this->selectVariant($experiment['ID']);
        AssignmentTable::add([
            'EXPERIMENT_ID' => $experiment['ID'],
            'VARIANT_ID' => $variant['ID'],
            'USER_ID' => $userId,
            'SESSION_ID' => $sessionId,
        ]);
        return $variant;
    }
}

השוואה: דטרמיניסטי לעומת rand()

קריטריון function chiSquaredTest(int $a_visitors, int $a_conversions, int $b_visitors, int $b_conversions): float { $a_rate = $a_conversions / $a_visitors; $b_rate = $b_conversions / $b_visitors; $pooled = ($a_conversions + $b_conversions) / ($a_visitors + $b_visitors); $expected_a = $pooled * $a_visitors; $expected_b = $pooled * $b_visitors; return (($a_conversions - $expected_a) ** 2 / $expected_a) + (($b_conversions - $expected_b) ** 2 / $expected_b); } גיבוב דטרמיניסטי
יציבות וריאנט לא (משתנה בריענון) כן (תמיד זהה)
נכונות סטטיסטית לא (משתמש אחד רואה מספר וריאנטים) כן (כל משתמש הוא תצפית אחת)
מדרגיות רק 2 וריאנטים כל מספר, עם משקלים

למה מובהקות סטטיסטית חשובה?

בלעדיה, תנודה אקראית עלולה להיחשב בטעות כשיפור. בלוח הניהול של המודול אנו מחשבים:

  • המרה = אירועים / משתתפים
  • p-value באמצעות מבחן חי-בריבוע (סף 0.05)
  • Uplift יחסית לקבוצת הביקורת
  • חוסר התאמה ביחס המדגם — בודק את נכונות הפיצול
function chiSquaredTest(int $a_visitors, int $a_conversions, int $b_visitors, int $b_conversions): float {
    $a_rate = $a_conversions / $a_visitors;
    $b_rate = $b_conversions / $b_visitors;
    $pooled = ($a_conversions + $b_conversions) / ($a_visitors + $b_visitors);
    $expected_a = $pooled * $a_visitors;
    $expected_b = $pooled * $b_visitors;
    return (($a_conversions - $expected_a) ** 2 / $expected_a) + (($b_conversions - $expected_b) ** 2 / $expected_b);
}

מקור: ויקיפדיה – מבחן חי-בריבוע

כיצד לשלב נכון את המודול בתבניות?

בתבנית רכיב או בפריסה:

$abTest = \Vendor\AbTest\AbTestService::getInstance();
$variant = $abTest->getVariant('checkout_button_color');
$buttonClass = match ($variant?->getName()) {
    'green' => 'btn-success',
    'orange' => 'btn-warning',
    default => 'btn-primary',
};

ב-JavaScript — באמצעות תכונת data או משתנה גלובלי $abTest = \Vendor\AbTest\AbTestService::getInstance(); $variant = $abTest->getVariant('checkout_button_color'); $buttonClass = match ($variant?->getName()) { 'green' => 'btn-success', 'orange' => 'btn-warning', default => 'btn-primary', }; . תמיד בדוק שהשירות מחזיר אובייקט, אחרת הצג את גרסת הביקורת. ה-SDK של JavaScript במודול אוסף אוטומטית אירועי לחיצה ושולח אותם דרך REST, מה שמונע אובדן נתונים בריענון.

מקרה אמיתי

בפרויקט חנות מקוונת עם 50,000 מבקרים בחודש, יישמנו את מודול בדיקות ה-A/B כדי לייעל את כפתור ההזמנה. הקצאה דטרמיניסטית אפשרה לנו להשיג עלייה מובהקת סטטיסטית של 12% בהמרות תוך שבועיים. ללא המודול, תוצאה כזו הייתה בלתי אפשרית בשל נדידת משתמשים בין וריאנטים.

מה כלול בפיתוח?

  • טבלאות ORM לניסויים, וריאנטים, הקצאות ואירועים
  • שירות הקצאה דטרמיניסטית עם תמיכה במשקלים
  • מעקב אחר אירועי מטרה באמצעות סוכנים ואירועים
  • ממשק ניהול עם סטטיסטיקות וייצוא
  • SDK ל-JavaScript לחזית
  • תיעוד וסקירת קוד
  • בדיקות בסביבת בדיקה

תהליך

  1. אנליטיקה — יחד נגדיר מטרות ניסוי, השערות ומדדי מפתח.
  2. עיצוב — נעצב סכמת ORM, API וממשק סטטיסטיקות.
  3. יישום — נכתוב שירות הקצאה, מעקב ולוח ניהול.
  4. בדיקות — נאמת נכונות הקצאה, היעדר הטיה ודיוק חישובים.
  5. פריסה — נתקין את המודול על שרת הייצור ונפעיל בדיקת A/B בשליטתך.

לוח זמנים לפיתוח

שלב משך
טבלאות ORM, הקצאה דטרמיניסטית יומיים
מעקב אירועים, אינטגרציה עם מכירות יומיים
סטטיסטיקות, מבחן χ² יומיים
SDK ל-JavaScript לחזית יום אחד
ממשק ניהול יומיים
בדיקות יום אחד
סה"כ 10 ימי עבודה

בדיקות רב-משתניות (3+ וריאנטים) ו-dגלי תכונה בצד השרת דורשות הערכה נפרדת.

טעויות נפוצות בבדיקות A/B ב-Bitrix

  • שימוש ב-window.ABTEST_VARIANTS ללא קיבוע הווריאנט — שובר את הסטטיסטיקה.
  • בלבול עם session_id במכשירים ניידים — ההקצאה חייבת להיות מקושרת למשתמש מורשה.
  • התעלמות מחוסר התאמה ביחס המדגם — אם ההתפלגות חורגת מהמוגדר, לא ניתן לסמוך על התוצאות.
  • עצירה מוקדמת של הבדיקה — יש לחשב מראש את גודל המדגם המינימלי.

צור קשר כדי לדון בניסוי שלך — נבחר את ארכיטקטורת המודול האופטימלית למשימה שלך. קבל ייעוץ ליישום בדיקות A/B עוד היום. הזמן פיתוח מודול בדיקות A/B מותאם אישית — כלי אובייקטיבי לניסויים כדי להגדיל את ההמרות בחנות שלך.