You are here

function abjs_generate_js in A/B Test JS 8

Same name and namespace in other branches
  1. 7 abjs.module \abjs_generate_js()
  2. 2.0.x abjs.module \abjs_generate_js()

Builds the javascript for all active and valid A/B tests.

Parameters

array $tests: An array of database result objects from a query on abjs_test to get all active and valid tests.

Return value

string A string of javascript for running all tests.

  • abTests will be an array of test objects. Each abTest object has these properties:

-- name: The name of the test, equal to the test id. This will be used as the name of the cookie that gets assigned this test, prefixed by abjs_cookie_prefix from the variables table. -- conditions: An array of condition strings with the names of the condition functions to run. The condition strings are prefixed by con_, followed by the primary id from the test table and primary id from the condition table, which is used instead of the condition table so that we don't get duplicate function definitions with the same name. -- experiences: An array of experience objects. Each experience object has these properties: --- name: The name of the experience, equal to the experience id. This will be used as the value of the cookie that gets assigned for this test. --- fraction: The probability of this experience getting chosen. If all experience probabilities for a single test add to less than 1, the remainder is the probability that a user will not be in the test on each page hit. If probabilities add to greater than 1, experiences may have less than their stated probability of occurring. --- script: The name of the function for this experience. The name is prefixed by exp_, followed by the primary id from the test table and primary id from the experience table, which is used instead of the experience table so that we don't get duplicate function definitions with the same name.

  • abConditions will be an array of condition functions that apply to the active tests, named the same as abTest.conditions above, and using the condition script from the condition table.
  • abExperiences will be an array of experience functions that apply to the active tests, named the same as abTest.experiences above, and using the experience script from the experience table.
1 call to abjs_generate_js()
abjs_page_attachments in ./abjs.module
Implements hook_page_attachments().

File

./abjs.module, line 95
Write test JavaScript.

Code

function abjs_generate_js(array $tests) {
  if (empty($tests)) {
    return '';
  }
  $tests_js = [];
  for ($i = 0; $i < count($tests); $i++) {

    // Set name of this test to the tid.
    $tests_js[$i] = [
      'name' => "t_{$tests[$i]->tid}",
      'conditions' => [],
      'experiences' => [],
    ];

    // Get all conditions associated with this test,and make functions for the
    // scripts.
    $conditions = Database::getConnection()
      ->query("SELECT tc.tid, tc.cid, c.script FROM {abjs_condition} AS c INNER JOIN {abjs_test_condition} AS tc ON c.cid = tc.cid WHERE tc.tid = :tid", [
      ':tid' => $tests[$i]->tid,
    ])
      ->fetchAll();
    for ($j = 0; $j < count($conditions); $j++) {
      $tests_js[$i]['conditions'][$j] = $conditions[$j]->script;
    }

    // Get all experiences associated with this test and their fractions, make
    // a name for the value of the test cookie, and make functions for the
    // scripts.
    $experiences = Database::getConnection()
      ->query("SELECT te.tid, te.eid, e.script, te.fraction FROM {abjs_experience} AS e INNER JOIN {abjs_test_experience} AS te ON e.eid = te.eid WHERE te.tid = :tid", [
      ':tid' => $tests[$i]->tid,
    ])
      ->fetchAll();
    for ($j = 0; $j < count($experiences); $j++) {
      $tests_js[$i]['experiences'][$j] = [
        'name' => "e_{$experiences[$j]->eid}",
        'fraction' => $experiences[$j]->fraction,
        'script' => $experiences[$j]->script,
      ];
    }
  }

  // These are the only php variables referenced in the script below.
  $cookie_prefix_var = \Drupal::config('abjs.settings')
    ->get('cookie.prefix');
  $cookie_lifetime_var = \Drupal::config('abjs.settings')
    ->get('cookie.lifetime');
  $cookie_domain_var = \Drupal::config('abjs.settings')
    ->get('cookie.domain');
  $cookie_secure_var = \Drupal::config('abjs.settings')
    ->get('cookie.secure');
  $cookie_prefix = !empty($cookie_prefix_var) ? $cookie_prefix_var : 'abjs_';
  $cookie_lifetime = !empty($cookie_lifetime_var) ? $cookie_lifetime_var : '30';
  $cookie_lifetime = floatval($cookie_lifetime);
  $cookie_domain = !empty($cookie_domain_var) ? '; domain=' . $cookie_domain_var : '';
  $cookie_secure = !empty($cookie_secure_var) ? '; secure' : '';
  $js_vars = [
    'tests' => $tests_js,
    'cookiePrefix' => $cookie_prefix,
    'cookieDomain' => $cookie_domain,
    'cookieLifetime' => $cookie_lifetime,
    'cookieSecure' => $cookie_secure,
  ];
  $json = json_encode($js_vars);

  // abjs-common.js is the core functionality of the A/B testing javascript
  // framework. Visitors that pass the assigned condition scripts for each test
  // will be randomly placed and cookied into an experience for that test,
  // based on assigned probabilities for each experience. Each experience has
  // an associated script that is run for that experience, and all applicable
  // experience scripts are executed for each visitor on every page load, in
  // the order in which the tests are defined. The user will have one cookie
  // for each active test.
  $common_js = file_get_contents(drupal_get_path('module', 'abjs') . '/js/abjs-common.js');
  $abjs_script = "'use strict'; (function() {var abjs = {$json};\n{$common_js}})();";
  return $abjs_script;
}