_wpnonce, 'abpo-new-experiment' )) return false; $status = (date("Y-m-d", strtotime($experiment->startDate)) > date("Y-m-d") ) ? 'paused' : "running"; $row = $wpdb->insert( ABPressOptimizer::get_table_name('experiment') , array( 'name' => $experiment->name, 'description' => $experiment->description, 'status' => $status , 'start_date' => date("Y-m-d", strtotime($experiment->startDate)) , 'end_date' => date("Y-m-d", strtotime($experiment->endDate)), 'goal' => $experiment->goal, 'goal_type' => 'clickEvent', 'url' => $experiment->url, 'date_created' => date('Y-m-d H:i:s') )); if(!$row) return false; $id = $wpdb->insert_id; $currImage = 0; $currValue = 0; if(isset($experiment->variationName)) { for ($i=0; $i < count($experiment->variationName); $i++) { $value = $experiment->variation[$currValue]; ++$currValue; $row = $wpdb->insert( ABPressOptimizer::get_table_name('variations') , array( 'experiment_id' => $id, 'type' => 'text', 'name' => $experiment->variationName[$i] , 'value' => $value , 'class' => $experiment->class[$i], 'date_created' => date('Y-m-d H:i:s') )); } } ab_press_createMessage("Your experiment has been created succesfully!"); return true; } /** * Update a new experiment and it's variations * * @return boolean */ function ab_press_updateExperiment($experiment, $files = null) { global $wpdb; $experiment = json_decode(json_encode($experiment), FALSE); ab_press_createMessage("There was an issue updating your experiment please try again"); if(!wp_verify_nonce( $experiment->_wpnonce, 'abpo-new-experiment' )) return false; $status = (date("Y-m-d", strtotime($experiment->startDate)) > date("Y-m-d") ) ? 'paused' : "running"; print_r(date("Y-m-d", strtotime($experiment->startDate))); $row = $wpdb->update( ABPressOptimizer::get_table_name('experiment'), array( 'name' => $experiment->name , 'description' => $experiment->description, 'status' => $status , 'start_date' => date("Y-m-d", strtotime($experiment->startDate)) , 'end_date' => date("Y-m-d", strtotime($experiment->endDate)), 'goal' => $experiment->goal , 'goal_type' => 'page', 'url' => $experiment->url), array( 'id' => $experiment->id ) ); $id = $experiment->id; $currImage = 0; $currValue = 0; if(isset($experiment->variationName)) { for ($i=0; $i < count($experiment->variationName); $i++) { if(empty($experiment->vId[$i])) { $isNew = true; $value = $experiment->variation[$currValue]; ++$currValue; } else { $isNew = false; $value = $experiment->variation[$currValue]; ++$currValue; } if($isNew) { $row = $wpdb->insert( ABPressOptimizer::get_table_name('variations') , array( 'experiment_id' => $id, 'type' => 'text', 'name' => $experiment->variationName[$i] , 'value' => $value , 'class' => $experiment->class[$i], 'date_created' => date('Y-m-d H:i:s') )); } elseif(!$isNew) { $row = $wpdb->update( ABPressOptimizer::get_table_name('variations'), array( 'name' => $experiment->variationName[$i] , 'value' => $value , 'class' => $experiment->class[$i]), array( 'id' => $experiment->vId[$i] ) ); } } } ab_press_createMessage("Your experiment has been updated succesfully!"); return true; } /** * Get an experiment by id * * @return boolean */ function ab_press_getExperiment($id){ global $wpdb; $table = ABPressOptimizer::get_table_name('experiment'); $table2 = ABPressOptimizer::get_table_name('variations'); $query = "SELECT * FROM $table WHERE id = $id"; $query2 = "SELECT * FROM $table2"; $result = $wpdb->get_row($query, OBJECT ); $variations = $wpdb->get_results($query2, OBJECT ); if(!$result) return false; $result->variations = array(); foreach ($variations as $variation) { if($result->id == $variation->experiment_id) $result->variations[] = $variation; } return stripslashes_deep($result); } /** * Get All Experiments * * @return boolean */ function ab_press_getAllExperiment($offset = null, $limit = null){ global $wpdb; $table = ABPressOptimizer::get_table_name('experiment'); $table2 = ABPressOptimizer::get_table_name('variations'); if(is_null($offset)) $query = "SELECT * FROM $table Order By date_created DESC"; else $query = "SELECT * FROM $table Order By date_created DESC LIMIT $offset, $limit "; $query2 = "SELECT * FROM $table2"; $results = $wpdb->get_results($query, OBJECT ); $variations = $wpdb->get_results($query2, OBJECT ); foreach ($results as $result) { $result->variations = array(); foreach ($variations as $variation) { if($result->id == $variation->experiment_id) $result->variations[] = $variation; } } return $results; } /** * Get All active experiments * * @return results */ function ab_press_getAllActiveExperiments($withVariations = false){ global $wpdb; $table = ABPressOptimizer::get_table_name('experiment'); $table2 = ABPressOptimizer::get_table_name('variations'); $query = "SELECT * FROM $table WHERE status = 'running' Order By date_created DESC"; $query2 = "SELECT * FROM $table2"; $results = $wpdb->get_results($query, OBJECT ); if($withVariations) { $variations = $wpdb->get_results($query2, OBJECT ); foreach ($results as $result) { $result->variations = array(); foreach ($variations as $variation) { if($result->id == $variation->experiment_id) $result->variations[] = $variation; } } } return $results; } /** * Get All active experiments * * @return results */ function ab_press_getExperimentIds(){ global $wpdb; $table = ABPressOptimizer::get_table_name('experiment'); $table2 = ABPressOptimizer::get_table_name('variations'); $query = "SELECT id, url, original_convertions FROM $table WHERE status = 'running' Order By date_created DESC"; $query2 = "SELECT id, experiment_id, convertions FROM $table2"; $results = $wpdb->get_results($query, OBJECT ); if(!$results) return false; $variations = $wpdb->get_results($query2, OBJECT ); foreach ($results as $result) { $result->variations = array(); foreach ($variations as $variation) { if($result->id == $variation->experiment_id) $result->variations[] = $variation; } } return $results; } /** * Update status of an experiment */ function ab_press_updateExperimentStatus($id, $status){ global $wpdb; $wpdb->update( ABPressOptimizer::get_table_name('experiment'), array( 'status' => $status), array( 'id' => $id ) ); } /** * Update impression on experiment */ function ab_press_updateImpression($id, $type, $count){ global $wpdb; $count = $count + 1; if($type == 'control') { $wpdb->update( ABPressOptimizer::get_table_name('experiment'), array( 'original_visits' => $count), array( 'id' => $id ) ); } else { $wpdb->update( ABPressOptimizer::get_table_name('variations'), array( 'visits' => $count), array( 'id' => $id ) ); } } /** * Update convertion on experiment */ function ab_press_updateConvertion($id, $type, $count){ global $wpdb; $count = $count + 1; if($type == 'control') { $wpdb->update( ABPressOptimizer::get_table_name('experiment'), array( 'original_convertions' => $count), array( 'id' => $id ) ); } else { $wpdb->update( ABPressOptimizer::get_table_name('variations'), array( 'convertions' => $count), array( 'id' => $id ) ); } } /** * Get Total Convertions * * @return number */ function ab_press_getTotalConvertions($experiment) { $total = $experiment->original_convertions; foreach ($experiment->variations as $variation) { $total += $variation->convertions; } return $total; } /** * Get Total Visitors * * @return number */ function ab_press_getTotalVisitors($experiment) { $total = $experiment->original_visits; foreach ($experiment->variations as $variation) { $total += $variation->visits; } return $total; } /** * Get Convertion Rate * * @return number */ function ab_press_getConvertionRate( $convertions , $total, $isPercent = true) { if($total == 0) return 0; if($isPercent ) return round(($convertions/$total) * 100, 2); else return $convertions/$total; } /** * Get Confinece Interval (Standard Error) * * @return number */ function ab_press_getConfidenceInterval($convertions , $total, $isPercent = true) { $rate = ab_press_getConvertionRate($convertions, $total, false); if($rate == 0) return 0; $se = sqrt(($rate * (1-$rate))/$total) * 1.96; if($isPercent) return round($se * 100 , 2); else return $se; } /** * Get Variation Improvement * * @return number */ function ab_press_getImprovement($control, $test) { if ( $test == 0 || $control == 0) { return 0; } $imporvement = round((($control - $test)/$control) * -100, 2); if($imporvement > 0) $imporvement = "+".$imporvement; else $imporvement = $imporvement; return $imporvement; } /** * Get Plot Points for Control * * @return string */ function ab_press_getPlotControlData($experiment) { $rate = ab_press_getConvertionRate($experiment->original_convertions, $experiment->original_visits, false); $variance = 1.282*( sqrt(($rate * (1-$rate))/$experiment->original_visits)); $variance95 = 1.96*( sqrt(($rate * (1-$rate))/$experiment->original_visits)); $upper = $rate + $variance; $lower= $rate- $variance; $upper95 = $rate + $variance95; $lower95 = $rate - $variance95; $plotPoints = array(($lower *100 ) - 1, $lower *100 , $rate *100 , $upper *100 , ($upper *100 ) + 1 ); return implode(", ", $plotPoints); } /** * Get Plot Points for Variations * * @return string */ function ab_press_getPlotVariationData($variation) { $rate = ab_press_getConvertionRate($variation->convertions, $variation->visits, false); $variance = 1.282*( sqrt(($rate * (1-$rate))/$variation->visits)); $variance95 = 1.96*( sqrt(($rate * (1-$rate))/$variation->visits)); $upper = $rate + $variance; $lower= $rate- $variance; $upper95 = $rate + $variance95; $lower95 = $rate - $variance95; $plotPoints = array(($lower *100 ) - 1, $lower *100 , $rate *100 , $upper *100 , ($upper *100 ) + 1 ); return implode(", ", $plotPoints); } /** * Get Experiment Winner * * @return string */ function ab_press_experimentWinner($experiment){ $winnerAmount = 0; foreach ($experiment->variations as $variation) { $significance = ab_press_getSignificance($experiment, $variation ); if( $significance > $winnerAmount && $significance >= 95 && $variation->visits > 30) { $winnerAmount = $significance; $winner = $variation; } } if($winnerAmount <= 0) return ""; $original_rate = ab_press_getConvertionRate($experiment->original_convertions,$experiment->original_visits); $variation_rate = ab_press_getConvertionRate($winner->convertions,$winner->visits); $improvement = ab_press_getImprovement($original_rate, $variation_rate); return "Test ". ucwords($winner->name) . " is beating out the control by $improvement%!"; } /** * Get Statistical Significance * * @return number */ function ab_press_getSignificance($original, $variation){ if($variation->visits == 0 ) return 0; $original_rate = ab_press_getConvertionRate($original->original_convertions, $original->original_visits, false); $variation_rate = ab_press_getConvertionRate($variation->convertions, $variation->visits, false); $original_se= ab_press_getConfidenceInterval($original->original_convertions, $original->original_visits, false); $variation_se = ab_press_getConfidenceInterval($variation->convertions, $variation->visits, false); $zscore = ab_press_normalcdf($original_rate, $original_se, $variation_rate ); return round($zscore *100, 2); } /** * Normalize Data * * @return number */ function ab_press_normalcdf($mean, $sigma, $to) { if($sigma == 0) return 0; $z = ($to-$mean)/sqrt(2*$sigma*$sigma); $t = 1/(1+0.3275911*abs($z)); $a1 = 0.254829592; $a2 = -0.284496736; $a3 = 1.421413741; $a4 = -1.453152027; $a5 = 1.061405429; $erf = 1-((((($a5*$t + $a4)*$t) + $a3)*$t + $a2)*$t + $a1)*$t*exp(-$z*$z); $sign = 1; if($z < 0) { $sign = -1; } return (1/2)*(1+$sign*$erf); } /** * Create markup for experiment also used inside of code */ function ab_press_optimizer($id, $content, $multipage = false) { $trialMode = false; $isReturningUser = false; $isBot = false; $bots = array('googlebot', 'msnbot', 'slurp', 'ask jeeves', 'crawl', 'ia_archiver', 'lycos'); foreach($bots as $botname) { if(stripos($_SERVER['HTTP_USER_AGENT'], $botname) !== false) { $trialMode = true; $isBot = true; break; } } if(isset($_GET['testing'])) $trialMode = true; if($isBot) return do_shortcode( $content ); $experiment = ab_press_getExperiment($id); $control = (object) array('id'=>"c", 'type'=>'control', 'value' => $content, 'class' => ''); array_unshift($experiment->variations, $control); if($experiment->status != 'running') return $content; //Select Experiment if(isset($_COOKIE["_ab_press_exp_".$id]) || isset($GLOBALS['abtestonpage'])) { if(isset($_COOKIE["_ab_press_exp_".$id])) $currVariation = $_COOKIE["_ab_press_exp_".$id]; else $currVariation = $GLOBALS['abtestonpage']; if($currVariation === "c") { $variation = $control; } else { foreach ($experiment->variations as $var) { if($currVariation == $var->id) { $variation = $var; break; } } } $isReturningUser = true; } else { $randomVariation = rand(0 , count($experiment->variations)-1) ; $variation = $experiment->variations[$randomVariation]; $varId = ($variation->type == "control") ? "c" : $variation->id; $GLOBALS['abtestonpage'] = $varId; if(!$trialMode) { ?> goal_type != "clickEvent"){ ?> goal_type, $experiment->id); if($variation->type == "control") { if(!$trialMode && !$isReturningUser) ab_press_updateImpression($id, 'control', $experiment->original_visits); return do_shortcode( ab_press_createControl($content, $tag, $attributes) ); } else { if(!$trialMode && !$isReturningUser) ab_press_updateImpression($variation->id, 'variation', $variation->visits); return do_shortcode( ab_press_createVariation($variation, $tag, $attributes, $experiment) ); } } function ab_press_full_url() { $s = empty($_SERVER["HTTPS"]) ? '' : ($_SERVER["HTTPS"] == "on") ? "s" : ""; $protocol = substr(strtolower($_SERVER["SERVER_PROTOCOL"]), 0, strpos(strtolower($_SERVER["SERVER_PROTOCOL"]), "/")) . $s; $port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":".$_SERVER["SERVER_PORT"]); return $protocol . "://" . $_SERVER['SERVER_NAME'] . $port . $_SERVER['REQUEST_URI']; } /** * Get Html Tag * * @return String */ function ab_press_getTag($content) { $tagTypes = array('div', 'section', 'p', 'a', 'span', 'input', 'img' ); $tag = ''; foreach ($tagTypes as $tagType) { if(preg_match('%(^<'.$tagType.'[^>]*>.*?^)%i', $content, $tempTag) || preg_match('#<'.$tagType.'[^>]*>#i', $content, $tempTag) ) { $tag = $tagType; break; } } return $tag; } /** * Get Attributes from html * * @return String */ function ab_press_getAttributes($content, $tag, $variation, $event, $id) { $attributes = ""; $ab_press_class = ' ab-press-hock '; $attr = array(); if($event == "clickEvent") { $ab_press_class = ' ab-press-action '; if($variation->type == "control") $attr['abpress'] = $id .'-c' ; else $attr['abpress'] = $id .'-'.$variation->id ; } elseif($event == "clickEventAjax") { $ab_press_class = ' ab-press-action-ajax '; if($variation->type == "control") $attr['abpress'] = $id .'-c' ; else $attr['abpress'] = $id .'-'.$variation->id ; } if(!empty($tag) ) { $doc = new DOMDocument(); libxml_use_internal_errors(true); $doc->loadHTML($content); $nodes = $doc->getElementsByTagName($tag); if ($nodes->item(0)->hasAttributes()) { foreach($nodes->item(0)->attributes as $a) { $attr[strtolower($a->name)] = $a->value; } } if(isset($attr['class'])) $attr['class'] = (string) $attr['class'] . $ab_press_class . $variation->class; else $attr['class'] = $ab_press_class; if($variation->type == "img") { $attr['src'] = $variation->value; } } elseif($variation->type == "img" && empty($tag)) { $attr = array(); $attr['src'] = $variation->value; } else { $attr['class'] = $ab_press_class; } foreach ($attr as $key => $value) { $attributes .= ( ' '. $key . '="' .$value .'" '); } return $attributes; } /** * Get content from html * * @return String */ function ab_press_getContent($content, $tag){ $tagContent = ""; if($tag != "img" && $tag != "input" && $tag != "") { $doc = new DOMDocument(); libxml_use_internal_errors(true); $doc->loadHTML($content); $nodes = $doc->getElementsByTagName($tag); $chidlNode = $nodes->item(0); $tagContent = DOMinnerHTML($nodes->item(0)); // $doc->saveHTML($nodes->item(0)); //$tagContent = $chidlNode->ownerDocument->saveHTML($chidlNode); } return $tagContent; } function DOMinnerHTML($element) { $innerHTML = ""; $children = $element->childNodes; foreach ($children as $child) { $tmp_dom = new DOMDocument(); $tmp_dom->appendChild($tmp_dom->importNode($child, true)); $innerHTML.=trim($tmp_dom->saveHTML()); } return $innerHTML; } /** * Create a control markup * * @return String */ function ab_press_createControl($content, $tag, $attributes) { $tagContent = ab_press_getContent($content, $tag); if($tag == "img") { $result = ""; } elseif ($tag == "input") { $result = ""; } else { if(empty($content)) $result = ""; elseif (!preg_match("/<\/$tag>$/", $content, $matches) ) { $result = $content; } else $result = "<$tag $attributes>$tagContent"; } return $result; } /** * Create a variation markup * * @return String */ function ab_press_createVariation($variation, $tag, $attributes, $experiment){ if($variation->type == "html") { $html = $variation->value; $htmlTag = ab_press_getTag($html); $htmlAttributes = ab_press_getAttributes($html, $htmlTag, $variation, $experiment->goal_type, $experiment->id); $htmlContent = ab_press_getContent($html, $htmlTag); //print_r($htmlAttributes); if(!$htmlTag) return "<$tag $htmlAttributes>$variation->value"; elseif (!preg_match("/<\/$htmlTag>$/", $html, $matches) ) { return $html; } else return "<$htmlTag $htmlAttributes>$htmlContent"; } elseif($variation->type == "img") { return ""; } else { if ($tag == "input") return ""; elseif( ! empty( $tag ) ) return "<$tag $attributes>$variation->value"; else return $variation->value; } } /** * Create a flash message */ function ab_press_createMessage($message) { $_SESSION['message'] = $message; } /** * Delete a flash message */ function ab_press_deleteMessage() { $_SESSION['message'] = null; }