Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,207 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_AB_Admin_View_Test_Page
* Used for viewing a test details(report)
*
* - enqueues the scripts/styles
* - localizes required data based on test id from query string
*/
class Thrive_AB_Admin_View_Test_Page {
/**
* @var int
*/
protected $_test_id;
/**
* @var Thrive_AB_Test
*/
protected $test;
public function __construct() {
$test_id = ! empty( $_GET['test_id'] ) ? sanitize_key( $_GET['test_id'] ) : null;
if ( $test_id ) {
$this->_test_id = (int) $test_id;
/**
* Enqueue Scripts
*/
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
/**
* Enqueue Styles
*/
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ), PHP_INT_MAX );
add_action( 'admin_print_footer_scripts', array( $this, 'print_backbone_templates' ) );
add_action( 'admin_print_footer_scripts', array( $this, 'include_svg' ) );
add_filter( 'admin_title', array( $this, 'get_title' ), 10, 2 );
}
}
public function get_title() {
$admin_title = thrive_ab()->plugin_name() . ' - ' . $this->_get_test()->title;
return $admin_title;
}
/**
* enqueue scripts
*/
public function enqueue_scripts() {
wp_enqueue_script( 'backbone' );
$js_suffix = defined( 'TVE_DEBUG' ) && TVE_DEBUG ? '.js' : '.min.js';
wp_enqueue_script( 'thrive-ab-dashboard', thrive_ab()->url( 'assets/js/dist/app' . $js_suffix ), array(
'backbone',
'jquery-ui-autocomplete',
'tve-dash-main-js',
), Thrive_AB::V, true );
$this->localize_data();
/**
* Enqueue dash js file cos it is needed for Modals, Views and Materialize
*/
tve_dash_enqueue_script( 'tve-dash-main-js', TVE_DASH_URL . '/js/dist/tve-dash.min.js', array(
'jquery',
'backbone',
), false, true );
tve_dash_enqueue_script( 'tve-dash-highcharts', TVE_DASH_URL . '/js/util/highcharts/highcharts.js', array(
'jquery',
), false, true );
tve_dash_enqueue_script( 'tve-dash-highcharts-more', TVE_DASH_URL . '/js/util/highcharts/highcharts-more.js', array(
'jquery',
'tve-dash-highcharts',
), false, true );
}
/**
* enqueue styles
*/
public function enqueue_styles() {
/**
* Inherit CSS from dashboard
*/
tve_dash_enqueue_style( 'tve-dash-styles-css', TVE_DASH_URL . '/css/styles.css' );
wp_enqueue_style( 'thrive-ab', thrive_ab()->url( 'assets/css/dashboard.css' ), array(
'tve-dash-styles-css',
), Thrive_AB::V );
/**
* Use this css file to overwrite the css for this page only
*/
wp_enqueue_style( 'thrive-ab-view-test-page', thrive_ab()->url( 'assets/css/admin/tab-view-test-page.css' ), array(
'tve-dash-styles-css',
), Thrive_AB::V );
}
/**
* put the backbone templates into page for later usage
*/
public function print_backbone_templates() {
$templates = tve_dash_get_backbone_templates( thrive_ab()->path( 'includes/views/backbone' ), 'backbone' );
tve_dash_output_backbone_templates( $templates );
}
protected function _get_test( $test_id = null ) {
if ( ! ( $this->test instanceof Thrive_AB_Test ) ) {
$this->test = new Thrive_AB_Test( (int) $this->_test_id );
}
return $this->test;
}
private function localize_data() {
$data = array();
try {
$test = $this->_get_test();
$test->get_items();
$page = new Thrive_AB_Page( (int) $test->page_id );
$report_manager = new Thrive_AB_Report_Manager();
$data['current_test'] = $test->get_data();
$data['page'] = $page->get_data();
$data['t'] = include( thrive_ab()->path( 'includes/i18n.php' ) );
$data['chart_colors'] = array(
'#20a238',
'#2f82d7',
'#fea338',
'#dd383d',
'#ab31a4',
'#95d442',
'#36c4e2',
'#525252',
'#f3643e',
'#e26edd',
);
$data['license'] = Thrive_AB::license_data();
$data['test_chart'] = $report_manager->get_test_chart_data(
array(
'test_id' => (int) $this->_test_id,
'type' => 'conversion_rate',
)
);
$data['ajax'] = array(
'url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( Thrive_AB_Ajax::NONCE_NAME ),
'action' => Thrive_AB_Ajax::$action,
'controller_action' => Thrive_AB_Ajax::$controller_action,
);
} catch ( Exception $e ) {
die( $e->getMessage() );
}
wp_localize_script( 'thrive-ab-dashboard', 'ThriveAB', $data );
}
/**
* puts the page html required for viewing a test
*/
public function render() {
echo '<div id="tab-dashboard-wrapper"></div>';
}
/**
* include svg file with all required icons
* usually used on admin_print_footer_scripts
*/
public function include_svg() {
include thrive_ab()->path( '/assets/fonts/icons.svg' );
}
}

View File

@@ -0,0 +1,378 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Ajax_Controller {
/**
* @var Thrive_AB_Ajax_Controller
*/
protected static $_instance;
private function __construct() {
}
public static function instance() {
if ( ! self::$_instance ) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Sets the request's header with server protocol and status
* Sets the request's body with specified $message
*
* @param string $message the error message.
* @param string $status the error status.
*/
protected function error( $message, $status = '404 Not Found' ) {
header( $_SERVER['SERVER_PROTOCOL'] . ' ' . $status );
wp_send_json_error( array( 'message' => $message ) );
}
/**
* Returns the params from $_POST or $_REQUEST
*
* @param int $key the parameter kew.
* @param null $default the default value.
*
* @return mixed|null|$default
*/
protected function param( $key, $default = null ) {
return isset( $_POST[ $key ] ) ? $_POST[ $key ] : ( isset( $_REQUEST[ $key ] ) ? $_REQUEST[ $key ] : $default );
}
/**
* Entry-point for each ajax request
* This should dispatch the request to the appropriate method based on the "route" parameter
*
* @return array|object
*/
public function handle() {
/* Check if user still has the cap to use the plugin */
if ( ! Thrive_AB_Product::has_access() ) {
$this->error( __( 'You do not have this capability anymore', 'thrive-ab-page-testing' ) );
}
if ( ! check_ajax_referer( Thrive_AB_Ajax::NONCE_NAME, 'nonce', false ) ) {
$this->error( __( 'Invalid request.', 'thrive-ab-page-testing' ) );
}
$route = $this->param( 'route' );
$route = preg_replace( '#([^a-zA-Z0-9-])#', '', $route );
$function = $route . '_action';
if ( ! method_exists( $this, $function ) ) {
$this->error( sprintf( __( 'Method %s not implemented', 'thrive-ab-page-testing' ), $function ) );
}
$method = empty( $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] ) ? 'GET' : $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'];
$model = json_decode( file_get_contents( 'php://input' ), true );
return call_user_func( array( $this, $function ), $method, $model );
}
protected function tests_action( $method, $model ) {
$response = array();
switch ( $method ) {
case 'POST':
case 'PUT':
try {
if ( ! empty( $model['save_test_settings'] ) ) {
unset( $model['save_test_settings'] );
unset( $model['items'] );
Thrive_AB_Test_Manager::save_test( $model );
return true;
}
$test = Thrive_AB_Test_Manager::save_test( $model );
$test->start()->save();
$response = $test->get_data();
} catch ( Exception $e ) {
$this->error( $e->getMessage() );
}
break;
}
return $response;
}
protected function variations_action( $method, $model ) {
$response = array();
switch ( $method ) {
case 'PATCH':
try {
$id = (int) $this->param( 'ID' );
$variation = new Thrive_AB_Page_Variation( $id );
$model['ID'] = $id;
$response = $variation->save( $model );
} catch ( Exception $e ) {
$this->error( $e->getMessage() );
}
break;
case 'PUT':
case 'POST':
try {
$post_parent = ! empty( $model['post_parent'] ) ? $model['post_parent'] : null;
$page = new Thrive_AB_Page( $post_parent );
$model['meta']['traffic'] = ! empty( $model['traffic'] ) ? (int) $model['traffic'] : 0;
$model['meta']['is_control'] = ! empty( $model['is_control'] ) ? (bool) $model['is_control'] : false;
if ( ! empty( $model['action'] ) && $model['action'] == 'publish' ) {
//case it is an archived variation and we want it restored
$model['meta']['status'] = 'deleted';
$variation = $page->save_variation( $model );
$model['source_id'] = $model['ID'];
$model['ID'] = null;
$model['meta']['status'] = 'published';
} elseif ( ! empty( $model['action'] ) && $model['action'] == 'archive' ) {
// case it is a published archived and we want it archived
$model['meta']['status'] = 'archived';
} else {
// anything else
$model['meta']['status'] = 'published';
}
$variation = $page->save_variation( $model );
$variation->set_page( $page->get_post() );
if ( ! empty( $model['source_id'] ) ) {
$source_variation = new Thrive_AB_Page_Variation( $model['source_id'] );
$variation_data = $variation->get_data();
if ( ! empty( $variation_data ) ) {
$variation_id = $variation_data['ID'];
$source_variation->get_meta()->init( array(
get_post_type( $post_parent ),
'template',
) )->copy_to( $variation_id );
$source_variation->copy_thumb_to( $variation_id );
}
}
$response = $variation->get_data();
} catch ( Exception $e ) {
$this->error( $e->getMessage() );
}
break;
case 'DELETE':
try {
$id = (int) $this->param( 'ID', null );
$variation = new Thrive_AB_Page_Variation( $id );
$response = $variation->get_meta()->update( 'status', 'deleted' );
} catch ( Exception $e ) {
$this->error( $e->getMessage() );
}
break;
}
return $response;
}
/**
* Report Action Endpoint
*
* @param $method
* @param $model
*
* @return array
*/
protected function report_action( $method, $model ) {
$response = array();
switch ( $method ) {
case 'GET':
$id = (int) $this->param( 'ID' );
$interval = $this->param( 'interval' );
$type = $this->param( 'type' );
$report_manager = new Thrive_AB_Report_Manager();
return $report_manager->get_test_chart_data( array(
'test_id' => $id,
'interval' => $interval,
'type' => $type,
) );
break;
default:
break;
}
return $response;
}
protected function testitem_action( $method, $model ) {
$response = array();
switch ( $method ) {
case 'POST':
case 'PUT':
if ( ! empty( $model['stop_test_item'] ) ) {
$variation = new Thrive_AB_Page_Variation( (int) $model['variation_id'] );
$meta = $variation->get_meta();
$meta->update( 'traffic', 0 );
$meta->update( 'status', 'archived' );
$item = new Thrive_AB_Test_Item( (int) $model['id'] );
$item->stop()->save();
$item->variation = $variation;
$data = $item->get_data();
return $data;
}
break;
default:
break;
}
return $response;
}
protected function traffic_action( $method, $model ) {
if ( isset( $model['ID'] ) ) {
unset( $model['ID'] );
}
$edit_post_traffic = $this->param( 'tab_edit_post_traffic' );
if ( empty( $model ) && ! empty( $edit_post_traffic ) && is_array( $edit_post_traffic ) ) {
/**
* Traffic From Edit Post View
*/
if ( array_sum( $edit_post_traffic ) < 100 ) {
$model = $edit_post_traffic;
}
}
foreach ( $model as $id => $traffic ) {
$variation = new Thrive_AB_Variation( $id );
$variation->get_meta()->update( 'traffic', (int) $traffic );
}
}
/**
* Called From Optimize Admin Dashboard
* Returns all tests that are stored in database for display
*
* @return array
* @throws Exception
*/
protected function testsforadmin_action() {
$test_manager = new Thrive_AB_Test_Manager();
$report_manager = new Thrive_AB_Report_Manager();
$all_tests = $test_manager->get_tests();
$stats = $report_manager->get_admin_dashboard_stats();
$goals = array(
'monetary' => __( 'Revenue', 'thrive-ab-page-testing' ),
'visits' => __( 'Goal Page Visit', 'thrive-ab-page-testing' ),
'optins' => __( 'Subscriptions', 'thrive-ab-page-testing' ),
);
$return = array();
$return['running_tests'] = array();
$return['completed_tests'] = array();
$return['dashboard_stats'] = $stats;
foreach ( $all_tests as $test ) {
//When a post is in trash list, we should hide it from the Admin Tests Table
if ( get_post_status( $test['page_id'] ) !== 'publish' ) {
continue;
}
$test['date_started_pretty'] = date_i18n( 'd F Y', strtotime( $test['date_started'] ) );
$test['date_completed_pretty'] = date_i18n( 'd F Y', strtotime( $test['date_completed'] ) );
$test['goal'] = $goals[ $test['type'] ];
$test['unique_impressions'] = 0;
$test['conversions'] = 0;
try {
$ab_page = new Thrive_AB_Page( (int) $test['page_id'] );
} catch ( Exception $e ) {
continue;
}
$test['test_link'] = $ab_page->get_test_link( $test['id'] );
$test['page_title'] = $ab_page->post_title;
$items = $test_manager->get_items_by_filters( array( 'test_id' => $test['id'] ) );
foreach ( $items as $item ) {
$test['unique_impressions'] += (int) $item['unique_impressions'];
$test['conversions'] += (int) $item['conversions'];
}
if ( $test['status'] === 'running' ) {
$return['running_tests'][] = $test;
} elseif ( $test['status'] === 'completed' ) {
$return['completed_tests'][] = $test;
}
}
function running_tests_sort( $a, $b ) {
return strtotime( $b['date_started'] ) - strtotime( $a['date_started'] );
}
function completed_tests_sort( $a, $b ) {
return strtotime( $b['date_completed'] ) - strtotime( $a['date_completed'] );
}
usort( $return['running_tests'], 'running_tests_sort' );
usort( $return['completed_tests'], 'completed_tests_sort' );
return $return;
}
/**
* Deletes a test from the Admin Dashboard
*
* @return array
*/
protected function deletecompletedtestadmin_action() {
$return = array(
'success' => 0,
'text' => __( 'There was an error in the process.', 'thrive-ab-page-testing' ),
);
$id = (int) $this->param( 'id' );
$page_id = (int) $this->param( 'page_id' );
if ( ! empty( $id ) && ! empty( $page_id ) ) {
Thrive_AB_Test_Manager::delete_test( array(
'id' => $id,
'page_id' => $page_id,
) );
$return['success'] = 1;
$return['text'] = __( 'The test was deleted successfully!', 'thrive-ab-page-testing' );
}
return $return;
}
}

View File

@@ -0,0 +1,386 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_AB_Ajax
*
* Defines the ajax actions and implements their hooks
*/
class Thrive_AB_Ajax {
const NONCE_NAME = 'thrive-ab-ajax-nonce';
const REGISTER_IMPRESSION_ACTION_NAME = 'register_impression';
public static $controller_action = 'thrive_ab_ajax_controller';
public static $action = 'thrive_ab_ajax_action';
public static $post_id = null;
public static function init() {
self::add_ajax_actions();
}
public static function add_ajax_actions() {
$actions = array(
self::$action => true,
self::$controller_action => true,
);
foreach ( $actions as $action => $nopriv ) {
add_action( 'wp_ajax_' . $action, array( __CLASS__, $action ) );
if ( $nopriv ) {
add_action( 'wp_ajax_nopriv_' . $action, array( __CLASS__, $action ) );
}
}
/**
* hook of TD lazy load
*/
add_filter( 'tve_dash_main_ajax_top_lazy_load', array( __CLASS__, 'dashboard_lazy_load' ), 10, 2 );
}
/**
* Handler for all
*/
public static function thrive_ab_ajax_action() {
$custom = isset( $_REQUEST['custom'] ) ? $_REQUEST['custom'] : '';
$response = array();
if ( method_exists( __CLASS__, $custom ) ) {
$response = call_user_func( array( __CLASS__, $custom ), $_REQUEST );
} else {
wp_send_json_error();
}
wp_send_json( $response );
}
public static function thrive_ab_ajax_controller() {
check_ajax_referer( self::NONCE_NAME, 'nonce' );
require_once dirname( __FILE__ ) . '/class-thrive-ab-ajax-controller.php';
$response = Thrive_AB_Ajax_Controller::instance()->handle();
wp_send_json( $response );
}
public static function post_search( $filters ) {
$s = trim( wp_unslash( $filters['q'] ) );
$s = trim( $s );
$selected_post_types = array_merge( array(
'post',
'product',
), array_diff( get_post_types(), apply_filters( 'tcb_post_grid_banned_types', array() ) ) );
if ( empty( $filters['exclude_id'] ) ) {
$filters['exclude_id'] = array();
}
$args = array(
'post_type' => $selected_post_types,
'post_status' => 'publish',
's' => $s,
'numberposts' => - 1,
'post__not_in' => $filters['exclude_id'],
'orderby' => 'title',
'order' => 'ASC',
);
$posts = array();
foreach ( get_posts( $args ) as $item ) {
$title = $item->post_title;
if ( ! empty( $s ) ) {
$item->post_title = preg_replace( "#($s)#i", '<b>$0</b>', $item->post_title );
}
$post = array(
'label' => $item->post_title,
'title' => $title,
'id' => $item->ID,
'value' => $item->post_title,
'url' => get_permalink( $item->ID ),
'edit_url' => tcb_get_editor_url( $item->ID ),
'type' => $item->post_type,
'is_popup' => isset( $post_types_data[ $item->post_type ] ) && ! empty( $post_types_data[ $item->post_type ]['event_action'] ),
);
if ( $post['is_popup'] ) {
$post['url'] = '#' . $post_types_data[ $item->post_type ]['name'] . ': ' . $title;
$post['event_action'] = $post_types_data[ $item->post_type ]['event_action'];
$post['post_type_name'] = $post_types_data[ $item->post_type ]['name'];
}
$posts [] = $post;
}
return $posts;
}
public static function add_new_page( $data ) {
if ( empty( $data['title'] ) ) {
die( __( 'Page could not be saved!', 'thrive-ab-page-testing' ) );
}
$attrs = array(
'post_content' => '<p>Thank you page</p>',
'post_title' => $data['title'],
'post_status' => 'publish',
'post_type' => 'page',
);
$post_id = wp_insert_post( $attrs );
if ( $post_id === 0 || is_wp_error( $post_id ) ) {
die( __( 'Page could not be saved!', 'thrive-ab-page-testing' ) );
}
$post = get_post( $post_id );
$post->edit_url = tcb_get_editor_url( $post_id );
return array(
'post' => $post,
);
}
public static function set_winner( $data ) {
if ( empty( $data['page_id'] ) || empty( $data['variation_id'] ) ) {
return null;
}
$page = new Thrive_AB_Page( (int) $data['page_id'] );
$winner_variation = new Thrive_AB_Page_Variation( (int) $data['variation_id'] );
$page_variation = new Thrive_AB_Page_Variation( (int) $data['page_id'] );
/**
* close test
*/
$running_test = $page->get_running_test();
if ( ! ( $running_test instanceof Thrive_AB_Test ) ) {
return null;
}
$test_item = new Thrive_AB_Test_Item();
$filters = array(
'test_id' => $running_test->id,
'page_id' => $data['page_id'],
'variation_id' => $data['page_id'],
);
$test_item->init_by_filters( $filters );
/**
* add new page variation to db with content from page
*/
$new_variation = $page->save_variation( array(
'post_title' => $page_variation->post_title,
) );
$page_variation->get_meta()->init( array(
'page',
'template',
'variation',
) )->copy_to( $new_variation->ID );
/**
* Changes the Winner Variation ID in the log table to be relevant for the report.
* This was done because on winning, a test item changes the variation_id
*/
Thrive_AB_Event_Manager::bulk_update_log( array( 'variation_id' => $new_variation->ID ), array(
'variation_id' => $test_item->variation_id,
'test_id' => $test_item->test_id,
'page_id' => $test_item->page_id,
) );
/**
* for page test item set the new variation which has the content from page
*/
$test_item->variation_id = $new_variation->ID;
/**
* set the content of winning variation to page
*/
$winner_variation->get_meta()->init( array(
'page',
'template',
'variation',
) );
$winner_variation->get_meta()->copy_to( $page_variation->ID );
if ( $winner_variation->is_control() ) {
$new_variation->get_meta()->update( 'status', 'deleted' );
} else {
$winner_variation->get_meta()->update( 'status', 'deleted' );
}
$notification_manager_item = null;
if ( (int) $test_item->is_control === 1 && (int) $test_item->id === (int) $data['id'] ) {
$test_item->is_winner = 1;
$notification_manager_item = $test_item;
} else {
/**
* Save Winner Item
*/
$winner_item = $winner_variation->get_test_item();
$winner_item->is_winner = 1;
$winner_item->save();
$notification_manager_item = $winner_item;
}
$test_item->save();
/**
* archive all other variations
*/
$all_variations = $page->get_variations( array(), 'obj' );
/** @var Thrive_AB_Page_Variation $item */
foreach ( $all_variations as $item ) {
if ( $item->is_control() ) {
continue;
}
$item->get_meta()->update( 'status', 'archived' );
}
/**
* Set status to completed once everything is done
*/
$running_test->stop()->save();
$_nm_variation = (object) $notification_manager_item->get_data();
$_nm_test = (object) $running_test->get_data();
$_nm_test->trigger_source = 'tab';
$_nm_test->url = $page->get_test_link( $running_test->id );
$_nm_variation->variation = array( 'post_title' => $_nm_variation->title, 'key' => $_nm_variation->id );
do_action( 'tab_action_set_test_item_winner', $_nm_variation, $_nm_test );
return $data;
}
public static function localize( $data ) {
if ( ! is_array( $data ) ) {
$data = array( 'ajax' );
}
$post_id = $data['post']->post_parent ? (int) $data['post']->post_parent : (int) $data['post']->ID;
try {
$page = new Thrive_AB_Page( $post_id );
$running_test = $page->get_running_test();
$data['ajax']['thrive_ab'] = array(
'action' => self::$action,
'running_test' => $running_test instanceof Thrive_AB_Test ? $running_test->id : false,
);
} catch ( Exception $e ) {
}
return $data;
}
public static function save_variation_thumb() {
if ( ! empty( $_REQUEST['reset_data'] ) ) {
Thrive_AB_Event_Manager::reset_test_data( $_REQUEST['reset_data'] );
}
if ( ! isset( $_FILES['preview_file'] ) ) {
return array(
'success' => false,
);
}
self::$post_id = $_REQUEST['post_id'];
if ( ! function_exists( 'wp_handle_upload' ) ) {
require_once( ABSPATH . 'wp-admin/includes/file.php' );
}
add_filter( 'upload_dir', array( __CLASS__, 'upload_dir' ) );
$moved_file = wp_handle_upload( $_FILES['preview_file'], array(
'action' => 'thrive_ab_ajax_action',
'unique_filename_callback' => array( __CLASS__, 'get_preview_filename' ),
) );
remove_filter( 'upload_dir', array( __CLASS__, 'upload_dir' ) );
if ( empty( $moved_file['url'] ) ) {
return array(
'success' => false,
);
}
$editor = wp_get_image_editor( $moved_file['file'] );
$editor->resize( 800, 500 );
$editor->save( $moved_file['file'] );
return array(
'success' => true,
);
}
public static function get_preview_filename() {
return self::$post_id . '.png';
}
public static function upload_dir( $upload ) {
$sub_dir = '/thrive-ab-page-testing/variations';
$upload['path'] = $upload['basedir'] . $sub_dir;
$upload['url'] = $upload['baseurl'] . $sub_dir;
$upload['subdir'] = $sub_dir;
return $upload;
}
/**
* Callback of TD Lazy Load
*
* @param $array
* @param $params
*
* @return mixed
*/
public static function dashboard_lazy_load( $array, $params ) {
/**
* register unique impression
*/
if ( ! empty( $params ) && is_array( $params ) && isset( $params['action'] ) && $params['action'] === self::REGISTER_IMPRESSION_ACTION_NAME ) {
$page_id = $params['page_id'];
$test_id = $params['test_id'];
$variation_id = $params['variation_id'];
Thrive_AB_Event_Manager::do_impression( $page_id, $test_id, $variation_id );
}
return $array;
}
}
Thrive_AB_Ajax::init();

View File

@@ -0,0 +1,380 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Admin {
protected static $_variations = array();
public static $pages
= array(
'view_test' => array(
'slug' => 'tab_admin_view_test',
),
);
public static function init() {
/**
* Init pages
*/
add_action( 'init', array( __CLASS__, 'init_pages' ) );
/**
* on this filter we are very sure the user is on post.php within edit case/action
*/
add_filter( 'replace_editor', array( __CLASS__, 'remove_tar_edit_button' ), 10, 2 );
add_filter( 'admin_body_class', array( __CLASS__, 'wp_editor_body_class' ), 10, 4 );
add_filter( 'page_row_actions', array( __CLASS__, 'page_row_actions' ), 11, 2 );
/**
* Add Thrive A/B Page Testing To Dashboard
*/
add_filter( 'tve_dash_admin_product_menu', array( __CLASS__, 'add_to_dashboard_menu' ) );
/**
* Add admin scripts and styles
*/
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
/**
* On Page delete, delete all the A/B Test Data
*/
add_action( 'delete_post', array( __CLASS__, 'delete_page_tests' ), 10 );
/**
* Hooks the notification manager trigger types
*/
add_filter( 'td_nm_trigger_types', array( __CLASS__, 'filter_nm_trigger_types' ) );
/**
* Thrown by Thrive Themes, maybe we should support more themes?
*/
add_filter( 'thrive_save_post_option', array( __CLASS__, 'save_meta_to_variations' ), 10, 3 );
}
/**
* Hook when a Thrive Theme Post Option is saved
* We need to replicate it to it's variations
*
* @param $post_id
* @param $meta_name
* @param $meta_value
*
* @return mixed
*/
public static function save_meta_to_variations( $meta_value, $post_id, $meta_name ) {
$post_id = (int) $post_id;
try {
$page = new Thrive_AB_Page( $post_id );
if ( empty( self::$_variations ) ) {
self::$_variations = $page->get_variations( array(), 'obj' );
}
/** @var Thrive_AB_Page_Variation $variation */
foreach ( self::$_variations as $variation ) {
if ( $variation->ID === $post_id ) {
continue;
}
$variation->get_meta()->update( $meta_name, $meta_value );
}
} catch ( Exception $e ) {
}
return $meta_value;
}
/**
* On page delete - Delete all the AB page data linked to the deleted page
*
* @param int $post_id
*/
public static function delete_page_tests( $post_id = 0 ) {
if ( empty( $post_id ) ) {
return;
}
$test_manager = new Thrive_AB_Test_Manager();
$tests = $test_manager->get_tests( array( 'page_id' => $post_id ), 'array' );
if ( empty( $tests ) ) {
return;
}
foreach ( $tests as $test ) {
Thrive_AB_Test_Manager::delete_test( array(
'id' => $test['id'],
'page_id' => $post_id,
) );
}
}
public static function remove_tar_edit_button( $return, $post ) {
try {
$page = new Thrive_AB_Page( (int) $post->ID );
$test_id = $page->get_meta()->get( 'running_test_id' );
} catch ( Exception $e ) {
}
if ( ! empty( $test_id ) ) {
remove_action( 'edit_form_after_title', array( tcb_admin(), 'admin_edit_button' ) );
add_action( 'edit_form_after_title', array( __CLASS__, 'tar_edit_button' ) );
}
return $return;
}
public static function tar_edit_button() {
include dirname( __FILE__ ) . '/views/admin/tar-edit-button.php';
}
public static function wp_editor_body_class( $classes ) {
$screen = get_current_screen();
if ( empty( $screen ) || ! $screen->base || 'post' != $screen->base ) {
return $classes;
}
$post_type = get_post_type();
$post_id = get_the_ID();
if ( empty( $post_id ) || empty( $post_type ) ) {
return $classes;
}
try {
$page = new Thrive_AB_Page( (int) $post_id );
$test_id = $page->get_meta()->get( 'running_test_id' );
} catch ( Exception $e ) {
}
if ( ! empty( $test_id ) ) {
$classes .= ' tcb-hide-wp-editor';
}
return $classes;
}
public static function page_row_actions( $actions, $page ) {
if ( empty( $actions['tcb'] ) ) {
return $actions;
}
try {
$page_instance = new Thrive_AB_Page( $page );
$test_id = $page_instance->get_meta()->get( 'running_test_id' );
if ( ! empty( $test_id ) ) {
/**
* when a pages has a test running remove some actions
*/
unset( $actions['tcb'] );
unset( $actions['edit_as_new_draft'] );
unset( $actions['trash'] );
$test_url = Thrive_AB_Test_Manager::get_test_url( $test_id );
$icon_url = thrive_ab()->url( 'assets/images/tab-logo.png' );
?>
<style type="text/css">
.thrive-ab-view-test-action {
background: url('<?php echo $icon_url ?>');
background-size: 17px 17px;
padding-left: 20px;
background-repeat: no-repeat;
}
</style>
<?php
$actions['thrive-ab'] = '<a class="thrive-ab-view-test-action" href="' . $test_url . '">' . __( 'View test details', 'thrive-ab-page-testing' ) . '</a>';
}
} catch ( Exception $e ) {
}
return $actions;
}
/**
* Push the Thrive A/B Testing to Thrive Dashboard menu
*
* @param array $menus items already in Thrive Dashboard.
*
* @return array
*/
public static function add_to_dashboard_menu( $menus = array() ) {
if ( ! class_exists( 'Thrive_AB_Product', false ) ) {
require_once dirname( __FILE__ ) . '/class-thrive-ab-product.php';
}
$menus['tab'] = array(
'parent_slug' => 'tve_dash_section',
'page_title' => __( 'Thrive Optimize', 'thrive-ab-page-testing' ),
'menu_title' => __( 'Thrive Optimize', 'thrive-ab-page-testing' ),
'capability' => Thrive_AB_Product::cap(),
'menu_slug' => 'tab_admin_dashboard',
'function' => array( __CLASS__, 'dashboard' ),
);
return $menus;
}
/**
* Enqueue all required scripts and styles
*
* @param string $hook page hook.
*/
public static function enqueue_scripts( $hook ) {
$accepted_hooks = apply_filters( 'tab_accepted_admin_pages', array(
'thrive-dashboard_page_tab_admin_dashboard',
'admin_page_tab_admin_view_test',
) );
if ( ! in_array( $hook, $accepted_hooks, true ) ) {
return;
}
/**
* Enqueue dash scripts
*/
tve_dash_enqueue();
if ( ! thrive_ab()->license_activated() ) {
return;
}
$js_suffix = defined( 'TVE_DEBUG' ) && TVE_DEBUG ? '.js' : '.min.js';
/**
* Specific admin styles
*/
wp_enqueue_style( 'tab-admin-style', thrive_ab()->url( 'assets/css/admin-styles.css' ), array(), Thrive_AB::V );
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'backbone' );
wp_enqueue_script( 'tab-admin-js', thrive_ab()->url( 'assets/js/dist/tab-admin' . $js_suffix ), array(
'jquery',
'backbone',
), Thrive_AB::V, true );
wp_localize_script( 'tab-admin-js', 'ThriveAbAdmin', self::get_localization() );
/**
* Output the main templates for backbone views used in dashboard.
*/
add_action( 'admin_print_footer_scripts', array( __CLASS__, 'render_backbone_templates' ) );
}
/**
* Render backbone templates
*/
public static function render_backbone_templates() {
$templates = tve_dash_get_backbone_templates( thrive_ab()->path( 'includes/views/admin/backbone' ), 'backbone' );
tve_dash_output_backbone_templates( $templates );
}
/**
* Output Thrive A/B Testing Dashboard - the main plugin admin page
*/
public static function dashboard() {
if ( ! thrive_ab()->license_activated() ) {
return;
}
include dirname( __FILE__ ) . '/views/admin/dashboard.php';
}
/**
* Hook into TD Notification Manager and push trigger types
*
* @param $trigger_types
*
* @return array
*/
public static function filter_nm_trigger_types( $trigger_types ) {
if ( ! in_array( 'split_test_ends', array_keys( $trigger_types ) ) ) {
$trigger_types['split_test_ends'] = __( 'A/B Test Ends', 'thrive-ab-page-testing' );
}
return $trigger_types;
}
/**
* Gets the javascript variables.
*
* @return array
*/
public static function get_localization() {
return array(
't' => array(
'Thrive_Dashboard' => __( 'Thrive Dashboard', 'thrive-ab-page-testing' ),
'Dashboard' => __( 'Optimize Dashboard', 'thrive-ab-page-testing' ),
'about_to_delete_variation' => __( 'Are you sure you want to delete %s ?', 'thrive-ab-page-testing' ),
'yes' => __( 'Yes', 'thrive-ab-page-testing' ),
'no' => __( 'No', 'thrive-ab-page-testing' ),
),
'ajax' => array(
'url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( Thrive_AB_Ajax::NONCE_NAME ),
'action' => Thrive_AB_Ajax::$action,
'controller_action' => Thrive_AB_Ajax::$controller_action,
),
'dash_url' => admin_url( 'admin.php?page=tve_dash_section' ),
'license' => Thrive_AB::license_data(),
);
}
/**
* callback for setting an admin menu for viewing a test
* initialize the page and add it to admin menu as submenu page
* it's not displayed on wp menu
*/
public static function view_test_menu() {
$view_test_page = new Thrive_AB_Admin_View_Test_Page();
$has_access = class_exists( 'Thrive_AB_Product', false ) ? Thrive_AB_Product::cap() : current_user_can( 'manage_options' );
add_submenu_page(
null,
__( 'View test', 'thrive-ab-page-testing' ),
__( 'View Test', 'thrive-ab-page-testing' ),
$has_access,
self::$pages['view_test']['slug'],
array( $view_test_page, 'render' )
);
}
public static function init_pages() {
require_once dirname( __FILE__ ) . '/admin/class-thrive-ab-view-test-page.php';
add_action( 'admin_menu', array( __CLASS__, 'view_test_menu' ) );
}
}
Thrive_AB_Admin::init();

View File

@@ -0,0 +1,91 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Checker {
/**
* @var array
*/
private static $_tar_required = array(
'active' => true,
'min_version' => '2.0.17',
);
public static function init() {
register_activation_hook( THRIVE_AB_PLUGIN_FILE, array( __CLASS__, 'check' ) );
}
/**
* Check if the requirements for this plugin are fulfilled
* If not a notification is pushed into stack for later display
*
* @return void
*/
public static function check() {
$details = self::get_thrive_architect_details();
if ( empty( $details['active'] ) ) {
Thrive_Admin_Notices::push_notice( 'active' );
return;
}
if ( ! self::is_required_version( $details['version'] ) ) {
Thrive_Admin_Notices::push_notice( 'min_version' );
return;
}
}
/**
* Check if the TAr version is greater or equal with required one
*
* @param $tar_version
*
* @return bool
*/
protected static function is_required_version( $tar_version ) {
if ( defined( 'TVE_DEBUG' ) && $tar_version === '0.dev' ) {
return true;
}
return version_compare( $tar_version, self::$_tar_required['min_version'], '>=' );
}
/**
* @return array
*/
public static function get_thrive_architect_details() {
$_defaults = array(
'active' => false,
'version' => 0,
);
$is_active = is_plugin_active( 'thrive-visual-editor/thrive-visual-editor.php' );
$version = defined( 'TVE_VERSION' ) ? TVE_VERSION : 0;
$_defaults['active'] = $is_active;
$_defaults['version'] = $version;
return $_defaults;
}
public static function get_tar_required_version() {
return self::$_tar_required['min_version'];
}
}
Thrive_AB_Checker::init();

View File

@@ -0,0 +1,55 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_AB_Event_Manager
*/
class Thrive_AB_Cookie_Manager {
protected static $_instance;
public function __construct() {
}
public static function instance() {
if ( empty( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
public static function set_cookie( $test_id = null, $page_id = null, $variation_id = null, $type = 1 ) {
setcookie( 'top-variation-' . $type . '-' . $test_id . '-' . $page_id, $variation_id, time() + ( 30 * 24 * 3600 ), '/' );
$_COOKIE[ 'top-variation-' . $type . '-' . $test_id . '-' . $page_id ] = $variation_id;
}
public static function get_cookie( $test_id = null, $page_id = null, $type = 1 ) {
return isset( $_COOKIE[ 'top-variation-' . $type . '-' . $test_id . '-' . $page_id ] ) ? $_COOKIE[ 'top-variation-' . $type . '-' . $test_id . '-' . $page_id ] : null;
}
public static function set_impression_cookie( $test_item, $sec = 5 ) {
$cookie_name = 'top-impression-' . $test_item;
$sec = intval( $sec );
setcookie( $cookie_name, $test_item, time() + $sec, '/' );
$_COOKIE[ $cookie_name ] = $test_item;
}
public static function get_impression_cookie( $test_item ) {
$cookie_name = 'top-impression-' . $test_item;
return isset( $_COOKIE[ $cookie_name ] ) ? $_COOKIE[ $cookie_name ] : null;
}
}
return Thrive_AB_Cookie_Manager::instance();

View File

@@ -0,0 +1,440 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Dashboard {
static protected $_instance;
private function __construct() {
$this->_init();
}
/**
* The only point to entry in this class
* and it is instantiated only if the query var is true
*/
public static function instance() {
if ( thrive_ab()->get_query()->get_var( 'thrive-variations' ) !== 'true' ) {
return null;
}
if ( ! current_user_can( 'edit_posts' ) || ! Thrive_AB_Product::has_access() ) {
return null;
}
if ( ! self::$_instance ) {
self::$_instance = new self();
}
if ( function_exists( 'tve_do_not_cache_page' ) ) {
tve_do_not_cache_page();
}
return self::$_instance;
}
private function _clear_scripts() {
global $wp_filter;
remove_all_actions( 'wp_head' );
remove_all_actions( 'wp_footer' );
remove_all_actions( 'wp_enqueue_scripts' );
remove_all_actions( 'wp_print_styles' );
remove_all_actions( 'wp_print_footer_scripts' );
remove_all_actions( 'print_footer_scripts' );
remove_all_actions( 'admin_bar_menu' );
remove_all_filters( 'template_redirect' );
remove_all_filters( 'page_template' );
add_action( 'wp_head', 'wp_enqueue_scripts' );
add_action( 'wp_head', 'wp_print_styles' );
add_action( 'wp_head', 'wp_print_head_scripts' );
add_action( 'wp_head', '_wp_render_title_tag', 1 );
add_action( 'wp_footer', '_wp_footer_scripts' );
add_action( 'wp_footer', 'wp_print_footer_scripts', 20 );
add_action( 'wp_footer', 'print_footer_scripts', 1000 );
}
/**
* Clear the styles and scripts and add required ones
*/
private function _init() {
if ( ! thrive_ab()->license_activated() ) {
return;
}
$this->_clear_scripts();
/**
* Layout
*/
add_filter( 'page_template', array( $this, 'layout' ) );
add_filter( 'home_template', array( $this, 'layout' ) );
add_action( 'template_redirect', array( $this, 'layout' ) );
/**
* Enqueue Scripts
*/
add_action( 'wp_print_footer_scripts', array( $this, 'enqueue_scripts' ) );
/**
* Enqueue Styles
*/
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ), PHP_INT_MAX );
add_action( 'wp_print_footer_scripts', array( $this, 'print_backbone_templates' ) );
add_action( 'wp_print_footer_scripts', 'tve_dash_backbone_templates' );
/**
* Works only if the theme supports title-tag
* Thrive Themes do not support title-tag
*
* @see _wp_render_title_tag
*
*/
add_filter( 'document_title_parts', array( $this, 'get_title' ) );
}
/**
* HTML title to be displayed in AB Dashboard
* Works only if current_theme_supports( 'title-tag' )
*
* @param $title_tags
*
* @return mixed
*/
public function get_title( $title_tags ) {
array_unshift( $title_tags, thrive_ab()->plugin_name() );
return $title_tags;
}
/**
* Specify the template file to be used on dashboard
*
* @return string
*/
public function layout() {
include dirname( __FILE__ ) . '/views/layouts/dashboard.php';
die;
}
/**
* Enqueues the necessary script files for AB Dashboard
*/
public function enqueue_scripts() {
wp_enqueue_script( 'backbone' );
$js_suffix = defined( 'TVE_DEBUG' ) && TVE_DEBUG ? '.js' : '.min.js';
wp_enqueue_script( 'thrive-ab-dashboard', thrive_ab()->url( 'assets/js/dist/app' . $js_suffix ), array(
'backbone',
'jquery-ui-autocomplete',
'tve-dash-main-js',
), Thrive_AB::V, true );
$this->localize_data();
/**
* Enqueue dash js file cos it is needed for Modals, Views and Materialize
*/
tve_dash_enqueue_script( 'tve-dash-main-js', TVE_DASH_URL . '/js/dist/tve-dash.min.js', array(
'jquery',
'backbone',
), false, true );
tve_dash_enqueue_script( 'tve-dash-highcharts', TVE_DASH_URL . '/js/util/highcharts/highcharts.js', array(
'jquery',
), false, true );
tve_dash_enqueue_script( 'tve-dash-highcharts-more', TVE_DASH_URL . '/js/util/highcharts/highcharts-more.js', array(
'jquery',
'tve-dash-highcharts',
), false, true );
}
private function localize_data() {
global $post;
try {
if ( is_home() && 'page' === get_option( 'show_on_front' ) && ( $post = get_option( 'page_on_front' ) ) ) {
$post = get_post( $post );
}
$page = new Thrive_AB_Page( $post );
} catch ( Exception $e ) {
return;
}
$data = array(
'page' => $page->get_data(),
'ajax' => array(
'url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( Thrive_AB_Ajax::NONCE_NAME ),
'action' => Thrive_AB_Ajax::$action,
'controller_action' => Thrive_AB_Ajax::$controller_action,
),
't' => include( thrive_ab()->path( 'includes/i18n.php' ) ),
'chart_colors' => array(
'#20a238',
'#2f82d7',
'#fea338',
'#dd383d',
'#ab31a4',
'#95d442',
'#36c4e2',
'#525252',
'#f3643e',
'#e26edd',
),
);
$test_id = thrive_ab()->get_query()->get_var( 'test-id' );
if ( $test_id ) {
$current_test = $page->get_tests( array(
'id' => $test_id,
), 'obj' );
if ( count( $current_test ) ) {
$current_test = current( $current_test );
}
if ( $current_test instanceof Thrive_AB_Test ) {
if ( thrive_ab()->get_query()->get_var( 'generate-stats' ) ) {
$this->generate_random_stats( 12, $current_test );
}
$current_test->get_items();
$current_test = $current_test->get_data();
}
$data['current_test'] = $current_test;
}
if ( empty( $data['current_test'] ) && $page->get_running_test() instanceof Thrive_AB_Test ) {
$data['running_test'] = $page->get_running_test()->get_data();
} else {
$all_variations = $this->get_variations_for_page( $page );
$data['variations'] = $all_variations['published'];
$data['archived'] = $all_variations['archived'];
}
if ( ! empty( $data['current_test'] ) || ! empty( $data['running_test'] ) ) {
$test_id = ! isset( $test_id ) ? $data['running_test']['id'] : $data['current_test']['id'];
$report_manager = new Thrive_AB_Report_Manager();
$data = array_merge(
$data,
array(
'test_chart' => $report_manager->get_test_chart_data(
array(
'test_id' => (int) $test_id,
'type' => 'conversion_rate',
)
),
)
);
}
$visit_page_monetary = array(
'name' => 'Visit Page',
'label' => __( 'A customer visits certain pages on my site', 'thrive-ab-page-testing' ),
'slug' => 'visit_page',
);
$data['monetary_services'][ $visit_page_monetary['slug'] ] = $visit_page_monetary;
$data['monetary_services'] = apply_filters( 'thrive_ab_monetary_services', $data['monetary_services'] );
$data['license'] = Thrive_AB::license_data();
wp_localize_script( 'thrive-ab-dashboard', 'ThriveAB', $data );
}
/**
* Generate event logs for a test
*
* @param $days int
* @param $test Thrive_AB_Test
*
* @throws
*/
protected function generate_random_stats( $days, $test ) {
$days = intval( $days );
if ( $days <= 0 || $days > 100 || ! ( $test instanceof Thrive_AB_Test ) ) {
return;
}
$variation_ids = array();
$variation_items = array();
$test_items = $test->get_items();
/** @var Thrive_AB_Test_Item $test_item */
foreach ( $test_items as $test_item ) {
$variation_ids[] = $test_item->variation_id;
$variation_items[ $test_item->variation_id ] = $test_item;
}
$goal_page = null;
$goal_page_ids = array_keys( $test->goal_pages );
$goal_pages = $test->goal_pages;
if ( count( $goal_page_ids ) === 1 ) {
$goal_page = $goal_pages[ $goal_page_ids[0] ];
} else {
$step = 1000;
$index = (int) rand( 0, count( $goal_page_ids ) * $step );
$goal_page = $goal_pages[ $goal_page_ids[ $index ] ];
}
/**
* Loop through dates
*/
for ( $d = $days; $d > 0; $d -- ) {
$date = date( 'Y-m-d H:i:s', time() - ( $d * 60 * 60 * 24 ) );
/**
* loop variations
*/
foreach ( $variation_ids as $variation_id ) {
$test_item = $variation_items[ $variation_id ];
$step = 1000;
$total_impressions = rand( 0, 30 * $step );
$total_impressions = intval( $total_impressions / $step );
$total_conversions = rand( 0, $total_impressions * $step );
$total_conversions = intval( $total_conversions / $step );
$event_model = array(
'page_id' => $test->page_id,
'variation_id' => $variation_id,
'test_id' => $test->id,
'date' => $date,
);
/**
* log impressions
*/
for ( $i = 0; $i < $total_impressions; $i ++ ) {
$impression = $event_model;
$impression['event_type'] = 1;
$event_log = new Thrive_AB_Event( $impression );
$event_log->save();
$test_item->impressions ++;
$test_item->unique_impressions ++;
}
/**
* log conversions
*/
for ( $c = 0; $c < $total_conversions; $c ++ ) {
$conversion = $event_model;
$conversion['event_type'] = 2;
$conversion['revenue'] = isset( $goal_page['revenue'] ) ? $goal_page['revenue'] : 0;
$conversion['goal_page'] = isset( $goal_page['post_id'] ) ? $goal_page['post_id'] : null;
$event_log = new Thrive_AB_Event( $conversion );
$event_log->save();
$test_item->conversions ++;
$test_item->revenue = $test_item->revenue + ( isset( $goal_page['revenue'] ) ? $goal_page['revenue'] : 0 );
}
$test_item->save();
if ( $d === $days ) {
$test->date_started = $date;
$test->save();
}
}
}
}
/**
* If the page does not have any variations automatically creates a new once as control
* On failure of creating the control variation empty array of variations is returned
*
* @param $page Thrive_AB_Page
*
* @return array
*/
public function get_variations_for_page( $page ) {
$result = array(
'published' => array(),
'archived' => array(),
'deleted' => array(),
);
try {
$variations = $page->get_variations( array( 'all' => true ) );
foreach ( $variations as $variation ) {
$variation_object = new Thrive_AB_Variation( (int) $variation['ID'] );
$meta = $variation_object->get_meta();
$variation['status'] = $meta->get( 'status' );
if ( isset( $result[ $variation['status'] ] ) ) {
array_push( $result[ $variation['status'] ], $variation );
}
}
} catch ( Exception $e ) {
die( $e );
}
return $result;
}
/**
* Enqueue css files used on Dashboard
*/
public function enqueue_styles() {
/**
* Inherit CSS from dashboard
*/
tve_dash_enqueue_style( 'tve-dash-styles-css', TVE_DASH_URL . '/css/styles.css' );
wp_enqueue_style( 'thrive-ab', thrive_ab()->url( 'assets/css/dashboard.css' ), array(
'tve-dash-styles-css',
), Thrive_AB::V );
}
/**
* Echoes in HTML the backbone templates used on Dashboard
* Uses Thrive Dashboard functions
*/
public function print_backbone_templates() {
$templates = tve_dash_get_backbone_templates( thrive_ab()->path( 'includes/views/backbone' ), 'backbone' );
tve_dash_output_backbone_templates( $templates );
}
}

View File

@@ -0,0 +1,147 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_AB_Editor
*
* Should work only in TAr Edit Mode
*/
class Thrive_AB_Editor {
protected static $_instance;
/**
* @var WP_Post
*/
protected $_post;
private function __construct( $post ) {
$this->_post = $post;
add_action( 'tcb_sidebar_extra_links', array( $this, 'render_buttons' ) );
add_action( 'tcb_main_frame_enqueue', array( $this, 'enqueue' ) );
add_action( 'tcb_has_templates_tab', array( __CLASS__, 'has_templates_tab' ), 10, 1 );
add_action( 'tcb_can_use_landing_pages', array( __CLASS__, 'can_use_landing_pages' ), 10, 1 );
add_filter( 'tcb_main_frame_localize', array( 'Thrive_AB_Ajax', 'localize' ) );
/**
* Includes the modal template files
*/
add_filter( 'tcb_modal_templates', array( __CLASS__, 'include_modal_files' ), 10, 1 );
}
/**
* Init the AB_Editor based on current post type
* and returns the instance if post type is allowed
*
* @return null|Thrive_AB_Editor
*/
public static function init() {
$post = get_post();
if ( ! thrive_ab()->is_cpt_allowed( $post->post_type ) && $post->post_type !== Thrive_AB_Post_Types::VARIATION ) {
return null;
}
if ( ! self::$_instance ) {
self::$_instance = new self( $post );
}
return self::$_instance;
}
public static function include_modal_files( $files = array() ) {
$files[] = thrive_ab()->path( 'includes/views/backbone/editor-modals/reset-stats.php' );
return $files;
}
public static function has_templates_tab( $has ) {
global $post;
if ( $post->post_type === Thrive_AB_Post_Types::VARIATION ) {
$has = true;
}
return $has;
}
public static function can_use_landing_pages( $can ) {
global $post;
if ( $post->post_type === Thrive_AB_Post_Types::VARIATION ) {
$can = true;
}
return $can;
}
/**
* Echoes the html buttons on the top sidebar of TAr Editor
*/
public function render_buttons() {
$html = '';
$page_id = thrive_ab()->maybe_variation( $this->_post ) ? $this->_post->post_parent : $this->_post->ID;
$test_manager = new Thrive_AB_Test_Manager();
$test = $test_manager->get_running_test( $page_id );
if ( $test ) {
$test_url = Thrive_AB_Test_Manager::get_test_url( $test->id );
ob_start();
include 'views/editor/html-running-test-button.php';
$html = ob_get_clean();
} elseif ( thrive_ab()->maybe_variation( $this->_post ) ) {
ob_start();
include 'views/editor/html-variation-button.php';
$html = ob_get_clean();
} elseif ( thrive_ab()->is_cpt_allowed( $this->_post->post_type ) && Thrive_AB_Product::has_access() ) {
ob_start();
include 'views/editor/html-buttons.php';
$html = ob_get_clean();
}
echo $html;
}
/**
* Enqueues the required styles and scripts for TAr Editor
*/
public function enqueue() {
/**
* scripts
*/
wp_enqueue_script( 'thrive-ab-testing-editor-script', plugin_dir_url( THRIVE_AB_PLUGIN_FILE ) . 'assets/js/dist/editor.min.js', array( 'tve-main' ), Thrive_AB::V, true );
/**
* styles
*/
wp_enqueue_style( 'thrive-ab-testing-editor-style', plugin_dir_url( THRIVE_AB_PLUGIN_FILE ) . 'assets/css/editor.css', array( 'tve2_editor_style' ), Thrive_AB::V );
}
public function get_dashboard_url() {
if ( ! thrive_ab()->license_activated() ) {
return admin_url( 'admin.php?page=tve_dash_section' );
}
$is_variation = $this->_post->post_type === Thrive_AB_Post_Types::VARIATION || $this->_post->post_status === Thrive_AB_Post_Status::VARIATION;
$url = get_permalink( $is_variation ? $this->_post->post_parent : $this->_post );
$url = add_query_arg( 'thrive-variations', 'true', $url );
return $url;
}
}

View File

@@ -0,0 +1,185 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 11/14/2017
* Time: 2:00 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
/**
* Class Thrive_AB_Meta_Box_Completed_Tests_Table
*/
class Thrive_AB_Meta_Box_Completed_Tests_Table extends WP_List_Table {
/**
* @var Thrive_AB_Page
*/
private $_page;
private $_page_tests = array();
private $_items_per_page = 100;
/**
* Thrive_AB_Meta_Box_Completed_Tests_Table constructor.
*
* @param $page Thrive_AB_Page
*/
public function __construct( $page ) {
$this->_page = $page;
$this->_page_tests = $this->_page->get_tests( array( 'status' => 'completed' ), 'instance' );
parent::__construct( array(
'singular' => 'thrive-ab-completed-test', //singular name of the listed records
'plural' => 'thrive-ab-completed-tests', //plural name of the listed records
'ajax' => false,
) );
}
/** Text displayed when no customer data is available */
public function no_items() {
echo __( 'There are no Thrive A/B Completed Tests for this page', 'thrive-ab-page-testing' );
}
/**
* Override the parent columns method. Defines the columns to use in your listing table
*
* @return array
*/
public function get_columns() {
$columns = array(
'title' => __( 'Completed Test', 'thrive-ab-page-testing' ),
'notes' => __( 'Description', 'thrive-ab-page-testing' ),
'date_started' => __( 'Start Date', 'thrive-ab-page-testing' ),
'date_completed' => __( 'End Date', 'thrive-ab-page-testing' ),
'view_test' => '',
'delete_test' => '',
);
return $columns;
}
/**
* Define which columns are hidden
*
* @return array
*/
public function get_hidden_columns() {
return array();
}
/**
* Define the sortable columns
*
* @return array
*/
public function get_sortable_columns() {
return array();
}
/**
* Get the table data
*
* @return array
*/
private function table_data() {
$data = array();
/**@var $test Thrive_AB_Test */
foreach ( $this->_page_tests as $test ) {
$tmp = $test->get_data();
$time_started = strtotime( $tmp['date_started'] );
$time_completed = strtotime( $tmp['date_completed'] );
$delete_href = sprintf( admin_url( 'admin.php?action=%s&ab_test_ID=%s&post_ID=%s' ), 'thrive-ab-tests-delete', absint( $tmp['id'] ), absint( $tmp['page_id'] ) );
$preview_link = '<a href="' . $this->_page->get_test_link( $test->id ) . '">' . tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-edit-post-icons' ) . ' ' . __( 'View Test', 'thrive-ab-page-testing' ) . '</a>';
$delete_link = '<a href="' . $delete_href . '">' . tcb_icon( 'trash-o', true, 'sidebar', 'thrive-ab-edit-post-icons' ) . ' ' . __( 'Delete', 'thrive-ab-page-testing' ) . '</a>';
$tmp['view_test'] = $preview_link;
$tmp['delete_test'] = $delete_link;
$tmp['date_started'] = $time_started ? date( 'd-m-Y', $time_started ) : '';
$tmp['date_completed'] = $time_completed ? date( 'd-m-Y', $time_completed ) : '';
$data[] = $tmp;
}
return $data;
}
/**
* Prepare the items for the table to process
*
* @return Void
*/
public function prepare_items() {
$columns = $this->get_columns();
$hidden = $this->get_hidden_columns();
$sortable = $this->get_sortable_columns();
$data = $this->table_data();
$per_page = $this->_items_per_page;
$current_page = $this->get_pagenum();
$total_items = count( $data );
$this->set_pagination_args( array(
'total_items' => $total_items,
'per_page' => $per_page,
) );
$data = array_slice( $data, ( ( $current_page - 1 ) * $per_page ), $per_page );
$this->_column_headers = array( $columns, $hidden, $sortable );
$this->items = $data;
}
/**
* Override the parent display method. Defines the HTML content for your listing table
*
* @since 3.1.0
* @access public
*/
public function display() {
$singular = $this->_args['singular'];
$this->screen->render_screen_reader_content( 'heading_list' );
include dirname( __FILE__ ) . '/views/admin/edit-post/tests-table.php';
}
/**
* Define what data to show on each column of the table
*
* @param array $item Data
* @param String $column_name - Current column name
*
* @return Mixed
*/
public function column_default( $item, $column_name ) {
$value = '';
if ( ! empty( $item[ $column_name ] ) ) {
$value = $item[ $column_name ];
}
return $value;
}
/**
* Get a list of CSS classes for the WP_List_Table table tag.
*
* @since 3.1.0
*
* @return array List of CSS classes for the table tag.
*/
public function get_table_classes() {
$classes = array_diff( parent::get_table_classes(), array( 'striped' ) );
return $classes;
}
}

View File

@@ -0,0 +1,391 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 11/13/2017
* Time: 4:32 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
/**
* Class Thrive_AB_Meta_Box_Variations_Table
*/
class Thrive_AB_Meta_Box_Variations_Table extends WP_List_Table {
/**
* @var Thrive_AB_Page
*/
private $_page;
private $_variations_ins = array();
private $_page_tests = array();
private $_table_has_no_test_class = 'thrive-ab-variation-no-test';
private $_variations_per_page = 100;
/**
* Thrive_AB_Meta_Box_Variations_Table constructor.
*
* @param $page Thrive_AB_Page
*/
public function __construct( $page ) {
$this->_page = $page;
$this->_page_tests = $this->_page->get_tests( array( 'status' => 'running' ) );
$this->_variations_ins = $this->_page->get_variations( array(), 'instance' );
parent::__construct( array(
'singular' => 'thrive-ab-variation', //singular name of the listed records
'plural' => 'thrive-ab-variations', //plural name of the listed records
'ajax' => false,
) );
}
/**
* Prepare the items for the table to process
*
* @return Void
*/
public function prepare_items() {
$columns = $this->get_columns();
$hidden = $this->get_hidden_columns();
$sortable = $this->get_sortable_columns();
$data = $this->_variations_ins;
$per_page = $this->_variations_per_page;
$current_page = $this->get_pagenum();
$total_items = count( $data );
$this->set_pagination_args( array(
'total_items' => $total_items,
'per_page' => $per_page,
) );
$data = array_slice( $data, ( ( $current_page - 1 ) * $per_page ), $per_page );
$this->_column_headers = array( $columns, $hidden, $sortable );
$this->items = $data;
}
/**
* Override the parent columns method. Defines the columns to use in your listing table
*
* @return array
*/
public function get_columns() {
$columns = array(
'post_title' => __( 'Name', 'thrive-ab-page-testing' ),
'traffic' => __( 'Traffic', 'thrive-ab-page-testing' ),
'impressions' => __( 'Unique Visitors', 'thrive-ab-page-testing' ),
'conversions' => __( 'Conversions', 'thrive-ab-page-testing' ),
'conversions_rate' => __( 'Conversions Rate', 'thrive-ab-page-testing' ),
'revenue' => __( 'Revenue', 'thrive-ab-page-testing' ),
'revenue_visitor' => __( 'Revenue per visitor', 'thrive-ab-page-testing' ),
'improvement' => __( 'Improvement', 'thrive-ab-page-testing' ),
'chance_to_beat_orig' => __( 'Chance to Beat Original', 'thrive-ab-page-testing' ),
);
if ( is_array( $this->_page_tests ) && count( $this->_page_tests ) && $this->_page_tests[0]['type'] === 'optins' ) {
$columns['conversions'] = __( 'Subscriptions', 'thrive-ab-page-testing' );
$columns['conversions_rate'] = __( 'Subscriptions Rate', 'thrive-ab-page-testing' );
}
return $columns;
}
/** Text displayed when no customer data is available */
public function no_items() {
echo __( 'There are no Thrive A/B Test variations for this page', 'thrive-ab-page-testing' );
}
/**
* Get a list of CSS classes for the WP_List_Table table tag.
*
* @since 3.1.0
*
* @return array List of CSS classes for the table tag.
*/
public function get_table_classes() {
$classes = parent::get_table_classes();
if ( count( $this->_page_tests ) === 0 ) {
$classes[] = $this->_table_has_no_test_class;
}
$classes = array_diff( $classes, array( 'striped' ) );
return $classes;
}
/**
* Define which columns are hidden
*
* @return array
*/
public function get_hidden_columns() {
$return = array( 'conversions', 'conversions_rate' );
$running_tests = count( $this->_page_tests );
if ( $running_tests === 0 || $running_tests > 0 && ( $this->_page_tests[0]['type'] === 'visits' || $this->_page_tests[0]['type'] === 'optins' ) ) {
$return = array( 'revenue', 'revenue_visitor' );
}
return $return;
}
/**
* Define what data to show on each column of the table
*
* @param array $item Data
* @param String $column_name - Current column name
*
* @return Mixed
*/
public function column_default( $item, $column_name ) {
$value = '';
if ( isset( $item[ $column_name ] ) ) {
$value = $item[ $column_name ];
}
return $value;
}
/**
* Define the sortable columns
*
* @return array
*/
public function get_sortable_columns() {
return array();
}
/**
* Generates content for a single row of the table
*
* @since 3.1.0
*
* @param object $item The current item
*/
public function single_row( $item ) {
if ( (int) $item->get_test_item()->active === 1 ) {
echo '<tr>';
$this->single_row_columns( $item );
echo '</tr>';
}
}
/**
* Override the parent display method. Defines the HTML content for your listing table
*
* @since 3.1.0
* @access public
*/
public function display() {
$singular = $this->_args['singular'];
$this->screen->render_screen_reader_content( 'heading_list' );
include dirname( __FILE__ ) . '/views/admin/edit-post/variations-table.php';
}
/**
* Returns Basic HTML for a column
*
* @param $classes
* @param $data
*
* @return string
*/
private function _column_template( $classes, $data ) {
$html = '';
$html .= "<td class='$classes' $data>";
$html .= '%s';
$html .= '</td>';
return $html;
}
/**
* @param $item Thrive_AB_Variation
* @param $classes
* @param $data
* @param $primary
*
* @return string
*/
public function _column_post_title( $item, $classes, $data, $primary ) {
$html = $this->_column_template( $classes, $data );
$edit_link = '';
// if ( count( $this->_page_tests ) === 0 ) {
$edit_link .= '&nbsp;&nbsp;';
$edit_link .= '<a href="' . $item->get_editor_url() . '" target="_blank" class="top-edit-icon">' . tcb_icon( 'pencil', true, 'sidebar', 'thrive-ab-edit-post-icons' ) . '</a>';
// }
$preview_link = '<a href="' . $item->get_preview_url() . '" target="_blank">' . tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-edit-post-icons' ) . '</a>';
$post_title = '<span>' . $item->post_title . '</span>&nbsp;' . $preview_link . '' . $edit_link;
return sprintf( $html, $post_title );
}
/**
* @param $item Thrive_AB_Variation
* @param $classes
* @param $data
* @param $primary
*
* @return string
*/
public function _column_traffic( $item, $classes, $data, $primary ) {
$html = $this->_column_template( $classes, $data );
$traffic = $item->get_traffic();
$item_data = $item->get_data();
$range = sprintf( '<input class="thrive-ab-traffic-input" id="thrive-ab-traffic-range-%s" type="range" min="0" max="100" step="1" value="%s" data-tab_variation_value="%s" data-tab_variation_id="%s" />', $item_data['ID'], $traffic, $traffic, $item_data['ID'] );
$input = sprintf( '<input class="thrive-ab-traffic-input" id="thrive-ab-traffic-input-%s" type="number" min="0" max="100" value="%s" data-tab_variation_value="%s" data-tab_variation_id="%s" />', $item_data['ID'], $traffic, $traffic, $item_data['ID'] );
$traffic_html = '<div class="thrive-ab-edit-post-traffic-holder"><div class="thrive-ab-edit-post-slider-holder">' . $range . '</div><div class="thrive-ab-edit-post-input-holder">' . $input . '</div></div>';//%
return sprintf( $html, $traffic_html );
}
/**
* Handles the impressions column content
*
* @param $item Thrive_AB_Variation
* @param $classes
* @param $data
* @param $primary
*
* @return string
*/
public function _column_impressions( $item, $classes, $data, $primary ) {
$html = $this->_column_template( $classes, $data );
return sprintf( $html, $item->get_test_item()->get_impressions() );
}
/**
* Handles the conversions column content
*
* @param $item Thrive_AB_Variation
* @param $classes
* @param $data
* @param $primary
*
* @return string
*/
public function _column_conversions( $item, $classes, $data, $primary ) {
$html = $this->_column_template( $classes, $data );
return sprintf( $html, $item->get_test_item()->get_conversions() );
}
/**
* Handles the conversions_rate column content
*
* @param $item Thrive_AB_Variation
* @param $classes
* @param $data
* @param $primary
*
* @return string
*/
public function _column_conversions_rate( $item, $classes, $data, $primary ) {
$html = $this->_column_template( $classes, $data );
return sprintf( $html, $item->get_test_item()->conversion_rate() . '%' );
}
/**
* Handles the revenue column content
*
* @param $item Thrive_AB_Variation
* @param $classes
* @param $data
* @param $primary
*
* @return string
*/
public function _column_revenue( $item, $classes, $data, $primary ) {
$html = $this->_column_template( $classes, $data );
return sprintf( $html, $item->get_test_item()->revenue );
}
/**
* Handles the revenue_visitor column content
*
* @param $item Thrive_AB_Variation
* @param $classes
* @param $data
* @param $primary
*
* @return string
*/
public function _column_revenue_visitor( $item, $classes, $data, $primary ) {
$html = $this->_column_template( $classes, $data );
$value = $item->get_test_item()->revenue_per_visitor();
return sprintf( $html, $value );
}
/**
* Handles the improvement column content if current item is control
*
* @param $item Thrive_AB_Variation
* @param $classes
* @param $data
* @param $primary
*
* @return string
*/
public function _column_improvement( $item, $classes, $data, $primary ) {
$html = '';
if ( $item->is_control() ) {
$classes .= ' thrv-ab-variation-control';
$html .= "<td class='$classes' $data colspan='2'>[ " . __( 'This is the control', 'thrive-ab-page-testing' ) . ' ]</td>';
echo $html;
return;
}
$improvement = $item->get_test_item()->get_improvement();
$classes .= $improvement < 0 ? ' thrive-ab-red' : ' thrive-ab-green';
$html = $this->_column_template( $classes, $data );
return sprintf( $html, $improvement . '%' );
}
/**
* Handles the chance_to_beat_orig column content if current item is control
*
* @param $item Thrive_AB_Variation
* @param $classes
* @param $data
* @param $primary
*
* @return string
*/
public function _column_chance_to_beat_orig( $item, $classes, $data, $primary ) {
if ( $item->is_control() ) {
return;
}
$chance = $item->get_test_item()->get_chance_to_beat_original();
$classes .= $chance < 0 ? ' thrive-ab-red' : ' thrive-ab-green';
$html = $this->_column_template( $classes, $data );
return sprintf( $html, $chance . '%' );
}
}

View File

@@ -0,0 +1,188 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 11/13/2017
* Time: 12:58 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_AB_Meta_Box
*/
class Thrive_AB_Meta_Box {
private static $_instance;
private $_page;
/**
* @var int
*/
private $_completed_tests_number = 0;
/**
* Thrive_AB_Meta_Box constructor.
*/
private function __construct() {
add_action( 'load-post.php', array( $this, 'add_meta_logic' ) );
add_action( 'admin_init', array( $this, 'meta_box_request_handler' ) );
add_action( 'admin_footer', array( $this, 'include_additional_files' ) );
}
/**
* Checks the post type to be compatible with the plugin post type
*/
public function add_meta_logic() {
if ( empty( $_GET['post'] ) || ! thrive_ab()->is_cpt_allowed( get_post_type( $_GET['post'] ) ) ) {
return;
}
if ( ! isset( $_GET['action'] ) || $_GET['action'] !== 'edit' ) {
return;
}
$this->_page = new Thrive_AB_Page( (int) $_GET['post'] );
$variations = $this->_page->get_variations();
$completed_tests = $this->_page->get_tests( array( 'status' => 'completed' ), 'instance' );
if ( count( $variations ) >= 2 ) {
add_action( 'add_meta_boxes', array( $this, 'add_variation_table_meta_box' ) );
}
$this->_completed_tests_number = count( $completed_tests );
if ( $this->_completed_tests_number >= 1 ) {
add_action( 'add_meta_boxes', array( $this, 'add_completed_tests_table_meta_box' ) );
}
/**
* Enqueue Meta Box Scripts
*/
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_meta_box_scripts' ) );
}
/**
* Adds Scripts to the Meta Box Screen
*
* @param $hook
*/
public function enqueue_meta_box_scripts( $hook ) {
thrive_ab()->enqueue_style( 'thrive-ab-testing-edit-post', plugin_dir_url( THRIVE_AB_PLUGIN_FILE ) . 'assets/css/edit-post.css' );
thrive_ab()->enqueue_script( 'thrive-ab-testing-edit-post', plugin_dir_url( THRIVE_AB_PLUGIN_FILE ) . 'assets/js/dist/edit-post.min.js', array( 'jquery' ) );
wp_localize_script( 'thrive-ab-testing-edit-post', 'ThriveAbEditPost', $this->get_localization() );
}
/**
* Localization variables for Edit Post View
*
* @return array
*/
public function get_localization() {
return array(
'ajax' => array(
'url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( Thrive_AB_Ajax::NONCE_NAME ),
'action' => Thrive_AB_Ajax::$action,
'controller_action' => Thrive_AB_Ajax::$controller_action,
),
);
}
public function meta_box_request_handler() {
if ( ! empty( $_REQUEST['action'] ) && $_REQUEST['action'] === 'thrive-ab-tests-delete' ) {
Thrive_AB_Test_Manager::delete_test( array(
'id' => $_REQUEST['ab_test_ID'],
'page_id' => $_REQUEST['post_ID'],
) );
$return_url = get_edit_post_link( $_REQUEST['post_ID'], '' );
wp_redirect( $return_url );
exit;
}
}
/**
* Includes svg icons to editor page
*/
public function include_additional_files() {
if ( empty( $_GET['post'] ) || ! thrive_ab()->is_cpt_allowed( get_post_type( $_GET['post'] ) ) ) {
return;
}
if ( ! isset( $_GET['action'] ) || $_GET['action'] !== 'edit' ) {
return;
}
include dirname( __FILE__ ) . '/../assets/fonts/icons.svg';
}
public static function instance() {
if ( ! self::$_instance ) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Adds The Variations Meta Box to the screen
*/
public function add_variation_table_meta_box() {
add_meta_box(
'thrive_ab_test_variation_table_meta_box',
__( 'Thrive Optimize - A/B Test Overview', 'thrive-ab-page-testing' ),
array( $this, 'show_variation_table_meta_box' ),
$this->_page->post_type,
'normal',
'high'
);
}
/**
* Adds the Tests Meta Box to the screen
*/
public function add_completed_tests_table_meta_box() {
add_meta_box(
'thrive_ab_test_completed_tests_table_meta_box',
__( 'Thrive Completed A/B Tests', 'thrive-ab-page-testing' ) . ' (' . $this->_completed_tests_number . ')',
array( $this, 'show_completed_tests_table_meta_box' ),
$this->_page->post_type,
'normal',
'high'
);
}
/**
* Callback for variation meta box function
*/
public function show_variation_table_meta_box() {
require_once 'class-thrive-ab-meta-box-variations-table.php';
$variations_table = new Thrive_AB_Meta_Box_Variations_Table( $this->_page );
$variations_table->prepare_items();
$variations_table->display();
}
/**
* Callback for tests meta box function
*/
public function show_completed_tests_table_meta_box() {
require_once 'class-thrive-ab-meta-box-completed-tests-table.php';
$completed_tests_table = new Thrive_AB_Meta_Box_Completed_Tests_Table( $this->_page );
$completed_tests_table->prepare_items();
$completed_tests_table->display();
}
}
Thrive_AB_Meta_Box::instance();

View File

@@ -0,0 +1,347 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_AB_Meta
*
* Wrapper upon sets of metas
*
* Use this for posts before deleting the post because the WP deletes the meta and then the post;
*/
class Thrive_AB_Meta {
const PREFIX = 'thrive_ab_';
protected $_post_id;
protected $_meta = array();
protected $_variation_prefix = 'thrive_ab_';
private $_meta_types
= array(
'page',
'template',
'variation',
);
public function __construct( $post_id ) {
$this->_post_id = $post_id;
}
/**
* @return array with meta keys
*/
public function page_meta() {
return array(
'tve_landing_page',
'thrv_lp_template_colours', // Template Colors
'thrv_lp_template_gradients', // Template Gradients
'thrv_lp_template_button', // Template Button Styles
'thrv_lp_template_section', // Template Section Styles
'thrv_lp_template_contentbox', // Template ContentBox Styles
'thrv_lp_template_palettes', // Template Palettes
'tve_globals',
'thrive_tcb_post_fonts',
'tve_page_events',
'thrive_icon_pack',
'tve_has_masonry',
'tve_has_typefocus',
'tve_has_wistia_popover',
'tve_content_before_more',
'tve_updated_post',
'tve_content_more_found',
'tve_custom_css',
'tve_user_custom_css',
//set for landing page but with no tpl suffix
'tve_global_scripts',
'tve_disable_theme_dependency',
'_tve_header',
'_tve_footer',
//template
'thrive_post_template'
);
}
/**
* @return array with meta keys that have template name as suffix
*/
public function template_meta() {
return array(
'thrive_icon_pack',
'thrive_tcb_post_fonts',
'tve_content_before_more',
'tve_content_more_found',
'tve_custom_css',
'tve_globals',
'tve_has_masonry',
'tve_has_typefocus',
'tve_has_wistia_popover',
'tve_page_events',
'tve_updated_post',
'tve_user_custom_css',
);
}
public function variation_meta() {
return array(
'traffic',
'status',
'running_test_id',
);
}
public function get_thrive_theme_meta() {
if ( function_exists( '_thrive_get_meta_fields' ) ) {
return _thrive_get_meta_fields( 'post' ); //dono why the heck is post ? :)
}
$meta = array(
'thrive_meta_show_post_title',
'thrive_meta_post_breadcrumbs',
'thrive_meta_post_featured_image',
'thrive_meta_post_header_scripts',
'thrive_meta_post_body_scripts',
'thrive_meta_post_body_scripts_top',
'thrive_meta_post_custom_css',
'thrive_meta_post_share_buttons',
'thrive_meta_post_floating_icons',
'thrive_meta_social_data_title',
'thrive_meta_social_data_description',
'thrive_meta_social_image',
'thrive_meta_social_twitter_username',
'thrive_meta_post_focus_area_top',
'thrive_meta_post_focus_area_bottom',
);
return $meta;
}
/**
* if the key is not in local array then read it from db
*
* @param $key
*
* @return mixed
*/
public function get( $key ) {
if ( in_array( $key, $this->template_meta() ) ) {
$this->_meta[ $key ] = tve_get_post_meta( $this->_post_id, $key );
} elseif ( in_array( $key, $this->variation_meta() ) ) {
$this->_meta[ $key ] = get_post_meta( $this->_post_id, $this->_variation_prefix . $key, true );
} else {
$this->_meta[ $key ] = get_post_meta( $this->_post_id, $key, true );
}
if ( method_exists( $this, $key ) ) {
return call_user_func( array( $this, $key ) );
}
return $this->_meta[ $key ];
}
/**
* Gets current post meta tve_disable_theme_dependency and covert into int
* - set it into local _meta[] array
*
* @return int
*/
public function tve_disable_theme_dependency() {
$value = (int) get_post_meta( $this->_post_id, 'tve_disable_theme_dependency', true );
$this->_meta['tve_disable_theme_dependency'] = $value;
return $value;
}
/**
* Update the DB and the local value
*
* @param $key
* @param $value
*
* @return mixed
*/
public function update( $key, $value ) {
$this->_meta[ $key ] = $value;
if ( in_array( $key, $this->template_meta() ) ) {
return tve_update_post_meta( $this->_post_id, $key, $value );
}
if ( in_array( $key, $this->variation_meta() ) ) {
return update_post_meta( $this->_post_id, 'thrive_ab_' . $key, $value );
}
return update_post_meta( $this->_post_id, $key, $value );
}
public function init( $types ) {
if ( is_string( $types ) ) {
$types = array( $types );
}
$keys = array();
if ( is_array( $types ) && ! empty( $types ) ) {
foreach ( $types as $type ) {
if ( ! in_array( $type, $this->_meta_types ) ) {
continue;
}
$method = $type . '_meta';
if ( method_exists( $this, $method ) ) {
$keys = array_merge( $keys, call_user_func( array( $this, $method ) ) );
}
}
}
foreach ( $keys as $key ) {
$this->get( $key );
}
return $this;
}
public function copy_to( $post_id ) {
$new_meta = new Thrive_AB_Meta( $post_id );
foreach ( $this->_meta as $key => $value ) {
$new_meta->update( $key, $value );
}
return $new_meta;
}
/**
* Copy thrive themes page options to a variation
*
* @param $variation_id
*
* @return $this
*/
public function copy_thrive_theme_meta( $variation_id ) {
$meta = $this->get_thrive_theme_meta();
foreach ( $meta as $key ) {
$key = '_' . $key;
$value = get_post_meta( $this->_post_id, $key, true );
update_post_meta( $variation_id, $key, $value );
}
return $this;
}
/**
* Copy non thrive post meta to variations
*
* @param $post_id
*
* @return $this
*/
public function copy_non_thrive_meta( $post_id ) {
$theme_metas = get_post_meta( $this->_post_id );
if ( is_array( $theme_metas ) && ! empty( $theme_metas ) ) {
foreach ( $theme_metas as $key => $value ) {
if ( $this->maybe_thrive_meta( $key ) ) {
continue;
} else {
update_post_meta( $post_id, $key, maybe_unserialize( $value[0] ) );
}
}
}
return $this;
}
/**
* Remove unused meta of variantion if it was deleted from parent
*
* @param $post_id
*
* @return $this
*/
public function removed_unused_non_thrive_meta( $post_id ) {
if ( get_post_meta( $post_id, '_thumbnail_id' ) && ! get_post_meta( $this->_post_id, '_thumbnail_id' ) ) {
delete_post_meta( $post_id, '_thumbnail_id' );
}
return $this;
}
/**
* Check if the key contains any of the thrive prefixes
*
* @param $key
*
* @return bool true if contains any prefix which means it is a thrive meta key
*/
public function maybe_thrive_meta( $key ) {
preg_match( '/(thrive)|(tcb)|(tve)|(is_control)/', $key, $matches );
return ! empty( $matches );
}
public function get_data() {
return $this->_meta;
}
public function is_control() {
return $this->_meta['is_control'] == 1;//we should have prefixed that
}
public function get_variation_prefix() {
return $this->_variation_prefix;
}
public static function hooks() {
$instance = new self( null );
add_filter( 'is_protected_meta', array( $instance, 'is_protected' ), 10, 2 );
}
public function is_protected( $is_protected, $meta_key ) {
$variation_metas = $this->variation_meta();
foreach ( $variation_metas as $key ) {
if ( $this->_variation_prefix . $key === $meta_key || $meta_key === 'is_control' ) {
$is_protected = true;
}
}
return $is_protected;
}
}
return Thrive_AB_Meta::hooks();

View File

@@ -0,0 +1,216 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
abstract class Thrive_AB_Model {
/**
* @var wpdb
*/
protected $wpdb;
/**
* @var array associative which has indexes columns from DB
*/
protected $_data;
/**
* Thrive_AB_Model constructor.
* If model is int then a db request is made and _data is initialized
*
* @param array|int $model of data to be save in DB
*/
public function __construct( $model = array() ) {
global $wpdb;
$this->wpdb = $wpdb;
$defaults = $this->_get_default_data();
if ( ! is_array( $model ) && is_int( $model ) ) {
$this->id = $model;
$model = array( 'id' => $model );
$this->init();
$model = array_merge( $model, $this->_data );
}
$this->_data = array_merge( $defaults, $model );
}
/**
* Magic call of prop from _data
*
* @param $key
*
* @return mixed|null
*/
public function __get( $key ) {
if ( method_exists( $this, $key ) ) {
$value = call_user_func( array( $this, $key ) );
} else {
$value = isset( $this->_data[ $key ] ) ? $this->_data[ $key ] : null;
}
return $value;
}
/**
* Magic setter
*
* @param $key
* @param $value
*
* @return mixed
*/
public function __set( $key, $value ) {
if ( method_exists( $this, 'set_' . $key ) ) {
return call_user_func( array( $this, 'set_' . $key ), $value );
}
$this->_data[ $key ] = $value;
return $this->_data[ $key ];
}
/**
* Read from DB the row with id
*
* id prop has to exists in $this->_data
*
* @throws Exception
* @return $this
*/
public function init() {
if ( ! $this->id ) {
throw new Exception( __( 'Invalid model id', 'thrive-ab-page-testing' ) );
}
$data = $this->wpdb->get_row( 'SELECT * FROM ' . $this->_table_name() . ' WHERE id = ' . $this->id, ARRAY_A );
if ( ! empty( $data ) ) {
foreach ( $data as $key => $value ) {
$this->$key = $value;
}
}
return $this;
}
/**
* Based on what exists in $this->_data insert or update the DB
*
* @return $this
* @throws Exception if model is not valid or is not saved in DB
*/
public function save() {
if ( ! $this->is_valid() ) {
throw new Exception( __( sprintf( 'Invalid model %s with data: %s', get_class( $this ), var_export( $this->_data, true ) ), 'thrive-ab-page-testing' ) );
}
$data = $this->_prepare_data();
if ( isset( $data['unique'] ) ) {
unset( $data['unique'] );
}
if ( $this->id ) {
$saved = $this->wpdb->update( $this->_table_name(), $data, array( 'id' => $this->id ) );
} else {
$saved = $this->wpdb->insert( $this->_table_name(), $data );
}
if ( is_wp_error( $saved ) || $saved === false ) {
throw new Exception( __( 'Model could not be saved', 'thrive-ab-page-testing' ) );
}
if ( isset( $this->wpdb->insert_id ) && $this->wpdb->insert_id && empty( $data['id'] ) ) {
$this->id = $this->wpdb->insert_id;
}
return $this;
}
/**
* Delete by id
*
* @return false|int
* @throws Exception
*/
public function delete() {
if ( ! is_numeric( $this->id ) ) {
throw new Exception( __( 'Invalid input for delete', 'thrive-ab-page-testing' ) );
}
return $this->wpdb->delete( $this->_table_name(), array( 'id' => $this->id ) );
}
/**
* If some data is not send at initialization
* default data can be stored in db.
*
* To be overwritten by specific models
*
* @return array
*/
protected function _get_default_data() {
return array();
}
/**
* Access the all _data
*
* @return array
*/
public function get_data() {
return $this->_data;
}
/**
* Called before save. This data is stored in DB
*
* @return array
*/
protected function _prepare_data() {
return $this->_data;
}
/**
* Return what should be localized for JS
*
* @return mixed
*/
public function json_data() {
return $this->_data;
}
/**
* Returns the table name for data to be saved
*
* @return string
*/
abstract protected function _table_name();
/**
* Called before saving _data in DB
*
* @return mixed
*/
abstract protected function is_valid();
}

View File

@@ -0,0 +1,288 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_AB_Page
*
* Page that will have variations for its content
*/
class Thrive_AB_Page extends Thrive_AB_Post {
/**
* @var Thrive_AB_Test
*/
protected $_running_test;
public function __construct( $post ) {
parent::__construct( $post );
if ( ! thrive_ab()->is_cpt_allowed( $this->_post->post_type ) ) {
throw new Exception( __( 'Provided post is not a page', 'thrive-ab-page-testing' ) );
}
}
/**
* Query all the variation custom posts for current page post
*
* @param $filters array wp_query args
* @param $type string default array
*
* @return array with elements of Thrive_AB_Page_Variation or array
* @throws Exception
*/
public function get_variations( $filters = array(), $type = 'array' ) {
if ( $this->_post->post_status === Thrive_AB_Post_Status::VARIATION ) {
return array();
}
$query_args = array(
'post_type' => array(
get_post_type( $this->_post->ID ),
Thrive_AB_Post_Types::VARIATION,
),
'post_parent' => $this->_post->ID,
'post_status' => 'any',
'orderby' => 'ID',
'order' => 'ASC',
'fields' => 'ids',
'posts_per_page' => -1,
);
$meta_query = array(
'relation' => 'AND',
);
if ( empty( $filters['all'] ) ) {
$meta_query['status'] = array(
'key' => Thrive_AB_Meta::PREFIX . 'status',
'value' => 'published',
);
} else {
unset( $filters['all'] );
}
$query_args['meta_query'] = $meta_query;
$query_args = array_merge( $query_args, $filters );
$query = new WP_Query( $query_args );
$post_ids = $query->get_posts();
$variations = array();
foreach ( $post_ids as $post_id ) {
$variation = new Thrive_AB_Page_Variation( $post_id );
$is_allowed = thrive_ab()->is_cpt_allowed( $variation->post_type );
if ( $is_allowed && $variation->post_status !== Thrive_AB_Post_Status::VARIATION ) {
//these posts are pages set as child from WP admin
//these posts are not variations
continue;
}
$variation->set_page( $this->_post );
$variations[] = $type === 'array' ? $variation->get_data() : $variation;
}
$parent_as_variation = new Thrive_AB_Page_Variation( $this->_post );
if ( count( $variations ) === 0 ) {
$parent_as_variation->get_meta()->update( 'traffic', 100 );
$parent_as_variation->get_meta()->update( 'is_control', 1 );
$parent_as_variation->get_meta()->update( 'status', 'published' );
}
array_unshift( $variations, $type === 'array' ? $parent_as_variation->get_data() : $parent_as_variation );
return $variations;
}
/**
* @param array $filters
* @param string $type
*
* @return array
*/
public function get_tests( $filters = array(), $type = 'array' ) {
$test_manager = new Thrive_AB_Test_Manager();
$filters = array_merge( $filters, array( 'page_id' => $this->_post->ID ) );
return $test_manager->get_tests( $filters, $type );
}
/**
* Returns the running test id of a page or null if the page has no running test
*
* @return int|null
*/
public function get_running_test_id() {
$running_test = $this->get_tests( array( 'status' => 'running' ) );
return empty( $running_test ) ? null : $running_test[0]['ID'];
}
public function get_running_test() {
if ( ! $this->_running_test instanceof Thrive_AB_Test ) {
$tests = $this->get_tests( array(
'status' => 'running',
), OBJECT );
$this->_running_test = count( $tests ) ? current( $tests ) : null;
}
if ( $this->_running_test instanceof Thrive_AB_Test ) {
$this->_running_test->get_items();
}
return $this->_running_test;
}
/**
* create a custom variation post based on the post
* and return it
*
* @param string $type
*
* @return Thrive_AB_Variation|array
*/
public function get_control_variation( $type = 'array' ) {
/** @var Thrive_AB_Variation $variation */
foreach ( $this->get_variations( array(), 'object' ) as $variation ) {
if ( $variation->get_meta()->get( 'is_control' ) === true ) {
break;
}
}
return $type === 'array' ? $variation->get_data() : $variation;
}
/**
* @param array $model
*
* @return Thrive_AB_Page_Variation
* @throws Exception if the post could not be saved or updated
*
*/
public function save_variation( $model ) {
/**
* Set default data
*/
$model = array_merge( array(
'post_status' => Thrive_AB_Post_Status::VARIATION,
'post_type' => get_post_type( $this->_post->ID ),
'post_parent' => $this->_post->ID,
'post_title' => __( 'Variation', 'thrive-ab-page-testing' ),
), $model );
if ( empty( $model['ID'] ) ) {
$post = wp_insert_post( $model );
} else {
$post = wp_update_post( $model );
}
if ( is_wp_error( $post ) || $post === 0 ) {
throw new ErrorException( __( 'Variation could not be saved', 'thrive-ab-page-testing' ) );
}
$variation = new Thrive_AB_Page_Variation( $post );
$model_has_meta = ! empty( $model['meta'] ) && is_array( $model['meta'] );
if ( $model_has_meta ) {
foreach ( $model['meta'] as $key => $value ) {
$variation->get_meta()->update( $key, $value );
}
$original_page = new Thrive_AB_Meta( $model['post_parent'] );
$variation->get_meta()->update( 'thrive_post_template', $original_page->get( 'thrive_post_template' ) );
}
return $variation;
}
/**
* Public data to be localized
*
* @return array
*/
public function get_data() {
return array(
'edit_link' => get_edit_post_link( $this->_post->ID, '' ),
'ID' => $this->_post->ID,
);
}
/**
* Implemented as hook for 'delete_post' action
*
* @param $post_id
*
* @see Thrive_AB __construct()
*
*/
public static function delete( $post_id ) {
try {
$page = new Thrive_AB_Page( $post_id );
$variations = $page->get_variations( array(), 'object' );
array_shift( $variations );
/** @var Thrive_AB_Page_Variation $variation */
foreach ( $variations as $variation ) {
$variation->get_meta()->update( 'is_control', false );
$variation->delete();
}
} catch ( Exception $e ) {
//if any of the variation cannot be deleted permanently
}
}
/**
* Hook into trash action and don't allow to trash page if it has a running test
*
* @param $null null check is made for NULL
* @param $post
*
* @return NULL or FALSE for not trashing
*/
public static function trash( $null, $post ) {
try {
$page = new Thrive_AB_Page( $post );
$test_id = $page->get_meta()->get( 'running_test_id' );
$null = empty( $test_id ) ? null : false;
} catch ( Exception $e ) {
}
return $null;
}
/**
* Returns the Start Test Url
*
* @return false|string
*/
public function get_start_test_url() {
$url = get_permalink( $this->_post );
$url = add_query_arg( 'thrive-variations', 'true', $url );
return $url;
}
public function get_test_link( $test_id ) {
return Thrive_AB_Test_Manager::get_test_url( $test_id );
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Post_Status {
const VARIATION = 'tab_variation';
public static function init() {
add_action( 'init', array( __CLASS__, 'register_variation_status' ) );
}
public static function register_variation_status() {
$args = array(
'label' => __( 'TOP Variation', 'thrive-ab-page-testing' ),
'label_count' => _n_noop( 'TOP Variation (%s)', 'TOP Variations (%s)', 'thrive-ab-page-testing' ),
'public' => false,//posts shown in frontend ?
'internal' => false,//internal use?
'private' => false,//posts accessed by their url?
'protected' => true,//for own user see class-wp-query.php line 2895
'exclude_from_search' => false,
'show_in_admin_all_list' => false,//posts shown in admin lists?
'show_in_admin_status_list' => false,//lists among other statues
);
register_post_status( self::VARIATION, $args );
}
}
Thrive_AB_Post_Status::init();

View File

@@ -0,0 +1,80 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Post_Types {
const VARIATION = 'thrive_ab_variation';
public static function init() {
add_action( 'init', array( __CLASS__, 'register_post_types' ) );
add_filter( 'tve_landing_page_post_types', array( __CLASS__, 'add_variation_type_as_landing_page' ) );
add_filter( 'tve_post_having_non_lp_settings', array( __CLASS__, 'has_non_lp_settings' ) );
add_filter( 'tcb_post_grid_banned_types', array( __CLASS__, 'add_post_grid_banned_types' ) );
}
public static function register_post_types() {
register_post_type( self::VARIATION, array(
'labels' => array(
'name' => 'Thrive Optimize Variation',
),
'hierarchical' => true,
'publicly_queryable' => true,
'query_var' => false,
'rewrite' => false,
) );
}
/**
* Tells TAr variation post type can be used as landing page
*
* @param $post_types
*
* @return array
*/
public static function add_variation_type_as_landing_page( $post_types ) {
$post_types[] = self::VARIATION;
return $post_types;
}
/**
* Add some Optimize post types to Architect Post Grid Element Banned Types
*
* @param array $banned_types
*
* @return array
*/
public static function add_post_grid_banned_types( $banned_types = array() ) {
$banned_types[] = self::VARIATION;
return $banned_types;
}
/**
* Tells TAr to load some settings for variation post type
*
* @param $post_types
*
* @return array
*/
public static function has_non_lp_settings( $post_types ) {
$post_types[] = self::VARIATION;
return $post_types;
}
}
Thrive_AB_Post_Types::init();

View File

@@ -0,0 +1,76 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Post {
/**
* @var WP_Post
*/
protected $_post;
/**
* @var Thrive_AB_Meta
*/
private $_meta;
/**
* Thrive_AB_Post constructor.
*
* @param $post WP_Post|int
*
* @throws Exception
*/
public function __construct( $post ) {
$post = is_int( $post ) ? get_post( $post ) : $post;
if ( ! ( $post instanceof WP_Post ) ) {
throw new Exception( __( 'Post not found', 'thrive-ab-page-testing' ) );
}
$this->_post = $post;
}
public function get_meta() {
if ( empty( $this->_meta ) ) {
$this->_meta = new Thrive_AB_Meta( $this->_post->ID );
}
return $this->_meta;
}
/**
* @param $meta Thrive_AB_Meta
*/
public function set_meta( $meta ) {
$this->_meta = $meta;
}
public function __get( $key ) {
$value = null;
if ( method_exists( $this, $key ) ) {
$value = call_user_func( array( $this, $key ) );
} elseif ( isset( $this->_post->$key ) ) {
$value = $this->_post->$key;
} elseif ( ( $meta = $this->get_meta()->get( $key ) ) !== null ) {
$value = $meta;
}
return $value;
}
public function get_post() {
return $this->_post;
}
}

View File

@@ -0,0 +1,148 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 12/21/2017
* Time: 2:24 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_AB_Product
*/
class Thrive_AB_Product extends TVE_Dash_Product_Abstract {
/**
* Tag of the product
*
* @var string tag.
*/
protected $tag = 'tab';
/**
* Slug
*
* @var string
*/
protected $slug = 'thrive-ab-page-testing';
/**
* Version
*
* @var string
*/
protected $version = Thrive_AB::V;
/**
* Name of the product displayed in Dashboard
*
* @var string title
*/
protected $title = 'Thrive Optimize';
/**
* Type of product
*
* @var string type of the product
*/
protected $type = 'plugin';
/**
* Thrive_AB_Product constructor.
*
* @param array $data info used in dashboard.
*/
public function __construct( $data = array() ) {
parent::__construct( $data );
$this->logoUrl = thrive_ab()->url( 'assets/images/tab-logo.png' );
$this->logoUrlWhite = thrive_ab()->url( 'assets/images/tab-logo-white.png' );
$this->productIds = array();
$this->description = __( 'Boost Conversion Rates by testing two or more variations of a page.', 'thrive-ab-page-testing' );
$this->button = array(
'active' => true,
'url' => admin_url( 'admin.php?page=tab_admin_dashboard' ),
'label' => __( 'Thrive Optimize', 'thrive-ab-page-testing' ),
);
$this->moreLinks = array(
'tutorials' => array(
'class' => '',
'icon_class' => 'tvd-icon-graduation-cap',
'href' => 'https://thrivethemes.com/thrive-optimize-tutorials/',
'target' => '_blank',
'text' => __( 'Tutorials', 'thrive-ab-page-testing' ),
),
'support' => array(
'class' => '',
'icon_class' => 'tvd-icon-life-bouy',
'href' => 'https://thrivethemes.com/support/',
'target' => '_blank',
'text' => __( 'Support', 'thrive-ab-page-testing' ),
),
);
}
/**
* In optimize we need to override the dash product functions just in case the dash is not loaded yet
*/
/**
* Check if the current has access to the product
*
* @return bool
*/
public static function has_access() {
return current_user_can( 'tve-use-tab' );
}
public static function cap() {
return 'tve-use-tab';
}
/**
* Reset plugin to default data
*/
public static function reset_plugin() {
$query = new WP_Query( array(
'post_type' => array(
Thrive_AB_Post_Types::VARIATION,
),
'fields' => 'ids',
'posts_per_page' => '-1',
)
);
$post_ids = $query->posts;
foreach ( $post_ids as $id ) {
wp_delete_post( $id, true );
}
global $wpdb;
$wpdb->query(
"DELETE FROM $wpdb->postmeta WHERE
`meta_key` LIKE '%thrive_ab%';"
);
$tables = array(
'event_log',
'tests',
'test_items',
);
foreach ( $tables as $table ) {
$table_name = thrive_ab()->table_name( $table );
$sql = "TRUNCATE TABLE $table_name";
$wpdb->query( $sql );
}
$wpdb->query(
"DELETE FROM $wpdb->options WHERE
`option_name` LIKE '%thrive_ab%' OR '%is_control%';"
);
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Query {
private $_query_vars = array(
'thrive-variations' => 'true',
'variation' => 'int',
'test-id' => 'int',
'generate-stats' => 'true',
);
public function __construct() {
add_filter( 'query_vars', array( $this, 'add_query_vars' ) );
}
public function add_query_vars( $vars ) {
foreach ( $this->_query_vars as $key => $value ) {
$vars[] = $key;
}
return $vars;
}
public function get_var( $key ) {
$value = null;
if ( in_array( $key, array_keys( $this->_query_vars ) ) ) {
global $wp;
$value = isset( $wp->query_vars[ $key ] ) ? $wp->query_vars[ $key ] : null;
}
return $value;
}
}

View File

@@ -0,0 +1,329 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 12/5/2017
* Time: 1:26 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Report_Manager {
static public $_transient_stats_name = 'tab_dashboard_stats';
/**
* @var wpdb
*/
protected $_wpdb;
/**
* Database Log Code for Impressions
* @var int
*/
private $_log_impression = 1;
/**
* Database Log Code for Conversions
* @var int
*/
private $_log_conversion = 2;
/**
* Thrive_AB_Report_Manager constructor.
*/
public function __construct() {
global $wpdb;
$this->_wpdb = $wpdb;
}
public function conversion_rate( $impressions, $conversions ) {
$conversions = (int) $conversions;
$impressions = (int) $impressions;
$conversion_rate = 0.0;
if ( $conversions !== 0 && $impressions !== 0 ) {
$conversion_rate = round( 100 * ( $conversions / $impressions ), 2 );
}
return $conversion_rate;
}
/**
* Computes the data necessary for the test in the report view
*
* @param array $filters
*
* @return array
*/
public function get_test_chart_data( $filters = array() ) {
$test = new Thrive_AB_Test( $filters['test_id'] );
$test_items = $test->get_items();
$test_data = $test->get_data();
$defaults = array(
'interval' => 'day',
'start_date' => date( 'Y-m-d H:i:s', strtotime( $test_data['date_started'] ) ),
);
if ( $test_data['status'] !== 'running' ) {
$defaults['end_date'] = date( 'Y-m-d H:i:s', strtotime( $test_data['date_completed'] ) );
} else {
$defaults['end_date'] = date( 'Y-m-d' ) . ' 23:59:59';
}
$filters = array_merge( $defaults, $filters );
$variations = array();
foreach ( $test_items as $item ) {
$variations[ $item->variation_id ] = array(
'name' => html_entity_decode( $item->title ),
'revenue' => $item->revenue,
'is_active' => $item->active,
'stopped_date' => $item->stopped_date,
);
}
$log_data = $this->get_test_chart_db_data( $filters );
/* generate dates for X Axis and to later fill the empty data */
$dates = $this->generate_dates_interval( $filters['start_date'], $filters['end_date'], $filters['interval'] );
$chart_data_temp = array();
foreach ( $log_data as $interval ) {
if ( empty( $chart_data_temp[ $interval->variation_id ] ) ) {
$chart_data_temp[ $interval->variation_id ][ $this->_log_impression ] = array();
$chart_data_temp[ $interval->variation_id ][ $this->_log_conversion ] = array();
}
if ( $filters['interval'] == 'day' ) {
$interval->date_interval = date( 'd M, Y', strtotime( $interval->date_interval ) );
}
if ( $test_data['type'] == 'monetary' ) {
$chart_data_temp[ $interval->variation_id ]['revenue'][ $interval->date_interval ] = $interval->revenue;
}
$chart_data_temp[ $interval->variation_id ][ intval( $interval->event_type ) ][ $interval->date_interval ] = intval( $interval->log_count );
}
$chart_data = array();
$total_over_time = 0;
$total_impressions = 0;
$total_conversions = 0;
if ( ! empty( $filters['type'] ) && $filters['type'] == 'conversion_rate' ) {
$test_data['type'] = $filters['type'];
}
foreach ( $variations as $id => $test_items_data ) {
$item_dates = $dates;
if ( ! $test_items_data['is_active'] ) {
$item_dates = $this->generate_dates_interval( $filters['start_date'], $test_items_data['stopped_date'], $filters['interval'] );
}
if ( empty( $chart_data[ $id ] ) ) {
$chart_data[ $id ]['id'] = $id;
$chart_data[ $id ]['name'] = $test_items_data['name'];
$chart_data[ $id ]['data'] = array();
}
$revenue = $impressions = $conversions = $variation_max_over_time = 0;
foreach ( $item_dates as $key => $date ) {
$impressions += empty( $chart_data_temp[ $id ][ $this->_log_impression ][ $date ] ) ? 0 : $chart_data_temp[ $id ][ $this->_log_impression ][ $date ];
$conversions += empty( $chart_data_temp[ $id ][ $this->_log_conversion ][ $date ] ) ? 0 : $chart_data_temp[ $id ][ $this->_log_conversion ][ $date ];
$revenue += empty( $chart_data_temp[ $id ]['revenue'][ $date ] ) ? 0 : $chart_data_temp[ $id ]['revenue'][ $date ];
$tmp = 0;
if ( ! empty( $impressions ) && ! empty( $conversions ) ) {
/* Complete with zero on empty dates */
$tmp = $this->generate_chart_entry_value( $test_data['type'], $impressions, $conversions, $revenue );
}
$chart_data[ $id ]['data'][] = $tmp;
$variation_max_over_time = $tmp;
}
$total_impressions += $impressions;
$total_conversions += $conversions;
$total_over_time += $variation_max_over_time;
}
$return = array(
'ID' => $filters['test_id'],
'title' => __( 'Total conversions over time', 'thrive-ab-page-testing' ),
'data' => $chart_data,
'x_axis' => $dates,
'y_axis' => __( 'Total visits', 'thrive-ab-page-testing' ),
'total_over_time' => $test_data['type'] === 'conversion_rate' ? $this->conversion_rate( $total_impressions, $total_conversions ) : $total_over_time,
'test_type_txt' => '',
);
if ( $test_data['type'] === 'monetary' ) {
$return['title'] = __( 'Total revenue over time', 'thrive-ab-page-testing' );
$return['y_axis'] = __( 'Total revenue', 'thrive-ab-page-testing' ) . ' $';
$return['test_type_txt'] = '$';
} elseif ( $test_data['type'] === 'optins' ) {
$return['title'] = __( 'Total subscriptions over time', 'thrive-ab-page-testing' );
$return['y_axis'] = __( 'Total subscriptions', 'thrive-ab-page-testing' );
} elseif ( $test_data['type'] === 'conversion_rate' ) {
$return['title'] = __( 'Page conversion rate', 'thrive-ab-page-testing' );
$return['y_axis'] = __( 'Conversion rate (%)', 'thrive-ab-page-testing' );
$return['test_type_txt'] = '%';
}
return $return;
}
/**
* Depending on the test type, it generates the data entry
*
* @param $test_type
* @param $conversions
* @param $impressions
* @param $revenue
*
* @return float|int
*/
private function generate_chart_entry_value( $test_type, $impressions, $conversions, $revenue ) {
$return = $conversions;
if ( $test_type === 'conversion_rate' ) {
$return = $this->conversion_rate( $impressions, $conversions );
} elseif ( $test_type === 'monetary' ) {
$return = (float) $revenue;
}
return $return;
}
/**
* Generate an array of dates between $start_date and $end_date depending on the $interval
*
* @param $start_date
* @param $end_date
* @param string $interval - can be 'day', 'week', 'month'
*
* @return array $dates
*/
private function generate_dates_interval( $start_date, $end_date, $interval = 'day' ) {
/* just to make sure the end day has the latest hour */
$end_date = date( 'Y-m-d', strtotime( $end_date ) ) . ' 23:59:59';
switch ( $interval ) {
case 'day':
$date_format = 'd M, Y';
break;
case 'week':
$date_format = '\W\e\e\k W, o';
break;
case 'month':
$date_format = 'F Y';
break;
default:
$date_format = 'Y-m-d';
break;
}
$dates = array();
for ( $i = 0; strtotime( $start_date . ' + ' . $i . 'day' ) <= strtotime( $end_date ); $i ++ ) {
$timestamp = strtotime( $start_date . ' + ' . $i . 'day' );
$date = date( $date_format, $timestamp );
//remove the 0 from the week number
if ( $interval == 'week' ) {
$date = str_replace( 'Week 0', 'Week ', $date );
}
if ( ! in_array( $date, $dates ) ) {
$dates[] = $date;
}
}
return $dates;
}
/**
* Interrogates the DB and returns data necessary for the chart
*
* @param $filters
*
* @return array|null|object
*/
public function get_test_chart_db_data( $filters ) {
$date_interval = '';
switch ( $filters['interval'] ) {
case 'month':
$date_interval = 'CONCAT(MONTHNAME(`log`.`date`)," ", YEAR(`log`.`date`)) as date_interval';
break;
case 'week':
$year = 'IF( WEEKOFYEAR(`log`.`date`) = 1 AND MONTH(`log`.`date`) = 12, 1 + YEAR(`log`.`date`), YEAR(`log`.`date`) )';
$date_interval = "CONCAT('Week ', WEEKOFYEAR(`log`.`date`), ', ', {$year}) as date_interval";
break;
default:
case 'day':
$date_interval = 'DATE(`log`.`date`) as date_interval';
break;
}
$sql = 'SELECT IFNULL(COUNT( DISTINCT log.id ), 0) AS log_count, variation_id, event_type, SUM( log.revenue ) as revenue, ' . $date_interval . '
FROM ' . thrive_ab()->table_name( 'event_log' ) . ' AS log WHERE 1 ';
$params = array();
if ( ! empty( $filters['test_id'] ) ) {
$sql .= 'AND `test_id` = %d ';
$params [] = $filters['test_id'];
}
if ( ! empty( $filters['start_date'] ) && ! empty( $filters['end_date'] ) ) {
$sql .= 'AND `date` BETWEEN %s AND %s ';
$params [] = $filters['start_date'];
$params [] = $filters['end_date'];
}
$sql .= ' GROUP BY variation_id, event_type, date_interval';
return $this->_wpdb->get_results( $this->_wpdb->prepare( $sql, $params ) );
}
public function get_admin_dashboard_stats() {
if ( false !== ( $results = get_transient( self::$_transient_stats_name ) ) ) {
return $results;
}
$query = 'SELECT * FROM ' . thrive_ab()->table_name( 'event_log' ) . ' WHERE DATE(date) >= DATE(DATE_SUB(NOW(), INTERVAL 1 MONTH))';
$return = array();
$return['unique_visitors'] = 0;
$return['total_conversions'] = 0;
$return['conversion_rate'] = 0;
$results = $this->_wpdb->get_results( $query, ARRAY_A );
if ( empty( $results ) ) {
return $return;
}
foreach ( $results as $entry ) {
if ( (int) $entry['event_type'] === $this->_log_impression ) {
$return['unique_visitors'] ++;
} elseif ( (int) $entry['event_type'] === $this->_log_conversion ) {
$return['total_conversions'] ++;
}
}
if ( $return['total_conversions'] !== 0 && $return['unique_visitors'] !== 0 ) {
$return['conversion_rate'] = round( 100 * ( $return['total_conversions'] / $return['unique_visitors'] ), 2 );
}
set_transient( self::$_transient_stats_name, $return, 8 * HOUR_IN_SECONDS );
return $return;
}
}

View File

@@ -0,0 +1,544 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB {
const V = '10.6';
const DB = '1.2';
private static $_instance;
/**
* @var null|Thrive_AB_Dashboard
*/
private $_dashboard;
/**
* @var Thrive_AB_Query
*/
private $_query;
protected static $_test_url;
private function __construct() {
$this->_includes();
$this->_query = new Thrive_AB_Query();
add_action( 'admin_init', array( $this, 'register_deactivation_hooks' ) );
/**
* When TAr hooks into template_redirect
*/
add_action( 'tcb_hook_template_redirect', array( 'Thrive_AB_Editor', 'init' ) );
add_action( 'has_non_landing_page_settings', array( __CLASS__, 'has_non_lp_settings' ), 10, 1 );
add_filter( 'tve_dash_installed_products', array( __CLASS__, 'add_to_dashboard_list' ) );
add_filter( 'tve_display_manager_current_post', static function ( $post ) {
if ( $post->post_status === 'tab_variation' ) {
/* if the display manager from leads or utilamtum tries to read current page, return the parent */
$post = get_post( $post->post_parent );
}
return $post;
} );
if ( is_admin() ) {
add_action( 'before_delete_post', array( 'Thrive_AB_Page', 'delete' ) );
add_action( 'pre_trash_post', array( 'Thrive_AB_Page', 'trash' ), 10, 2 );
add_action( 'save_post_page', array( __CLASS__, 'save_page' ), 10, 3 );
} else {
add_action( 'wp', array( $this, 'initiate_dashboard' ) );
add_action( 'wp', array( $this, 'remove_admin_bar_tar_button' ) );
add_filter( 'template_include', array( $this, 'determine_variation_template' ) );
add_filter( 'tu_is_page_allowed', array( $this, 'is_campaign_allowed_on_variation' ), 10, 3 );
add_filter( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 90 );
}
add_action( 'init', array( $this, 'update_checker' ) );
add_action( 'init', array( $this, 'load_plugin_textdomain' ) );
add_action( 'thrive_dashboard_loaded', array( $this, 'dash_loaded' ) );
add_action( 'thrive_prepare_migrations', array( $this, 'register_db_migrations' ) );
}
public static function instance() {
if ( ! self::$_instance ) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Data needed for license processing
* @return array
*/
public static function license_data() {
$manager = TD_TTW_User_Licenses::get_instance();
return [
'exp' => ! $manager->has_active_license( 'tab' ),
'gp' => $manager->is_in_grace_period( 'tab' ),
'show_lightbox' => $manager->show_gp_lightbox( 'tab' ),
'grace_time' => $manager->get_grace_period_left( 'tab' ),
'link' => tvd_get_individual_plugin_license_link( 'tab' ),
];
}
/**
* Push Thrive A/B Page Testing to Thrive Dashboard installed products list
*
* @param array $items
*
* @return array
*/
public static function add_to_dashboard_list( $items = array() ) {
$items[] = new Thrive_AB_Product();
return $items;
}
/**
* Check if the plugin can be used on a specific post type
*
* @param $post_type
*
* @return bool
*/
public function is_cpt_allowed( $post_type ) {
return ! empty( $post_type ) && apply_filters( 'tve_allowed_post_type', true, $post_type );
}
/**
* @return Thrive_AB_Query
*/
public function get_query() {
return $this->_query;
}
protected function _includes() {
/**
* CORE
*/
require_once dirname( __FILE__ ) . '/class-thrive-ab-checker.php';
require_once dirname( __FILE__ ) . '/class-thrive-ab-query.php';
require_once dirname( __FILE__ ) . '/class-thrive-ab-post-types.php';
require_once dirname( __FILE__ ) . '/class-thrive-ab-post-status.php';
require_once dirname( __FILE__ ) . '/class-thrive-ab-post.php';
require_once dirname( __FILE__ ) . '/class-thrive-ab-meta.php';
require_once dirname( __FILE__ ) . '/class-thrive-ab-page.php';
require_once dirname( __FILE__ ) . '/variations/class-thrive-ab-variation.php';
require_once dirname( __FILE__ ) . '/variations/class-thrive-ab-page-variation.php';
require_once dirname( __FILE__ ) . '/ajax/class-thrive-ab-ajax.php';
require_once dirname( __FILE__ ) . '/class-thrive-ab-model.php';
require_once dirname( __FILE__ ) . '/test/class-thrive-ab-test.php';
require_once dirname( __FILE__ ) . '/test/class-thrive-ab-test-item.php';
require_once dirname( __FILE__ ) . '/test/class-thrive-ab-test-manager.php';
require_once dirname( __FILE__ ) . '/events/class-thrive-ab-event.php';
require_once dirname( __FILE__ ) . '/events/class-thrive-ab-event-manager.php';
require_once dirname( __FILE__ ) . '/class-thrive-ab-cookie-manager.php';
require_once dirname( __FILE__ ) . '/class-thrive-ab-report-manager.php';
require_once dirname( __FILE__ ) . '/compat.php';
if ( is_admin() ) {
require_once dirname( __FILE__ ) . '/class-thrive-admin-notices.php';
require_once dirname( __FILE__ ) . '/class-thrive-ab-admin.php';
require_once dirname( __FILE__ ) . '/class-thrive-ab-meta-box.php';
}
require_once dirname( __FILE__ ) . '/class-thrive-ab-editor.php';
require_once dirname( __FILE__ ) . '/class-thrive-ab-dashboard.php';
require_once dirname( __FILE__ ) . '/variations/class-thrive-ab-variation-manager.php';
}
/**
* Hook for plugin deactivation and TAr deactivation
*/
public function register_deactivation_hooks() {
register_deactivation_hook( THRIVE_AB_PLUGIN_FILE, array( 'Thrive_Admin_Notices', 'remove_notices' ) );
if ( defined( 'TVE_PLUGIN_FILE' ) ) {
register_deactivation_hook( TVE_PLUGIN_FILE, array( 'Thrive_Admin_Notices', 'push_notice_active' ) );
}
}
/**
* Helper for deactivating this plugin
*/
public function deactivate() {
deactivate_plugins( THRIVE_AB_PLUGIN_FILE );
}
function load_plugin_textdomain() {
$locale = apply_filters( 'plugin_locale', get_locale(), 'thrive-ab-page-testing' );
load_textdomain( 'thrive-ab-page-testing', WP_LANG_DIR . '/thrive/thrive-ab-page-testing-' . $locale . '.mo' );
load_plugin_textdomain( 'thrive-ab-page-testing', false, 'ab-page-testing/languages' );
}
public function path( $file = '' ) {
return plugin_dir_path( THRIVE_AB_PLUGIN_FILE ) . ltrim( $file, '\\/' );
}
public function url( $file = '' ) {
return plugin_dir_url( THRIVE_AB_PLUGIN_FILE ) . ltrim( $file, '\\/' );
}
public function plugin_name() {
return 'Thrive Optimize';
}
/**
* Dashboard is instantiated if the WP_Query has specific query string
*
* @return null|Thrive_AB_Dashboard
*/
public function initiate_dashboard() {
$this->_dashboard = Thrive_AB_Dashboard::instance();
return $this->_dashboard;
}
public function is_dashboard() {
return $this->_query->get_var( 'thrive-variations' ) === 'true';
}
public function table_name( $table_name ) {
if ( class_exists( 'TD_DB_Migration' ) ) {
$migration = new TD_DB_Migration( 'tab' );
$table_name = $migration->get_table_name( $table_name );
}
return $table_name;
}
/**
* Wrapper over the wp_enqueue_script function.
* It will add the plugin version to the script source if no version is specified.
*
* @param $handle
* @param string $src
* @param array $deps
* @param bool $ver
* @param bool $in_footer
*/
public function enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $in_footer = false ) {
if ( false === $ver ) {
$ver = Thrive_AB::V;
}
wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer );
}
/**
* Wrapper over the wp_enqueue_style function.
* It will add the plugin version to the style link if no version is specified
*
* @param $handle
* @param bool $src
* @param array $deps
* @param bool $ver
* @param string $media
*/
public function enqueue_style( $handle, $src = false, $deps = array(), $ver = false, $media = 'all' ) {
if ( false === $ver ) {
$ver = Thrive_AB::V;
}
wp_enqueue_style( $handle, $src, $deps, $ver, $media );
}
public function remove_admin_bar_tar_button() {
global $post;
if ( ! ( $post instanceof WP_Post ) ) {
return;
}
try {
$post_id = $post->ID;
$is_variation = Thrive_AB_Post_Types::VARIATION === $post->post_type || Thrive_AB_Post_Status::VARIATION === $post->post_status;
if ( $is_variation && ! empty( $post->post_parent ) ) {
$post_id = $post->post_parent;
}
$page = new Thrive_AB_Page( $post_id );
$test_id = $page->get_meta()->get( 'running_test_id' );
} catch ( Exception $e ) {
}
if ( ! empty( $test_id ) ) {
/**
* set this here for later use @see view_test_button()
*/
self::$_test_url = Thrive_AB_Test_Manager::get_test_url( $test_id );
remove_action( 'admin_bar_menu', 'thrive_editor_admin_bar', 100 );
add_action( 'admin_bar_menu', array( $this, 'view_test_button' ), 100 );
}
}
/**
* Check if there is a valid activated license for the TAB plugin.
*
* @return bool
*/
public function license_activated() {
if ( ! defined( 'TVE_Dash_Product_LicenseManager::TAB_TAG' ) ) {
return false;
}
return TVE_Dash_Product_LicenseManager::getInstance()->itemActivated( TVE_Dash_Product_LicenseManager::TAB_TAG );
}
/**
* Called after dash has been loaded
*/
public function dash_loaded() {
require_once dirname( __FILE__ ) . '/class-thrive-ab-product.php';
}
/**
* Checks for updates
*/
public function update_checker() {
/** plugin updates script **/
if ( ! class_exists( 'TVE_PluginUpdateChecker', false ) ) {
return;
}
new TVE_PluginUpdateChecker(
'https://service-api.thrivethemes.com/plugin/update',
dirname( dirname( __FILE__ ) ) . '/thrive-ab-page-testing.php',
'thrive-ab-page-testing',
12,
'',
'thrive_ab_page_testing'
);
/**
* Adding icon of the product for update-core page
*/
add_filter( 'puc_request_info_result-thrive-ab-page-testing', array( $this, 'tab_set_product_icon' ) );
}
/**
* Adding the product icon for the update core page
*
* @param $info
*
* @return mixed
*/
public function tab_set_product_icon( $info ) {
$info->icons['1x'] = thrive_ab()->url( 'assets/images/tab-logo.png' );
return $info;
}
/**
* Force page template to be loaded when user edits/sees the variation custom post
*
* @param $template
*
* @return string
* @deprecated we should removed this and its caller because the variations are no longer custom posts
*
*/
public function determine_variation_template( $template ) {
global $post;
if ( $post instanceof WP_Post && Thrive_AB_Post_Types::VARIATION === $post->post_type ) {
$template = get_page_template();
}
return $template;
}
/**
* @param $wp_admin_bar WP_Admin_Bar
*/
public function view_test_button( $wp_admin_bar ) {
$test_link = self::$_test_url;
$icon_url = thrive_ab()->url( 'assets/images/tab-logo-admin-bar.png' );
$args = array(
'id' => 'tve_button',
'title' => __( 'View test details', 'thrive-ab-page-testing' ),
'href' => $test_link,
'meta' => array(
'class' => 'thrive-ab-view-test',
'html' => '<style type="text/css">.thrive-ab-view-test .ab-item:before {content: url("' . $icon_url . '"); margin-right: 4px !important;}</style>',
),
);
if ( ! empty( $test_link ) ) {
$wp_admin_bar->add_node( $args );
}
}
/**
* Check if $post is a variation
*
* @param $post
*
* @return bool|null
*/
public function maybe_variation( $post ) {
if ( ! ( $post instanceof WP_Post ) ) {
return null;
}
return Thrive_AB_Post_Status::VARIATION === $post->post_status || Thrive_AB_Post_Types::VARIATION === $post->post_type;
}
/**
* Hook when a page is update/added
* Hook for updating page variations options: thrive metas, _wp_page_template meta, post_password
*
* @param $post_ID int
* @param $post WP_Post
* @param $update bool
*
* @return $this|null|Thrive_AB_Meta
*/
public static function save_page( $post_ID, $post, $update ) {
$is_insert = ! $update;
/**
* this is an insert of a non Thrive_AB_Variation
*/
if ( $is_insert && Thrive_AB_Post_Status::VARIATION !== $post->post_status ) {
return null;
}
try {
/**
* insert of new variation
*/
if ( $is_insert && thrive_ab()->maybe_variation( $post ) ) {
$page = new Thrive_AB_Page( $post->post_parent );
$variation = new Thrive_AB_Page_Variation( $post );
$variation->save(
array(
'ID' => $variation->get_post()->ID,
'post_password' => $page->get_post()->post_password,
)
);
return $page->get_meta()->copy_non_thrive_meta( $post_ID )->copy_thrive_theme_meta( $post_ID );
}
/**
* user updates a page and we need to check if it has variations
* to update them too
*/
if ( $update && ! thrive_ab()->maybe_variation( $post ) ) {
$page = new Thrive_AB_Page( $post_ID );
$variations = $page->get_variations( array(), 'obj' );
array_shift( $variations );
/** @var Thrive_AB_Page_Variation $variation */
foreach ( $variations as $variation ) {
$variation->save(
array(
'ID' => $variation->get_post()->ID,
'post_password' => $page->get_post()->post_password,
)
);
$page->get_meta()
// ->copy_non_thrive_meta( $variation->get_post()->ID )
->removed_unused_non_thrive_meta( $variation->get_post()->ID )
->copy_thrive_theme_meta( $variation->get_post()->ID );
}
}
} catch ( Exception $e ) {
}
return null;
}
/**
* Allow TU to display campaigns on page variations too
* if campaign is allowed on parent page
*
* @param $is_allowed bool
* @param $page WP_Post
* @param $pages_tab Thrive_Ult_Pages_Tab
*
* @return bool
*/
public function is_campaign_allowed_on_variation( $is_allowed, $page, $pages_tab ) {
if ( $page instanceof WP_Post && thrive_ab()->maybe_variation( $page ) ) {
$parent = get_post( $page->post_parent );
$is_allowed = $parent instanceof WP_Post && $pages_tab->isPageAllowed( $parent );
}
return $is_allowed;
}
/**
* Hooks into the TD DB migrations manager
*
* @throws Exception
*/
public function register_db_migrations() {
TD_DB_Manager::add_manager(
thrive_ab()->path( 'migrations' ),
'thrive_ab_page_testing_db',
Thrive_AB::DB,
'Thrive Optimize',
'tab',
'thrive_optimize_reset'
);
}
/**
* Manage the wp admin bar
* - removes the Edit Page menu for variations
*
* @param WP_Admin_Bar $admin_bar
*/
public function admin_bar_menu( WP_Admin_Bar $admin_bar ) {
global $post;
if ( true === $this->maybe_variation( $post ) ) {
$admin_bar->remove_menu( 'edit' );
}
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_Admin_Notices {
private static $_notices = array();
public static function init() {
add_action( 'admin_print_styles', array( __CLASS__, 'add_notices' ) );
}
public static function get_notices() {
self::$_notices = array_unique( array_merge( self::$_notices, get_option( 'thrive_ab_page_testing_notifications', array() ) ) );
return self::$_notices;
}
public static function remove_notices() {
delete_option( 'thrive_ab_page_testing_notifications' );
self::$_notices = array();
}
public static function push_notice( $notice ) {
self::$_notices = array_unique( array_merge( self::get_notices(), array( $notice ) ) );
self::save_notifications();
}
protected static function save_notifications() {
update_option( 'thrive_ab_page_testing_notifications', self::$_notices );
}
/**
* Call this function for a hook
*/
public static function push_notice_active() {
self::push_notice( 'active' );
}
public static function add_notices() {
$notices = self::get_notices();
if ( ! empty( $notices ) ) {
foreach ( $notices as $notice ) {
$callback = $notice . '_notice';
if ( method_exists( 'Thrive_Admin_Notices', $callback ) ) {
add_action( 'admin_notices', array( __CLASS__, $callback ) );
}
}
}
}
/**
* Display an error notice and deactivate the plugin
*/
public static function active_notice() {
include dirname( __FILE__ ) . '/views/admin/notices/html-active.php';
thrive_ab()->deactivate();
}
/**
* Display an error notice and deactivate the plugin
*/
public static function min_version_notice() {
include dirname( __FILE__ ) . '/views/admin/notices/html-version.php';
thrive_ab()->deactivate();
}
}
Thrive_Admin_Notices::init();

View File

@@ -0,0 +1,60 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden!
}
/**
* Rank Math Breadcrumbs shortcode compatibility - remove the ab-testing parent page from the Rank Math breadcrumbs list
* The issue is that the original page where the variations are run is shown in the breadcrumb path since it's the parent of the variation.
* So through this filter, "Home -> page_being_tested -> variation" should become "Home -> variation"
*/
add_filter( 'rank_math/frontend/breadcrumb/items', function ( $breadcrumbs ) {
$breadcrumbs_count = count( $breadcrumbs );
$index_to_delete = 0;
for ( $i = 0; $i < $breadcrumbs_count; $i ++ ) {
$breadcrumb = $breadcrumbs[ $i ];
/* Rank Math stores the page URL at the '1' index */
$page_url = $breadcrumb[1];
$id = url_to_postid( $page_url );
if ( ! empty( $id ) ) {
$post_parent = get_post_parent( $id );
if ( $post_parent !== null ) {
$has_ab_testing_parent = ! empty( get_post_meta( $post_parent->ID, 'thrive_ab_running_test_id', true ) );
/* if this is the variation, then the parent is located at the previous index and we mark it to be removed */
if ( $has_ab_testing_parent ) {
$index_to_delete = $i - 1;
}
}
}
}
if ( ! empty( $index_to_delete ) ) {
unset( $breadcrumbs[ $index_to_delete ] );
/* re-index */
$breadcrumbs = array_values( $breadcrumbs );
}
return $breadcrumbs;
} );
/**
* Don't display metrics ribbon if we don't have any license
*/
add_filter( 'tve_dash_metrics_should_enqueue', static function ( $should_enqueue ) {
$screen = tve_get_current_screen_key();
if ( $screen === 'thrive-dashboard_page_tab_admin_dashboard' && ! thrive_ab()->license_activated() ) {
$should_enqueue = false;
}
return $should_enqueue;
}, 10, 1 );

View File

@@ -0,0 +1,448 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_AB_Event_Manager
*/
class Thrive_AB_Event_Manager {
protected static $_instance;
protected $_page_id;
protected $_test_id;
/**
* @var wpdb
*/
protected $_wpdb;
public function __construct() {
global $wpdb;
$this->_wpdb = $wpdb;
}
public static function instance() {
if ( empty( self::$_instance ) ) {
self::$_instance = new self();
}
add_action( 'tcb_api_form_submit', array( self::$_instance, 'on_form_submit' ) );
return self::$_instance;
}
public function on_form_submit( $data ) {
$post_id = ! empty( $data['frontend_post_id'] ) ? (int)( $data['frontend_post_id'] ) : 0;
$post_id = ! empty( $post_id ) ? $post_id : ( isset( $data['post_id'] ) ? (int)$data['post_id'] : 0 );
if ( empty( $post_id ) ) {
return;
}
$post = get_post( $post_id );
$is_post_variation = thrive_ab()->maybe_variation( $post );
$page_id = (int)( $is_post_variation ? $post->post_parent : $post->ID );
try {
$page = new Thrive_AB_Page( $page_id );
$test_id = (int)$page->get_meta()->get( 'running_test_id' );
} catch ( Exception $e ) {
return;
}
/**
* page has no test running
*/
if ( empty( $test_id ) ) {
return;
}
/**
* test type has to be optins
*/
$test = new Thrive_AB_Test( $test_id );
if ( 'optins' !== $test->type ) {
return;
}
$impression_cookie = Thrive_AB_Cookie_Manager::get_cookie( $test_id, $page_id, 1 );
$conversion_cookie = Thrive_AB_Cookie_Manager::get_cookie( $test_id, $page_id, 2 );
/**
* user already made impression and conversion
*/
if ( ! $impression_cookie || $conversion_cookie ) {
return;
}
$goal_pages = $test->goal_pages;
/**
* save conversion cookie
*/
self::do_conversion( $test_id, $page_id, $post->ID, empty( $goal_pages[ $post->ID ] ) ? null : $goal_pages[ $post->ID ] );
}
public static function check_thank_you_page( $post ) {
if ( ! $post instanceof WP_Post || ! is_singular() ) {
return;
}
$test_manager = new Thrive_AB_Test_Manager();
$tests = $test_manager->get_tests( array( 'status' => 'running' ), 'object' );
$do_not_cache = false;
/** @var Thrive_AB_Test $test */
foreach ( $tests as $test ) {
/**
* If current page is goal page in one of the running tests do not cache
*/
$do_not_cache = $do_not_cache || ( ! empty( $goal_pages ) && ! empty( $goal_pages[ $post->ID ] ) );
$impression_variation = Thrive_AB_Cookie_Manager::get_cookie( $test->id, $test->page_id, 1 );
if ( empty( $impression_variation ) ) {
continue;
}
$conversion_variation = Thrive_AB_Cookie_Manager::get_cookie( $test->id, $test->page_id, 2 );
if ( ! empty( $conversion_variation ) ) {
continue;
}
$goal_pages = $test->goal_pages;
if ( $test->has_goal_page( $post->ID ) ) {
Thrive_AB_Event_Manager::do_conversion( $test->id, $test->page_id, $impression_variation, $test->get_goal_page_details( $post->ID ) );
continue;
}
}
if ( ! empty( $do_not_cache ) && function_exists( 'tve_do_not_cache_page' ) ) {
tve_do_not_cache_page();
}
}
/**
* Registers unique impression
* If there is a cookie set counts visit only
*
* @param $page_id
* @param $test_id
* @param $variation_id
*
* @return null|Thrive_AB_Event|Thrive_AB_Test_Item
*
* @throws Exception
*/
public static function do_impression( $page_id, $test_id, $variation_id ) {
$model = array(
'page_id' => $page_id,
'test_id' => $test_id,
'variation_id' => $variation_id,
'event_type' => 1,
'unique' => true,
);
/**
* Create here an event model so that:
* - it is thrown in an action
* - other plugins can hook into
*/
$event_log = new Thrive_AB_Event( $model );
do_action( 'thrive_ab_pre_impression', $event_log );
$cookie_variation_id = Thrive_AB_Cookie_Manager::get_cookie( $test_id, $page_id, 1 );
if ( $cookie_variation_id ) {
unset( $model['unique'] );
return Thrive_AB_Event_Manager::count_visit( $model );
}
$event = Thrive_AB_Event_Manager::save_event( $model );
Thrive_AB_Cookie_Manager::set_cookie( $event->test_id, $event->page_id, $event->variation_id, 1 );
return $event;
}
public static function do_conversion( $test_id, $page_id, $variation_id, $goal_page ) {
if ( empty( $test_id ) || empty( $page_id ) || empty( $variation_id ) ) {
return false;
}
$log_model = array(
'page_id' => $page_id,
'test_id' => $test_id,
'variation_id' => $variation_id,
'event_type' => 2,
'revenue' => ! empty( $goal_page['revenue'] ) ? $goal_page['revenue'] : 0,
'goal_page' => ! empty( $goal_page['post_id'] ) ? $goal_page['post_id'] : null,
);
Thrive_AB_Event_Manager::save_event( $log_model );
Thrive_AB_Cookie_Manager::set_cookie( $test_id, $page_id, $variation_id, 2 );
}
public static function save_event( $model ) {
delete_transient( Thrive_AB_Report_Manager::$_transient_stats_name );
$defaults = array(
'date' => date( 'Y-m-d H:i:s' ),
);
$model = array_merge( $defaults, $model );
$event_log = new Thrive_AB_Event( $model );
try {
$event_log->save();
} catch ( Exception $e ) {
}
do_action( 'thrive_ab_event_saved', $event_log );
/**
* save test item data
*/
Thrive_AB_Event_Manager::count_visit( $model );
Thrive_AB_Event_Manager::check_auto_winner( $model );
return $event_log;
}
/**
* Increments test_item model impression and/or unique impression column
* Sets a cookie with 5 seconds expiration time, just not to spam impression column
*
* @param $model
*
* @return Thrive_AB_Test_Item|null
*
* @throws Exception
*/
public static function count_visit( $model ) {
if ( function_exists( 'tve_dash_is_crawler' ) && tve_dash_is_crawler( true ) ) {
return null;
}
$test_item = new Thrive_AB_Test_Item();
$test_item->init_by_filters(
array(
'page_id' => $model['page_id'],
'variation_id' => $model['variation_id'],
'test_id' => $model['test_id'],
)
);
if ( 1 == $model['event_type'] ) {
/**
* increment impressions only if cookie not set, which is set to expire in 5 seconds
*/
if ( ! Thrive_AB_Cookie_Manager::get_impression_cookie( $test_item->id ) ) {
$test_item->impressions ++;
Thrive_AB_Cookie_Manager::set_impression_cookie( $test_item->id );
}
if ( ! empty( $model['unique'] ) ) {
$test_item->unique_impressions ++;
}
} else {
$test_item->conversions ++;
if ( ! empty( $model['revenue'] ) ) {
$test_item->revenue += $model['revenue'];
}
}
return $test_item->save();
}
public static function check_auto_winner( $event ) {
if ( empty( $event ) ) {
return null;
}
$test_manager = new Thrive_AB_Test_Manager();
$test = $test_manager->get_running_test( $event['page_id'] );
if ( ! $test->auto_win_enabled || 'running' !== $test->status ) {
return null;
}
if ( $test->auto_win_min_duration ) {
if ( time() < strtotime( $test->date_started . ' +' . $test->auto_win_min_duration . 'days' ) ) {
return false;
}
}
$test_item = new Thrive_AB_Test_Item();
$total_conversions = $test_item->get_total_conversions( $test->id );
if ( intval( $total_conversions->total_conversions ) <= intval( $test->auto_win_min_conversions ) ) {
return false;
}
$test_items = $test->get_items();
$winner = array(
'item' => null,
'chance' => 0,
);
$underperforming = array();
$leftovers = array();
foreach ( $test_items as $item ) {
if ( ! intval( $item->active ) ) {
continue;
}
if ( ! $item->is_control ) {
$current_chance = $item->get_chance_to_beat_original( '' );
if ( floatval( $current_chance ) > floatval( $test->auto_win_chance_original ) && floatval( $current_chance ) > $winner['chance'] ) {
$winner['item'] = $item;
$winner['chance'] = floatval( $current_chance );
}
if ( floatval( $current_chance ) < ( 100 - floatval( $test->auto_win_chance_original ) ) ) {
array_push( $underperforming, $item );
} else {
array_push( $leftovers, $item );
}
} else {
array_push( $leftovers, $item );
}
}
/**
* If there is a winner chosen, set the winner and stop the test
*/
if ( ! empty( $winner['item'] ) ) {
$data = $winner['item']->get_data();
Thrive_AB_Ajax::set_winner( $data );
} else {
/**
* Check if besides the underperforming variations there are any leftovers
* If so, then set it as winner. If not, take out the underperformers
*/
$removed_traffic = 0;
foreach ( $underperforming as $test_item ) {
$test_item->stop()->save();
$variation = new Thrive_AB_Variation( (int)$test_item->variation_id );
$meta = $variation->get_meta();
$removed_traffic += $meta->get( 'traffic' );
$meta->update( 'traffic', 0 );
$meta->update( 'status', 'archived' );
}
if ( sizeof( $leftovers ) == 1 ) {
$data = $leftovers[0]->get_data();
Thrive_AB_Ajax::set_winner( $data );
}
$extra_traffic = floor( $removed_traffic / sizeof( $leftovers ) );
foreach ( $leftovers as $test_item ) {
$variation = new Thrive_AB_Variation( (int)$test_item->variation_id );
$meta = $variation->get_meta();
$traffic = $meta->get( 'traffic' ) + $extra_traffic;
$meta->update( 'traffic', $traffic );
$last_test_item_meta = $meta;
}
$traffic_diff = $removed_traffic % sizeof( $leftovers );
if ( $traffic_diff ) {
$last_test_item_traffic = $last_test_item_meta->get( 'traffic' ) + $traffic_diff;
$last_test_item_meta->update( 'traffic', $last_test_item_traffic );
}
}
return true;
}
/**
* Bulk update the log table
*
* @param array $data
* @param array $where
*
* @return int|bool
*/
public static function bulk_update_log( $data = array(), $where = array() ) {
if ( empty( $data ) || empty( $where ) ) {
return false;
}
global $wpdb;
$update_rows = $wpdb->update( thrive_ab()->table_name( 'event_log' ), $data, $where );
return false !== $update_rows;
}
/**
* Bulk delete from log table
*
* @param array $where
*
* @return bool
*/
public static function bulk_delete_log( $where = array() ) {
if ( empty( $where ) ) {
return false;
}
global $wpdb;
$deleted_rows = $wpdb->delete( thrive_ab()->table_name( 'event_log' ), $where );
return false !== $deleted_rows;
}
/**
* Reset test data
*
* @param bool $test_id
*
* @return bool
*
* @throws Exception
*/
public static function reset_test_data( $test_id = false ) {
if ( empty( $test_id ) ) {
return false;
}
Thrive_AB_Event_Manager::bulk_delete_log( array( 'test_id' => $test_id ) );
$test_manager = new Thrive_AB_Test_Manager();
$items = $test_manager->get_items_by_filters( array( 'test_id' => $test_id ) );
foreach ( $items as $item ) {
$test_item = new Thrive_AB_Test_Item( $item );
$test_item->unique_impressions = 0;
$test_item->impressions = 0;
$test_item->conversions = 0;
$test_item->revenue = 0;
$test_item->save();
}
return true;
}
}
return Thrive_AB_Event_Manager::instance();

View File

@@ -0,0 +1,51 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Event extends Thrive_AB_Model {
/**
* @inheritdoc
*/
protected function _table_name() {
return thrive_ab()->table_name( 'event_log' );
}
/**
* @inheritdoc
*/
protected function is_valid() {
$is_valid = true;
if ( ! ( $this->page_id ) ) {
$is_valid = false;
} elseif ( ! ( $this->variation_id ) ) {
$is_valid = false;
} elseif ( ! ( $this->test_id ) ) {
$is_valid = false;
} elseif ( ! ( $this->event_type ) ) {
$is_valid = false;
}
return $is_valid;
}
public function is_impression() {
return 1 === $this->event_type;
}
public function is_conversion() {
return 2 === $this->event_type;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
return array(
'control' => __( 'Control', 'thrive-ab-page-testing' ),
'variation_added' => __( 'Variation Added', 'thrive-ab-page-testing' ),
'delete_title' => __( 'Yes, delete', 'thrive-ab-page-testing' ),
'archive_title' => __( 'Yes, archive', 'thrive-ab-page-testing' ),
'cancel' => __( 'Cancel', 'thrive-ab-page-testing' ),
'stop' => __( 'Stop', 'thrive-ab-page-testing' ),
'keep_it_running' => __( 'Keep It Running', 'thrive-ab-page-testing' ),
'add_variation_error' => __( 'Error adding new variation', 'thrive-ab-page-testing' ),
'variation_no' => __( 'Variation %s', 'thrive-ab-page-testing' ),
'about_to_delete' => __( 'You are about to delete %s. Do you want to continue?', 'thrive-ab-page-testing' ),
'about_to_archive' => __( 'You are about to archive %s. Do you want to continue?', 'thrive-ab-page-testing' ),
'about_to_stop_variation' => __( 'Are you sure you want to stop showing the variation: "%s"', 'thrive-ab-page-testing' ),
'invalid_test_title' => __( 'Invalid test title', 'thrive-ab-page-testing' ),
'invalid_min_win_conversions' => __( 'Invalid minimum conversions', 'thrive-ab-page-testing' ),
'not_number_min_win_conversions' => __( 'Minimum conversions is not number', 'thrive-ab-page-testing' ),
'greater_zero_min_win_conversions' => __( 'Minimum conversions must be greater than zero', 'thrive-ab-page-testing' ),
'invalid_auto_win_min_duration' => __( 'Minimum duration invalid', 'thrive-ab-page-testing' ),
'invalid_auto_win_chance_original' => __( 'Chance to beat original invalid', 'thrive-ab-page-testing' ),
'variation_status_not_changed' => __( 'Variation status could not be changed', 'thrive-ab-page-testing' ),
'variation_winner' => __( '<b>%s</b> was declared as being the winner for the current test.', 'thrive-ab-page-testing' ),
'choose_winner' => __( 'Choose winner variation', 'thrive-ab-page-testing' ),
'automatic_winner_settings' => __( 'Automatic winner settings', 'thrive-ab-page-testing' ),
'auto_win_enabled' => __( 'Automatic winner settings enabled.', 'thrive-ab-page-testing' ),
'auto_win_disabled' => __( 'Automatic winner settings disabled.', 'thrive-ab-page-testing' ),
'delete_variation' => __( 'Delete variation', 'thrive-ab-page-testing' ),
'archive_variation' => __( 'Archive variation', 'thrive-ab-page-testing' ),
'select_thank_you_page' => __( 'Select a thank you page', 'thrive-ab-page-testing' ),
'select_goal_page' => __( 'Select a goal page', 'thrive-ab-page-testing' ),
'select_measurement_option' => __( 'Select a measurement option', 'thrive-ab-page-testing' ),
);

View File

@@ -0,0 +1,409 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Test_Item extends Thrive_AB_Model {
/**
* @var Thrive_AB_Test_Item
*/
protected $control;
/**
* @return array
*/
public function get_data() {
return array(
'id' => $this->id,
'variation_id' => $this->variation_id,
'test_id' => $this->test_id,
'thankyou_id' => $this->thankyou_id,
'page_id' => $this->page_id,
'title' => $this->title,
'is_control' => (bool) $this->is_control,
'active' => $this->active,
'is_winner' => $this->is_winner,
'impressions' => $this->impressions,
'unique_impressions' => $this->unique_impressions,
'stopped_date' => date( 'j F Y', strtotime( $this->stopped_date ) ),
'preview_link' => $this->get_preview_link(),
'editor_link' => $this->get_editor_link(),
'traffic' => $this->get_traffic(),
'conversions' => $this->conversions,
'revenue' => $this->revenue,
'revenue_visitor' => $this->revenue_per_visitor(),
'conversion_rate' => $this->conversion_rate(),
'improvement' => $this->get_improvement(),
'chance_to_beat_orig' => $this->get_chance_to_beat_original(),
);
}
public function get_preview_link() {
$url = '';
/**@var $this ->>variation Thrive_AB_Variation */
if ( $this->variation instanceof Thrive_AB_Variation ) {
$url = $this->variation->get_preview_url();
}
return $url;
}
public function get_editor_link() {
$url = '';
/**@var $this ->>variation Thrive_AB_Variation */
if ( $this->variation instanceof Thrive_AB_Variation ) {
if ( current_user_can( 'edit_post', $this->variation->get_data()['ID'] ) ) {
$url = $this->variation->get_editor_url();
}
}
return $url;
}
public function get_traffic() {
$traffic = '';
/**@var $this ->>variation Thrive_AB_Variation */
if ( $this->variation instanceof Thrive_AB_Variation ) {
$traffic = (int) $this->variation->get_meta()->get( 'traffic' );
}
return $traffic;
}
/**
* @return mixed|null
*/
public function get_impressions() {
return $this->unique_impressions;
}
/**
* @return mixed|null
*/
public function get_conversions() {
return $this->conversions;
}
/**
* @return float
*/
public function get_chance_to_beat_original() {
$chance = $this->chance( $this->get_control()->conversion_rate(), $this->get_control()->unique_impressions );
if ( $chance === false ) {
return 0.0;
}
return $chance;
}
/**
* Returns the improvement for current test item
*
* @return float
*/
public function get_improvement() {
$control_conversion_rate = $this->get_control()->conversion_rate();
if ( $control_conversion_rate == 0 ) {
return 0;
}
return round( ( ( $this->conversion_rate() - $control_conversion_rate ) * 100 ) / $control_conversion_rate, 2 );
}
/**
* Calculates the revenue per visitor
*
* @return float
*/
public function revenue_per_visitor() {
$this->unique_impressions = (int) $this->unique_impressions;
$value = 0.0;
if ( $this->unique_impressions !== 0 ) {
$value = round( $this->revenue / $this->unique_impressions, 2 );
}
return $value;
}
/**
* Calculate conversion rate for current test item
*
* @return float
*/
public function conversion_rate() {
$conversions = (int) $this->conversions;
$impressions = (int) $this->unique_impressions;
$conversion_rate = 0.0;
if ( $conversions !== 0 && $impressions !== 0 ) {
$conversion_rate = round( 100 * ( $conversions / $impressions ), 2 );
}
return $conversion_rate;
}
/**
* Calculate the chance of current variation to beat the original during a test
*
* @param float $control_conversion_rate
* @param float $control_unique_impressions
*
* @return string
*/
public function chance( $control_conversion_rate, $control_unique_impressions ) {
if ( $this->unique_impressions == 0 || $control_unique_impressions == 0 ) {
return false;
}
$variation_conversion_rate = $this->conversion_rate() / 100;
$control_conversion_rate = (float) $control_conversion_rate / 100;
//standard deviation = sqrt((conversionRate*(1-conversionRate)/uniqueImpressions)
$variation_standard_deviation = sqrt( ( $variation_conversion_rate * ( 1 - $variation_conversion_rate ) / $this->unique_impressions ) );
$control_standard_deviation = sqrt( ( $control_conversion_rate * ( 1 - $control_conversion_rate ) / $control_unique_impressions ) );
if ( ( $variation_standard_deviation == 0 && $control_standard_deviation == 0 ) || ( is_nan( $variation_standard_deviation ) || is_nan( $control_standard_deviation ) ) ) {
return false;
}
//z-score = (control_conversion_rate - variation_conversion_rate) / sqrt((controlStandardDeviation^2)+(variationStandardDeviation^2))
$z_score = ( $control_conversion_rate - $variation_conversion_rate ) / sqrt( pow( $control_standard_deviation, 2 ) + pow( $variation_standard_deviation, 2 ) );
if ( is_nan( $z_score ) ) {
return false;
}
//Confidence_level (which is synonymous with “chance to beat original”) = normdist(z-score)
$confidence_level = $this->normal_distribution( $z_score );
if ( $confidence_level === false ) {
return false;
}
return number_format( round( ( 1 - $confidence_level ) * 100, 2 ), 2 );
}
/**
* Function that will generate a cumulative normal distribution and return the confidence level as a number between 0 and 1
*
* @param $x
*
* @return float
*/
protected function normal_distribution( $x ) {
$b1 = 0.319381530;
$b2 = - 0.356563782;
$b3 = 1.781477937;
$b4 = - 1.821255978;
$b5 = 1.330274429;
$p = 0.2316419;
$c = 0.39894228;
if ( $x >= 0.0 ) {
if ( ( 1.0 + $p * $x ) == 0 ) {
return false;
}
$t = 1.0 / ( 1.0 + $p * $x );
return ( 1.0 - $c * exp( - $x * $x / 2.0 ) * $t * ( $t * ( $t * ( $t * ( $t * $b5 + $b4 ) + $b3 ) + $b2 ) + $b1 ) );
}
if ( ( 1.0 - $p * $x ) == 0 ) {
return false;
}
$t = 1.0 / ( 1.0 - $p * $x );
return ( $c * exp( - $x * $x / 2.0 ) * $t * ( $t * ( $t * ( $t * ( $t * $b5 + $b4 ) + $b3 ) + $b2 ) + $b1 ) );
}
/**
* @inheritdoc
*/
protected function _table_name() {
return thrive_ab()->table_name( 'test_items' );
}
/**
* @inheritdoc
*/
protected function _get_default_data() {
$defaults = array(
'is_control' => 0,
'is_winner' => 0,
'impressions' => 0,
'unique_impressions' => 0,
'conversions' => 0,
'revenue' => 0.0,
'active' => true,
'stopped_date' => null,
);
return $defaults;
}
/**
* @inheritdoc
*/
protected function is_valid() {
$is_valid = true;
if ( ! ( $this->page_id ) ) {
$is_valid = false;
} elseif ( ! ( $this->variation_id ) ) {
$is_valid = false;
} elseif ( ! ( $this->test_id ) ) {
$is_valid = false;
} elseif ( ! ( $this->title ) ) {
$is_valid = false;
}
return $is_valid;
}
public function get_total_conversions( $test_id ) {
$sql = 'SELECT SUM(conversions) as total_conversions FROM ' . $this->_table_name() . ' WHERE test_id = %d LIMIT 1';
$params = array( $test_id );
return $this->wpdb->get_row( $this->wpdb->prepare( $sql, $params ) );
}
/**
* Init by filters
*
* @param array $filters
*
* @throws Exception
*/
public function init_by_filters( $filters = array() ) {
if ( empty( $filters ) ) {
throw new Exception( __( 'Invalid filters', 'thrive-ab-page-testing' ) );
}
$sql = 'SELECT * FROM ' . $this->_table_name() . ' WHERE 1 ';
$params = array();
if ( ! empty( $filters['id'] ) ) {
$sql .= 'AND `id` = %d ';
$params [] = $filters['id'];
}
if ( ! empty( $filters['page_id'] ) ) {
$sql .= 'AND `page_id` = %d ';
$params [] = $filters['page_id'];
}
if ( ! empty( $filters['variation_id'] ) ) {
$sql .= 'AND `variation_id` = %d ';
$params [] = $filters['variation_id'];
}
if ( ! empty( $filters['test_id'] ) ) {
$sql .= 'AND `test_id` = %d ';
$params [] = $filters['test_id'];
}
if ( ! empty( $filters['active'] ) ) {
$sql .= 'AND `active` = %d ';
$params [] = $filters['active'];
}
$sql_prepared = $this->wpdb->prepare( $sql, $params );
$result = $this->wpdb->get_row( $sql_prepared, ARRAY_A );
if ( ! empty( $result ) ) {
$this->_data = $result;
}
}
public function get_control() {
if ( $this->control instanceof Thrive_AB_Test_Item ) {
return $this->control;
}
$sql = 'SELECT * FROM ' . $this->_table_name() . ' WHERE is_control = 1 AND test_id = %d LIMIT 1';
$params = array( $this->test_id );
$sql_prepared = $this->wpdb->prepare( $sql, $params );
$result = $this->wpdb->get_row( $sql_prepared, ARRAY_A );
if ( ! empty( $result ) ) {
$this->control = new Thrive_AB_Test_Item( $result );
} else {
$this->control = new Thrive_AB_Test_Item();
}
return $this->control;
}
/**
* Stops a test item
*
* @throws Exception
*/
public function stop() {
$this->active = 0;
$this->stopped_date = date( 'Y-m-d H:i:s' );
return $this;
}
/**
* @inheritdoc
*/
protected function _prepare_data() {
$data = $this->_data;
$save_data = array(
'id' => null,
'page_id' => null,
'variation_id' => null,
'test_id' => null,
'thankyou_id' => null,
'goal_pages' => null,
'title' => null,
'is_control' => null,
'is_winner' => null,
'impressions' => null,
'unique_impressions' => null,
'conversions' => null,
'revenue' => null,
'active' => null,
'stopped_date' => null,
);
$save_data = array_intersect_key( $data, $save_data );
if ( empty( $save_data['id'] ) ) {
unset( $save_data['id'] );
}
$save_data['is_control'] = (int) $save_data['is_control'];
return $save_data;
}
}

View File

@@ -0,0 +1,278 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_AB_Test_Manager
*
* This class can be instantiate but it also has static methods to easily work with test models
*/
class Thrive_AB_Test_Manager {
public static $types
= array(
'monetary',
'visits',
'optins',
);
/**
* @var wpdb
*/
protected $_wpdb;
public function __construct() {
global $wpdb;
$this->_wpdb = $wpdb;
}
/**
* init some hooks
*/
public static function init() {
/**
* before TAr template_redirect which is at 0 priority
*/
// add_action( 'template_redirect', array( __CLASS__, 'template_redirect' ), - 1 );
}
/**
* redirects the user to post parent if he wants to edit the page with TAr
* and a test is running
*/
public static function template_redirect() {
if ( ! is_editor_page() ) {
return;
}
global $post;
$post_id = $post->ID;
/**
* if the posts is a variation
* check its parent for test
*/
if ( $post->post_type === Thrive_AB_Post_Types::VARIATION ) {
$post_id = $post->post_parent;
}
$instance = new Thrive_AB_Test_Manager();
$tests = $instance->get_running_test( $post_id );
if ( ! empty( $tests ) ) {
wp_redirect( get_permalink( $post_id ) );
die;
}
}
/**
* Store the model into db and return it
* If model has items prop set it tries to save those into db and push them into local _data
*
* @param $model
*
* @return Thrive_AB_Test
* @throws Exception
*/
public static function save_test( $model ) {
$test = new Thrive_AB_Test( $model );
$test->save();
try {
if ( ! empty( $model['items'] ) ) {
$test->items = array();
foreach ( $model['items'] as $item ) {
$item['test_id'] = $test->id;
$item['page_id'] = $test->page_id;
$test->save_item( $item );
}
}
} catch ( Exception $e ) {
$test->delete();
throw new Exception( $e->getMessage() );
}
if ( ! empty( $model['page_id'] ) ) {
$page = new Thrive_AB_Page( (int) $model['page_id'] );
if ( 'draft' === $page->post_status ) {
$page->get_post()->post_status = 'publish';
wp_update_post( $page->get_post() );
}
}
return $test;
}
/**
* Delete a test
*
* @param array $model
*/
public static function delete_test( $model = array() ) {
if ( empty( $model ) ) {
return;
}
$test = new Thrive_AB_Test( $model );
$test->delete();
}
/**
* Based on $filters a list of test models should be read from DB and returned
*
* @param array $filters
* @param string $type
*
* @return array
*/
public function get_tests( $filters = array(), $type = 'array' ) {
$tests = array();
$where = ' WHERE 1=1 ';
$filters = array_merge( array(), $filters );
$params = array();
if ( ! empty( $filters['page_id'] ) ) {
$where .= ' AND `page_id` = %s';
$params[] = $filters['page_id'];
}
if ( ! empty( $filters['status'] ) ) {
$where .= ' AND `status` = %s';
$params[] = $filters['status'];
}
if ( ! empty( $filters['id'] ) ) {
$where .= ' AND `id` = %s';
$params[] = $filters['id'];
}
$sql = 'SELECT * FROM ' . thrive_ab()->table_name( 'tests' ) . $where;
if ( ! empty( $params ) ) {
$sql = $this->_wpdb->prepare( $sql, $params );
}
$results = $this->_wpdb->get_results( $sql, ARRAY_A );
if ( ! empty( $results ) ) {
foreach ( $results as $test ) {
$tmp = new Thrive_AB_Test( $test );
$tests[] = $type === 'array' ? $tmp->get_data() : $tmp;
}
}
return $tests;
}
/**
* Returns an array of test items by filters
*
* @param array $filters
* @param string $output
*
* @return array|null|object
*/
public function get_items_by_filters( $filters = array(), $output = ARRAY_A ) {
$where = ' WHERE 1=1 ';
$sql = 'SELECT * FROM ' . thrive_ab()->table_name( 'test_items' ) . $where;
$params = array();
if ( ! empty( $filters['test_id'] ) ) {
$sql .= 'AND `test_id` = %d ';
$params [] = $filters['test_id'];
}
if ( ! empty( $filters['active'] ) ) {
$sql .= 'AND `active` = %d ';
$params [] = $filters['active'];
}
$sql_prepared = $this->_wpdb->prepare( $sql, $params );
$results = $this->_wpdb->get_results( $sql_prepared, $output );
return $results;
}
/**
* Get running test based on page_id
*
* @param int $page_id
*
* @return Thrive_AB_Test|null
*/
public function get_running_test( $page_id ) {
$filters = array(
'page_id' => $page_id,
'status' => 'running',
);
$tests = $this->get_tests( $filters, 'object' );
return empty( $tests ) ? null : reset( $tests );
}
protected static function get_goals( $goal = '' ) {
$goals = array(
'monetary' => array(
'icon' => 'monetary-2',
'label' => __( 'Goal one', 'thrive-ab-page-testing' ),
'name' => __( 'Revenue', 'thrive-ab-page-testing' ),
),
'visits' => array(
'icon' => 'visit_gp',
'label' => __( 'Goal two', 'thrive-ab-page-testing' ),
'name' => __( 'Visit goal page', 'thrive-ab-page-testing' ),
),
'optins' => array(
'icon' => 'subs',
'label' => __( 'Goal three', 'thrive-ab-page-testing' ),
'name' => __( 'Subscriptions', 'thrive-ab-page-testing' ),
),
);
return in_array( $goal, self::$types ) ? $goals[ $goal ] : $goals;
}
public static function display_goal_option( $goal ) {
$data = self::get_goals( $goal );
$icon = tcb_icon( $data['icon'], true, 'sidebar' );
$label = $data['label'];
$name = $data['name'];
include dirname( __FILE__ ) . '/../views/backbone/goals/goal.php';
}
/**
* @param $test_id int
*
* @return false|string
*/
public static function get_test_url( $test_id ) {
$url = add_query_arg( array(
'page' => 'tab_admin_view_test',
'test_id' => $test_id,
), admin_url( 'admin.php' ) ) . '#test';
return $url;
}
}
Thrive_AB_Test_Manager::init();

View File

@@ -0,0 +1,327 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_AB_Test
*
* - id int primary key
* - type string: monetary, visits, optins
* - page_id int
* - thank_you_id int
* - date_started datetime
* - date_completed datetime
* - title string
* - notes string
* - auto_win_enabled bool
* - auto_win_min_conversions int
* - auto_win_min_duration int days
* - auto_win_chance_original float
* - status string: running, completed, archived
*
* Dynamic properties
* - items array of test_items instances
*
* array associative which has indexes columns from DB
*/
class Thrive_AB_Test extends Thrive_AB_Model {
protected function _get_default_data() {
$_items_count = ! empty( $this->items ) && is_array( $this->items ) ? count( $this->items ) : 0;
$defaults = array(
'date_added' => date( 'Y-m-d H:i:s' ),
'date_started' => date( 'Y-m-d H:i:s' ),
'auto_win_enabled' => true,
'auto_win_min_conversions' => $this->_get_default_win_conversions( $_items_count ),
'auto_win_min_duration' => 14,
'auto_win_chance_original' => 95,
'status' => 'running',
'items' => array(),
);
return $defaults;
}
public function get_data() {
$data = array(
'id' => $this->id,
'goal_pages' => $this->goal_pages,
'page_id' => $this->page_id,
'title' => $this->title,
'notes' => $this->notes,
'type' => $this->type,
'auto_win_enabled' => $this->auto_win_enabled,
'auto_win_min_conversions' => $this->auto_win_min_conversions,
'auto_win_min_duration' => $this->auto_win_min_duration,
'auto_win_chance_original' => $this->auto_win_chance_original,
'date_started' => $this->date_started,
'date_completed' => $this->date_completed,
'status' => $this->status,
'items' => $this->items,
);
$items = array();
/** @var Thrive_AB_Test_Item $item */
foreach ( $this->items as $item ) {
$items[] = $item->get_data();
}
$data['items'] = $items;
if ( is_array( $data['goal_pages'] ) ) {
foreach ( $data['goal_pages'] as $key => &$page ) {
$page['permalink'] = get_permalink( $page['post_id'] );
$page['tcb_edit_url'] = tcb_get_editor_url( $page['post_id'] );
}
}
return $data;
}
/**
* @inheritdoc
*
* @return bool
*/
protected function is_valid() {
$is_valid = true;
if ( ! ( $this->page_id ) ) {
$is_valid = false;
} elseif ( ! ( $this->title ) ) {
$is_valid = false;
} elseif ( ! ( $this->type ) ) {
$is_valid = false;
}
return $is_valid;
}
/**
* @inheritdoc
*
* @return array
*/
protected function _prepare_data() {
$data = $this->_data;
if ( isset( $data['items'] ) ) {
unset( $data['items'] );
}
if ( ! empty( $data['goal_pages'] ) ) {
$data['goal_pages'] = maybe_serialize( $data['goal_pages'] );
}
//use goal_pages column from test tables to store monetary services
if ( ! empty( $data['service'] ) && 'visit_page' !== $data['service'] && 'monetary' === $data['type'] ) {
$data['goal_pages'] = $data['service'];
unset( $data['service'] );
}
if ( isset( $data['service'] ) ) {
unset( $data['service'] );
}
if ( empty( $data['id'] ) ) {
unset( $data['id'] );
}
return $data;
}
/**
* Calc default winning conversions based on how many items current test has
*
* @param $test_items_count int
*
* @return int
*/
protected function _get_default_win_conversions( $test_items_count ) {
return abs( ( $test_items_count - 1 ) * 100 );
}
/**
* @inheritdoc
*/
protected function _table_name() {
return thrive_ab()->table_name( 'tests' );
}
/**
* Save the model into db and push it into _data[items]
*
* @param $model
*
* @return Thrive_AB_Test_Item
*/
public function save_item( $model ) {
$item = new Thrive_AB_Test_Item( $model );
$item->save();
if ( ! $this->items || ! is_array( $this->items ) ) {
$this->items = array();
}
$this->_data['items'][] = $item;
return $item;
}
public function delete() {
delete_transient( Thrive_AB_Report_Manager::$_transient_stats_name );
parent::delete();
$this->delete_test_items();
/**
* Delete also log entries
*/
Thrive_AB_Event_Manager::bulk_delete_log( array( 'test_id' => $this->id ) );
}
public function get_items() {
if ( empty( $this->items ) ) {
global $wpdb;
$sql = $this->wpdb->prepare(
'SELECT *
FROM ' . thrive_ab()->table_name( 'test_items' ) . ' AS tt
INNER JOIN ' . $wpdb->prefix . 'posts AS p ON p.ID = tt.variation_id
WHERE test_id = %s ORDER BY is_control DESC',
array(
$this->id,
)
);
$items = $this->wpdb->get_results( $sql, ARRAY_A );
if ( count( $items ) ) {
$control = new Thrive_AB_Test_Item( $items[0] );
foreach ( $items as $key => $item ) {
$item['control'] = $control;
$item['variation'] = new Thrive_AB_Page_Variation( (int) $item['variation_id'] );
$items[ $key ] = new Thrive_AB_Test_Item( $item );
}
$this->items = $items;
}
}
return $this->items;
}
public function start() {
$this->status = 'running';
$this->date_started = date( 'Y-m-d H:i:s' );
if ( $this->page_id && $this->id ) {
try {
$page = new Thrive_AB_Page( (int) $this->page_id );
$page->get_meta()->update( 'running_test_id', $this->id );
} catch ( Exception $e ) {
}
}
if ( function_exists( 'tve_flush_cache' ) ) {
tve_flush_cache( $this->page_id );
}
/**
* purge cache for goal pages
*/
$goal_pages = is_array( $this->goal_pages ) ? $this->goal_pages : maybe_unserialize( $this->goal_pages );
$goal_pages = is_array( $goal_pages ) ? array_keys( $goal_pages ) : array();
foreach ( $goal_pages as $page_id ) {
if ( function_exists( 'tve_flush_cache' ) ) {
tve_flush_cache( $page_id );
}
}
return $this;
}
public function stop() {
$this->status = 'completed';
$this->date_completed = date( 'Y-m-d H:i:s' );
if ( $this->page_id && $this->id ) {
$page = new Thrive_AB_Page( (int) $this->page_id );
$page->get_meta()->update( 'running_test_id', false );
}
return $this;
}
protected function delete_test_items() {
try {
//try to delete test post variations
$items = $this->get_items();
/** @var Thrive_AB_Test_Item $item */
foreach ( $items as $key => $item ) {
if ( $item->variation && $item->variation instanceof Thrive_AB_Page_Variation ) {
$item->variation->delete();
}
}
} catch ( Exception $e ) {
}
$this->wpdb->delete( thrive_ab()->table_name( 'test_items' ), array( 'test_id' => $this->id ) );
}
/**
* Get goal pages
*
* @return array|mixed
*/
public function goal_pages() {
return ! empty( $this->_data['goal_pages'] ) ? maybe_unserialize( $this->_data['goal_pages'] ) : array();
}
public function set_goal_pages( $value ) {
$this->_data['goal_pages'] = maybe_unserialize( $value );
return $this->_data['goal_pages'];
}
public function has_goal_page( $post_id ) {
$goal_pages = $this->goal_pages();
return is_array( $goal_pages ) && in_array( $post_id, array_keys( $goal_pages ) );
}
public function get_goal_page_details( $id ) {
$goal_pages = $this->goal_pages();
$details = null;
if ( is_array( $goal_pages ) && ! empty( $goal_pages[ $id ] ) ) {
$details = $goal_pages[ $id ];
}
return $details;
}
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Page_Variation extends Thrive_AB_Variation {
}

View File

@@ -0,0 +1,237 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
/**
* Class Thrive_AB_Variation_Manager
*
* Applies logic based on info: page, variation(s)
*/
class Thrive_AB_Variation_Manager {
protected static $_instance;
/**
* Flag for overwriting the current query
*
* @var bool
*/
protected static $_querying_variations;
/**
* @var Thrive_AB_Test|null
*/
protected $_running_test;
protected function __construct() {
add_filter( 'the_posts', array( $this, 'the_posts' ), 10, 2 );
}
public static function instance() {
if ( empty( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Overwrite the queried post if the post is_singular(if it's page)
*
* @param $posts
* @param $wp_query WP_Query
*
* @return mixed
*/
public function the_posts( $posts, $wp_query ) {
$variation = null;
self::$_querying_variations = false;
if ( $this->should_determine_variation( $wp_query ) ) {
if ( function_exists( 'tve_do_not_cache_page' ) ) {
tve_do_not_cache_page();
}
$variation = $this->determine_variation();
// Reset the flag.
self::$_querying_variations = false;
/**
* enqueue the frontend script to allow
* - making conversions for html forms if the test type is 'optins' only
* - register lazy impressions on DOM Ready
*/
$js_suffix = defined( 'TVE_DEBUG' ) && TVE_DEBUG ? '.js' : '.min.js';
thrive_ab()->enqueue_script( 'tab-frontend', thrive_ab()->url( 'assets/js/dist/tab-frontend' . $js_suffix ), array(
'tve_frontend',
'tve-dash-frontend'
), true, true );
$localize_data = array(
'impression_data' => array(
'action' => Thrive_AB_Ajax::REGISTER_IMPRESSION_ACTION_NAME,
'test_id' => $this->_running_test->id,
'page_id' => $this->_running_test->page_id,
'variation_id' => (int) $variation->ID,
),
'test_type' => $this->_running_test->type,
);
if ( $this->_running_test->page_id != $variation->ID ) {
$variation_data['page_id'] = $this->_running_test->page_id;
$variation_data['variation_id'] = $variation->ID;
add_filter( 'tcb_lp_body_class', function ( $classes ) use ( $variation_data ) {
$classes .= ' page-id-' . $variation_data['variation_id'];
return $classes;
}, 10 );
}
wp_localize_script( 'tab-frontend', 'ThriveAB', $localize_data );
try {
/**
* let this here in case we need to implement option for user to register stats on server or lazy loading
* if there has to be on server side just uncomment next line
*/
//Thrive_AB_Event_Manager::do_impression( $this->_running_test->page_id, $this->_running_test->id, $variation->ID );
} catch ( Exception $e ) {
}
}
if ( self::$_querying_variations === false && isset( $variation ) ) {
$wp_query->post = $variation;
$posts = array( $variation );
}
return $posts;
}
/**
* Read the variations from DB and determine one to be displayed
* Call this function if there is a running test only so we are sure there is a test running on this context/instance
*
* @return WP_Post always
*/
protected function determine_variation() {
/**
* If a cookie is set with a certain variation, the same variation should be displayed
*/
$cookie_variation_id = Thrive_AB_Cookie_Manager::get_cookie( $this->_running_test->id, $this->_running_test->page_id, 1 );
$variation = $cookie_variation_id ? get_post( $cookie_variation_id ) : $this->_determine_traffic_variation();
if ( $variation === null ) {
$variation = get_post( $this->_running_test->page_id );
}
return $variation;
}
/**
* Checks if the current request should display variations content
*
* @param $wp_query WP_Query
*
* @return bool
*/
protected function should_determine_variation( $wp_query ) {
$should = function_exists( 'tve_dash_is_crawler' ) && ! tve_dash_is_crawler( true );
$should = $should && $wp_query->is_singular;
/**
* when user wants to edit a page with TAr which has variations
*/
$should = $should && defined( 'TVE_EDITOR_FLAG' ) && ! isset( $_GET[ TVE_EDITOR_FLAG ] );
/**
* if user wants to see the page variations dashboard
*/
$should = $should && ! thrive_ab()->is_dashboard();
/**
* if current user is not admin
*/
$should = $should && ! ( current_user_can( 'edit_posts' ) || Thrive_AB_Product::has_access() );
if ( $should ) {
$post = isset( $wp_query->posts[0] ) ? $wp_query->posts[0] : null;
Thrive_AB_Event_Manager::check_thank_you_page( $post );
$this->_init_test( $wp_query->queried_object_id ? $wp_query->queried_object_id : ( $post instanceof WP_Post ? $post->ID : null ) );
}
/**
* The control variation should be displayed if the AB Test is not running
*/
$should = $should && $this->_running_test instanceof Thrive_AB_Test;
return $should;
}
/**
* Based on traffic allocated on each variations return the corresponding one
* Please complete this doc based on todo
*
* @return WP_POST|null
*/
protected function _determine_traffic_variation() {
$variations = $this->query_variations();
$_rand = function_exists( 'mt_rand' ) ? mt_rand( 0, 101 ) : rand( 0, 101 );
$measurement = 0;
/**@var Thrive_AB_Variation $variation */
foreach ( $variations as $variation ) {
$traffic = $variation->get_meta()->get( 'traffic' );
if ( ( $_rand >= $measurement ) && ( $_rand < ( $measurement + $traffic ) ) ) {
return $variation->get_post();
}
$measurement += $traffic;
}
return null;
}
/**
* @param $filters array
*
* @return array|null
*/
protected function query_variations( $filters = array() ) {
$page = new Thrive_AB_Page( (int) $this->_running_test->page_id );
self::$_querying_variations = true;
return $page->get_variations( $filters, 'obj' );
}
protected function _init_test( $page_id ) {
if ( empty( $page_id ) ) {
return $this;
}
$test_manager = new Thrive_AB_Test_Manager();
$this->_running_test = $test_manager->get_running_test( $page_id );
return $this;
}
}
return Thrive_AB_Variation_Manager::instance();

View File

@@ -0,0 +1,334 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
class Thrive_AB_Variation extends Thrive_AB_Post {
protected $_test_item;
protected $_page;
/**
* Already loaded lightbox which have LG Element
*
* @var array
*/
private static $tcb_lightbox_ids = array();
public function get_data() {
$data = array(
'ID' => $this->_post->ID,
'post_title' => $this->_post->post_title,
'post_parent' => $this->_post->post_parent,
'preview_link' => $this->get_preview_url(),
'edit_link' => $this->get_editor_url(),
'thumb_link' => $this->get_thumb_link(),
'is_control' => $this->get_meta()->get( 'is_control' ),
'traffic' => $this->get_meta()->get( 'traffic' ),
'has_form' => $this->_has_form(),
);
return $data;
}
public function get_traffic() {
return $this->get_meta()->get( 'traffic' );
}
public function get_test_item() {
if ( ! $this->_test_item ) {
$this->_test_item = new Thrive_AB_Test_Item();
$this->_test_item->init_by_filters( array(
'page_id' => thrive_ab()->maybe_variation( $this->_post ) ? $this->_post->post_parent : $this->_post->ID,
'variation_id' => $this->_post->ID,
) );
}
return $this->_test_item;
}
/**
* Delete variation post with all its meta
* and if it's control then set the next variation in list as control
*
* @return bool
* @throws Exception
*/
public function delete() {
if ( $this->is_control() ) {
throw new Exception( 'Control cannot be deleted' );
}
$deleted = wp_delete_post( $this->_post->ID, true );
if ( $deleted === false || is_wp_error( $deleted ) ) {
throw new Exception( __( 'Variation could not be deleted', 'thrive-ab-page-testing' ) );
}
return true;
}
/**
* Gets the preview thumb for current variation
* if the thumb is a print screen then applies a random version number to the url
* to prevent browser cache
*
* @return null|string
*/
public function get_thumb_link() {
$args = array(
'v' => rand( 1000, 10000 ),
);
$thumb = $this->_get_print_screen_url();
if ( ! empty( $thumb ) ) {
$thumb = add_query_arg( $args, $thumb );
}
$thumb = ! empty( $thumb ) ? $thumb : $this->_get_landing_page_thumb_url();
$thumb = ! empty( $thumb ) ? $thumb : thrive_ab()->url( 'assets/images/default-variation.jpg' );
return $thumb;
}
/**
* Check if the variation has any landing page template set and try to
* return template's thumb url
*
* @return null|string
*/
protected function _get_landing_page_thumb_url() {
$url = null;
$landing_page_name = $this->get_meta()->get( 'tve_landing_page' );
$upload = wp_upload_dir();
if ( $landing_page_name && defined( 'TVE_CLOUD_LP_FOLDER' ) ) {
$thumb_file_path = trailingslashit( $upload['basedir'] ) . TVE_CLOUD_LP_FOLDER . '/templates/thumbnails/' . $landing_page_name . '.png';
}
if ( isset( $thumb_file_path ) && is_file( $thumb_file_path ) ) {
$url = trailingslashit( $upload['baseurl'] ) . TVE_CLOUD_LP_FOLDER . '/templates/thumbnails/' . $landing_page_name . '.png';
}
return $url;
}
/**
* Gets the print screen file url if file exists
*
* @return null|string
*/
protected function _get_print_screen_url() {
$url = null;
$wp_upload_dir = wp_get_upload_dir();
$filename = $this->ID . '.png';
$file_path = $wp_upload_dir['basedir'] . '/thrive-ab-page-testing/variations/' . $filename;
if ( is_file( $file_path ) ) {
$url = $wp_upload_dir['baseurl'] . '/thrive-ab-page-testing/variations/' . $filename;
}
return $url;
}
public function get_editor_url() {
if ( $this->_page instanceof WP_Post && $this->_page->post_status === 'draft' ) {
/**
* construct the url manually because WP doesn't see this post_status as draft or pending
*
* @see _get_page_link()
*/
$params = array(
'tve' => 'true',
'action' => 'architect',
);
$link = add_query_arg( $params, get_edit_post_link( $this->_post->ID ) );
} else {
$link = tcb_get_editor_url( $this->_post->ID );
}
return $link;
}
public function get_preview_url() {
$link = tcb_get_preview_url( $this->_post->ID );
return $link;
}
public function is_control() {
return (bool) $this->_post->is_control;
}
public function get_parent_ID() {
return $this->_post->post_parent;
}
public function save( $model ) {
$saved = wp_update_post( $model );
return ! is_wp_error( $saved ) && $saved !== 0;
}
/**
* @return bool
*/
protected function _has_form() {
/**
* TOP-108: Remove Subscription goal restriction
*
* For now, we removed this restriction.
*/
return true;
$content = $this->_get_content();
/**
* check if variation content has any LG ELement in content
*/
$has_form = strpos( $content, 'thrv_lead_generation_container' ) !== false;
/**
* Check for Leads ThriveBox
*/
$has_form = $has_form || strpos( $content, '[thrive_2step id' ) !== false;
$has_form = $has_form || strpos( $content, 'thrive_leads_2_step' ) !== false;
/**
* check if variation has a Thrive Lightbox assigned and Thrive Lightbox has LG Element in content
*/
$has_form = $has_form || $this->_parse_events( $content );
return $has_form;
}
/**
* @return string
*/
protected function _get_content() {
return $this->get_meta()->get( 'tve_updated_post' );
}
/**
* @param string $content
*
* @return bool if action content html has LG element
*/
protected function _parse_events( $content ) {
list( $start, $end ) = array(
'__TCB_EVENT_',
'_TNEVE_BCT__',
);
$event_pattern = "#data-tcb-events=('|\"){$start}(.+?){$end}('|\")#";
$triggers = tve_get_event_triggers();
$actions = tve_get_event_actions();
$registered_actions = array();
if ( preg_match_all( $event_pattern, $content, $matches, PREG_OFFSET_CAPTURE ) !== false ) {
foreach ( $matches[2] as $i => $data ) {
$m = htmlspecialchars_decode( $data[0] ); // the actual matched regexp group
if ( ! ( $_params = json_decode( $m, true ) ) ) {
$_params = array();
}
if ( empty( $_params ) ) {
continue;
}
foreach ( $_params as $event_config ) {
if ( empty( $event_config['t'] ) || empty( $event_config['a'] ) || ! isset( $triggers[ $event_config['t'] ] ) || ! isset( $actions[ $event_config['a'] ] ) ) {
continue;
}
$action = clone $actions[ $event_config['a'] ];
$registered_actions [] = array(
'class' => $action,
'event_config' => $event_config,
);
}
}
}
if ( ! empty( $registered_actions ) ) {
foreach ( $registered_actions as $data ) {
if ( ! empty( $data['class'] ) && $data['class'] instanceof TCB_Event_Action_Abstract ) {
$lightbox_id = $data['event_config']['config']['l_id'];
if ( in_array( $lightbox_id, self::$tcb_lightbox_ids ) ) {
return true;
}
$content_html = $data['class']->applyContentFilter( $data['event_config'] );
$has_form = strpos( $content_html, 'thrv_lead_generation_container' ) !== false;
if ( $has_form ) {
self::$tcb_lightbox_ids[] = $lightbox_id;
return true;
}
}
}
}
return false;
}
public function copy_thumb_to( $new_variation_id ) {
$new_filename = $new_variation_id . '.png';
add_filter( 'upload_dir', array( 'Thrive_AB_Ajax', 'upload_dir' ) );
$upload = wp_upload_dir();
$editor = wp_get_image_editor( $upload['path'] . '/' . $this->ID . '.png' );
if ( ! is_wp_error( $editor ) ) {
$editor->save( $upload['path'] . '/' . $new_filename );
}
remove_filter( 'upload_dir', array( 'Thrive_AB_Ajax', 'upload_dir' ) );
}
/**
* Set the parent page for current variation for checking
*
* @param $page WP_Post
*
* @return $this
* @see get_editor_url()
*
*/
public function set_page( $page ) {
if ( $page instanceof WP_Post && thrive_ab()->is_cpt_allowed( $page->post_type ) ) {
$this->_page = $page;
}
return $this;
}
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 1/16/2018
* Time: 11:05 AM
*/
?>
<ul class="clearfix">
<# links.each( function( item, index ) { item.has_link = index < links.size() - 1 #>
<li class="tvd-breadcrumb <#= ( item.has_link ? '' : ' tqb-no-link' ) #>">
<# if ( item.has_link ) { #><a href="<#= item.get_url() #>"><# } #>
<#= _.escape ( item.get ( 'label' ) ) #>
<# if ( item.has_link ) { #></a><# } #>
</li>
<# } ) #>
</ul>

View File

@@ -0,0 +1,21 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 1/16/2018
* Time: 5:18 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<td><#= model.get('title') #></td>
<td><#= model.get('date_completed_pretty') #></td>
<td><#= model.get('page_title') #></td>
<td><#= model.get('goal') #></td>
<td>
<a href="<#= model.get('test_link') #>"><?php echo __( 'View Test Details', 'thrive-ab-page-testing' ); ?></a>&nbsp;&nbsp;&nbsp;
<a href="javascript:void(0);" class="tab-delete-test"><?php echo __( 'Delete Test', 'thrive-ab-page-testing' ); ?></a>
</td>

View File

@@ -0,0 +1,11 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 1/19/2018
* Time: 10:16 AM
*/
?>
<tr>
<td style="text-align: center;" colspan="5"><?php echo __( 'You have no finished tests, yet.', 'thrive-ab-page-testing' ); ?></td>
</tr>

View File

@@ -0,0 +1,11 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 2/1/2018
* Time: 3:48 PM
*/
?>
<tr>
<td style="text-align: center;" colspan="5"><?php echo __( 'You have no completed test with that name', 'thrive-ab-page-testing' ); ?></td>
</tr>

View File

@@ -0,0 +1,180 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 1/16/2018
* Time: 2:18 PM
*/
?>
<div class="tab-center">
<div class="tvd-row">
<div class="tvd-col tvd-s12">
<span class="tab-dash-title"><?php echo __( 'Last 30 Days Stats', 'thrive-ab-page-testing' ); ?></span>
</div>
</div>
<div class="tvd-row">
<div class="tvd-col tvd-s12">
<span class="tab-dash-subtitle"><?php //echo __( '(Applies for running tests only)', 'thrive-ab-page-testing' ); ?></span>
</div>
</div>
</div>
<div class="tvd-row" style="margin-bottom: 40px">
<div class="tvd-col tvd-s4">
<div class="tab-overview-box">
<p class="tab-stats-text">
<span class="tvd-icon-eye tvd-stats-icon"></span>
<span><?php echo __( 'Total Unique Visitors', 'thrive-ab-page-testing' ); ?></span>
</p>
<hr>
<p class="tab-stats-number tab-stats-blue"><#= stats.unique_visitors #></p>
</div>
</div>
<div class="tvd-col tvd-s4">
<div class="tab-overview-box">
<p class="tab-stats-text">
<span class="tvd-icon-paper-plane tvd-stats-icon"></span>
<span><?php echo __( 'Total Conversions', 'thrive-ab-page-testing' ); ?></span>
</p>
<hr>
<p class="tab-stats-number tab-stats-blue"><#= stats.total_conversions #></p>
</div>
</div>
<div class="tvd-col tvd-s4">
<div class="tab-overview-box">
<p class="tab-stats-text">
<span class="tvd-icon-line-chart tvd-stats-icon"></span>
<span><?php echo __( 'Conversion Rate', 'thrive-ab-page-testing' ); ?></span>
</p>
<hr>
<p class="tab-stats-number tab-stats-green"><#= stats.conversion_rate #>%</p>
</div>
</div>
</div>
<hr>
<br>
<div class="tvd-row tab-no-margin">
<div class="tvd-col tvd-s6">
<h3><?php echo __( 'Running A/B Tests Overview', 'thrive-ab-page-testing' ); ?></h3>
</div>
<div class="tvd-col tvd-s6 tab-right">
<div class="tvd-input-field tvd-prefix tvd-input-field-limit">
<i class="tvd-icon-search"></i>
<input type="text" class="tab-running-search-input tvd-no-margin" placeholder="<?php echo __( 'Search tests...', 'thrive-ab-page-testing' ); ?>" value=""/>
</div>
</div>
</div>
<div class="tvd-row">
<div class="tvd-col tvd-s12">
<table class="tvd-collection">
<thead>
<tr>
<td>
<div class="tvd-truncate-on-small" data-popup="<?php echo __( 'Test Name', 'thrive-ab-page-testing' ); ?>">
<h5 class="tvd-truncate-on-small-el"><?php echo __( 'Test Name', 'thrive-ab-page-testing' ); ?></h5>
</div>
</td>
<td>
<div class="tvd-truncate-on-small" data-popup="<?php echo __( 'Date Started', 'thrive-ab-page-testing' ); ?>">
<h5 class="tvd-truncate-on-small-el"><?php echo __( 'Date Started', 'thrive-ab-page-testing' ); ?></h5>
</div>
</td>
<td>
<div class="tvd-truncate-on-small" data-popup="<?php echo __( 'On Page', 'thrive-ab-page-testing' ); ?>">
<h5 class="tvd-truncate-on-small-el"><?php echo __( 'On Page', 'thrive-ab-page-testing' ); ?></h5>
</div>
</td>
<td>
<div class="tvd-truncate-on-small" data-popup="<?php echo __( 'Test Goal', 'thrive-ab-page-testing' ); ?>">
<h5 class="tvd-truncate-on-small-el">
<?php echo __( 'Test Goal', 'thrive-ab-page-testing' ); ?>
</h5>
</div>
</td>
<td>
<div class="tvd-truncate-on-small" data-popup="<?php echo __( 'Unique Visitors', 'thrive-ab-page-testing' ); ?>">
<h5 class="tvd-truncate-on-small-el"><?php echo __( 'Unique Visitors', 'thrive-ab-page-testing' ); ?></h5>
</div>
</td>
<td>
<div class="tvd-truncate-on-small" data-popup="<?php echo __( 'Conversions', 'thrive-ab-page-testing' ); ?>">
<h5 class="tvd-truncate-on-small-el">
<?php echo __( 'Conversions', 'thrive-ab-page-testing' ); ?>
</h5>
</div>
</td>
<td>
<div class="tvd-truncate-on-small" data-popup="<?php echo __( 'Actions', 'thrive-ab-page-testing' ); ?>">
<h5 class="tvd-truncate-on-small-el">
<?php echo __( 'Actions', 'thrive-ab-page-testing' ); ?>
</h5>
</div>
</td>
</tr>
</thead>
<tbody class="tab-running-test-items-list"></tbody>
</table>
</div>
</div>
<div class="tvd-row">
<div class="tvd-col tvd-s6 tvd-offset-s6 tab-running-pagination"></div>
</div>
<div class="tvd-row tab-no-margin">
<div class="tvd-col tvd-s6">
<h3><?php echo __( 'Completed Tests', 'thrive-ab-page-testing' ); ?></h3>
</div>
<div class="tvd-col tvd-s6 tab-right">
<div class="tvd-input-field tvd-prefix tvd-input-field-limit">
<i class="tvd-icon-search"></i>
<input type="text" class="tab-completed-search-input tvd-no-margin" placeholder="<?php echo __( 'Search tests...', 'thrive-ab-page-testing' ); ?>" value=""/>
</div>
</div>
</div>
<div class="tvd-row">
<div class="tvd-col tvd-s12">
<table class="tvd-collection">
<thead>
<tr>
<td>
<div class="tvd-truncate-on-small" data-popup="<?php echo __( 'Test Name', 'thrive-ab-page-testing' ); ?>">
<h5 class="tvd-truncate-on-small-el"><?php echo __( 'Test Name', 'thrive-ab-page-testing' ); ?></h5>
</div>
</td>
<td>
<div class="tvd-truncate-on-small" data-popup="<?php echo __( 'End Date', 'thrive-ab-page-testing' ); ?>">
<h5 class="tvd-truncate-on-small-el"><?php echo __( 'End Date', 'thrive-ab-page-testing' ); ?></h5>
</div>
</td>
<td>
<div class="tvd-truncate-on-small" data-popup="<?php echo __( 'On Page', 'thrive-ab-page-testing' ); ?>">
<h5 class="tvd-truncate-on-small-el"><?php echo __( 'On Page', 'thrive-ab-page-testing' ); ?></h5>
</div>
</td>
<td>
<div class="tvd-truncate-on-small" data-popup="<?php echo __( 'Test Goal', 'thrive-ab-page-testing' ); ?>">
<h5 class="tvd-truncate-on-small-el">
<?php echo __( 'Test Goal', 'thrive-ab-page-testing' ); ?>
</h5>
</div>
</td>
<td>
<div class="tvd-truncate-on-small" data-popup="<?php echo __( 'Actions', 'thrive-ab-page-testing' ); ?>">
<h5 class="tvd-truncate-on-small-el">
<?php echo __( 'Actions', 'thrive-ab-page-testing' ); ?>
</h5>
</div>
</td>
</tr>
</thead>
<tbody class="tab-completed-test-items-list"></tbody>
</table>
</div>
</div>
<div class="tvd-row">
<div class="tvd-col tvd-s6 tvd-offset-s6 tab-completed-pagination"></div>
</div>

View File

@@ -0,0 +1,30 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-modal-content">
<p>
<#= this.data.description #>
</p>
</div>
<div class="tvd-modal-footer">
<div class="tvd-row">
<div class="tvd-col tvd-s12 tvd-m6">
<a href="javascript:void(0)" class="tvd-btn-flat tvd-btn-flat-primary tvd-btn-flat-light tvd-modal-close tvd-waves-effect">
<#= this.data.btn_no_txt #>
</a>
</div>
<div class="tvd-col tvd-s12 tvd-m6">
<a href="javascript:void(0)" class="tvd-waves-effect tvd-waves-light tvd-btn-flat tvd-btn-flat-primary tvd-btn-flat-light tvd-right tvd-modal-submit">
<#= this.data.btn_yes_txt #>
</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,33 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 1/16/2018
* Time: 5:36 PM
*/
?>
<div class="tvd-right">
<span class="tvd-inline-block"><strong><?php echo __('Rows per page:','thrive-ab-page-testing' ); ?></strong></span>
<div class="tvd-input-field tvd-input-field-small tvd-inline-block tab-pagination-select">
<select class="tab-items-per-page">
<option value="10" <# if(itemsPerPage == 10) { #> selected="selected" <# } #>>10</option>
<option value="15" <# if(itemsPerPage == 15) { #> selected="selected" <# } #>>15</option>
<option value="30" <# if(itemsPerPage == 30) { #> selected="selected" <# } #>>30</option>
<option value="50" <# if(itemsPerPage == 50) { #> selected="selected" <# } #>>50</option>
</select>
</div>
<div class="tvd-inline-block ">
<strong>
<#= (currentPage-1)*itemsPerPage #> - <#= currentPage * itemsPerPage > total_items ? total_items : currentPage * itemsPerPage #>
<?php echo __('of','thrive-ab-page-testing' ) ?> <#= total_items #>
</strong>
</div>
<div id="pages" class="tvd-inline-block tab-pagination-icons">
<# if( pageCount > 1) { #>
<a <# if(currentPage > 1) { #> class="page" value="<#= currentPage - 1 #>" <# } #>> <span class="tab-icon-pagination tvd-icon-chevron-left"></span></a>
<a <# if(currentPage < pageCount) { #> class="page" value="<#= (currentPage + 1) #>" <# } #>> <span class="tab-icon-pagination tvd-icon-chevron-left tab-next-pagination"></span></a>
<# } #>
</div>
</div>

View File

@@ -0,0 +1,15 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 1/16/2018
* Time: 4:35 PM
*/
?>
<td><#= model.get('title') #></td>
<td><#= model.get('date_started_pretty') #></td>
<td><#= model.get('page_title') #></td>
<td><#= model.get('goal') #></td>
<td><#= model.get('unique_impressions') #></td>
<td><#= model.get('conversions') #></td>
<td><a href="<#= model.get('test_link') #>"><?php echo __( 'View Test Details', 'thrive-ab-page-testing' ); ?></a></td>

View File

@@ -0,0 +1,11 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 1/19/2018
* Time: 10:17 AM
*/
?>
<tr>
<td style="text-align: center;" colspan="7"><?php echo __( 'You have no running tests, yet.', 'thrive-ab-page-testing' ); ?></td>
</tr>

View File

@@ -0,0 +1,11 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 2/1/2018
* Time: 3:47 PM
*/
?>
<tr>
<td style="text-align: center;" colspan="7"><?php echo __( 'You have no running test with that name', 'thrive-ab-page-testing' ); ?></td>
</tr>

View File

@@ -0,0 +1,25 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 1/16/2018
* Time: 9:23 AM
*/
?>
<div id="thrive-ab-top-bar" class="thrive-ab-logo-holder" style="margin-left: -20px">
<div class="thrive-ab-logo">
<span></span>
</div>
<?php do_action( 'tvd_notification_inbox' ); ?>
</div>
<div class="td-app-notification-overlay overlay close "></div>
<div class="td-app-notification-drawer">
<div class="td-app-notification-holder">
<div class="td-app-notification-header notification-header-notify-t-optimize"></div>
<div class="td-app-notification-wrapper notification-wrapper-notify-t-optimize"></div>
<div class="notification-footer notification-footer-notify-t-optimize"></div>
</div>
</div>
<div id="tab-breadcrumbs-wrapper"></div>
<?php echo tvd_get_individual_plugin_license_message( new Thrive_AB_Product(), true ); ?>
<div id="tab-admin-dashboard-wrapper"></div>

View File

@@ -0,0 +1,25 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 11/21/2017
* Time: 9:03 AM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
$singular = isset( $singular ) ? $singular : null;
?>
<table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
<thead>
<tr>
<?php $this->print_column_headers(); ?>
</tr>
</thead>
<tbody id="top-the-list"<?php echo $singular ? " data-wp-lists='list:$singular'" : ''; ?>>
<?php $this->display_rows_or_placeholder(); ?>
</tbody>
</table>

View File

@@ -0,0 +1,38 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 11/18/2017
* Time: 7:31 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
$singular = isset( $singular ) ? $singular : null;
$start_test_link = $this->_page->get_start_test_url();
/** @var Thrive_AB_Meta_Box_Variations_Table $this */
?>
<table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
<thead>
<tr>
<?php $this->print_column_headers(); ?>
</tr>
</thead>
<tbody id="top-the-list"<?php echo $singular ? " data-wp-lists='list:$singular'" : ''; ?>>
<?php $this->display_rows_or_placeholder(); ?>
</tbody>
</table>
<?php if ( $this->_pagination_args['total_items'] > 0 ) : ?>
<div class="thrv-ab-action-button-wrapper">
<?php if ( count( $this->_page_tests ) > 0 ) : ?>
<?php $view_test_link = $this->_page->get_test_link( $this->_page_tests[0]['id'] ) ?>
<p><span></span><?php echo __( 'Changes occurred while a test is running can sometimes invalidate the test results.', 'thrive-ab-page-testing' ); ?></p>
<a class="thrv-ab-action-button" href="<?php echo $view_test_link; ?>"><?php echo __( 'View Test Details', 'thrive-ab-page-testing' ); ?></a>
<?php else : ?>
<a class="thrv-ab-action-button" href="<?php echo $start_test_link . '#dashboard/start-test'; ?>"><?php echo __( 'Set Up & Start A/B Test', 'thrive-ab-page-testing' ); ?></a>
<?php endif; ?>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,21 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
$plugin_name = 'Thrive Optimize';
$tar_name = 'Thrive Architect';
?>
<div class="notice notice-error">
<p>
<?php echo __( sprintf( '%s is not active on your site and you cannot use %s', $tar_name, $plugin_name ), 'thrive-ab-page-testing' ) ?>
</p>
</div>

View File

@@ -0,0 +1,20 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
$tar_name = 'Thrive Architect';
$tar_required_version = Thrive_AB_Checker::get_tar_required_version();
?>
<div class="notice notice-error">
<p>
<?php echo __( sprintf( 'Version of %s is not the required one: %s! Please update it before.', $tar_name, $tar_required_version ), 'thrive-ab-page-testing' ) ?>
</p>
</div>

View File

@@ -0,0 +1,32 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 1/18/2018
* Time: 5:26 PM
*/
tve_enqueue_style( 'tve_architect_edit_links', tve_editor_css() . '/thrive-architect-edit-links.css' );
global $post;
$view_test_link = '';
try {
$page = new Thrive_AB_Page( (int) $post->ID );
$test_id = $page->get_meta()->get( 'running_test_id' );
$start_test_link = $page->get_start_test_url();
$view_test_link = $start_test_link . '&test-id=' . $test_id . '#test';
} catch ( Exception $e ) {
}
?>
<!--<a class="thrive-architect-edit-link tcb-enable-editor thrive-architect-edit-disabled">-->
<!-- <div class="thrive-architect-admin-icon-holder">-->
<!-- <div class="thrive-architect-admin-icon"></div>-->
<!-- </div>-->
<!-- <div class="thrive-architect-admin-text">-->
<!-- --><?php //echo __( 'Edit with Thrive Architect', 'thrive-ab-page-testing' ) ?>
<!-- </div>-->
<!--</a>-->
<!-- TOP-143 <p style="display: inline;">--><?php //echo sprintf( __( 'Page editing is disabled while the A/B test is running. Click <a href="%s">here</a> to manage/end the test and enable editing again.', 'thrive-ab-page-testing' ), $view_test_link ); ?><!--</p>-->

View File

@@ -0,0 +1,63 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 11/27/2017
* Time: 9:46 AM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
global $post;
?>
<div id="thrive-ab-top-bar" class="tvd-row">
<div class="tvd-col tvd-s2 thrive-ab-logo">
<a href="<?php echo tcb_get_editor_url( $post ) ?>"><span><?php echo __( 'Thrive', 'thrive-ab-page-testing' ) ?></span> <?php echo __( 'Architect', 'thrive-ab-page-testing' ) ?>
<div class="tvd-icon-chevron-left"></div>
</a>
</div>
<div class="tvd-col tvd-s10 thrive-ab-settings">
<a href="<?php echo get_edit_post_link( $post->ID, '' ) ?>">
<div class="tvd-icon-cog"></div>
<span><?php echo __( 'Page Settings', 'thrive-ab-page-testing' ) ?></span>
</a>
<a href="javascript:void(0)" id="thrive-ab-start-test" class="click" data-fn="start_test">
<div class="tvd-icon-eye"></div>
<span><?php echo $post->post_status === 'publish' ? __( 'Set Up & Start A/B Test', 'thrive-ab-page-testing' ) : __( 'Set Up & Start A/B Test', 'thrive-ab-page-testing' ) ?></span>
</a>
</div>
</div>
<div class="clearfix">
<div class="thrive-ab-heading">
<h1><?php echo __( 'Variations', 'thrive-ab-page-testing' ) ?></h1>
<button class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-blue click" data-fn="add_new_variation"><?php echo __( 'Add new', 'thrive-ab-page-testing' ) ?></button>
<p><?php echo __( 'You can duplicate an existing variation or create a new one from scratch. You can later edit the created variations, even though the test is running.', 'thrive-ab-page-testing' ) ?></p>
<a id="thrive-ab-eq-traffic" class="tvd-btn-flat tvd-btn-flat-primary tvd-btn-flat-dark click" data-fn="equalize_traffic" href="javascript:void(0)">
<span><?php echo __( 'Distribute traffic evenly', 'thrive-ab-page-testing' ) ?></span>
</a>
</div>
<div class="tvd-row thrive-ab-card-list" id="thrive-ab-card-list">
<div class="tvd-col tvd-l3 tvd-m6 click" data-fn="add_new_variation">
<div class="tvd-card tvd-small tvd-card-new tvd-valign-wrapper">
<div class="tvd-card-content tvd-valign tvd-center-align">
<i class="tvd-icon-plus tvd-icon-rounded tvd-icon-medium"></i>
<h4>
<?php echo __( 'Add new variation', 'thrive-ab-page-testing' ) ?>
</h4>
</div>
</div>
</div>
</div>
<div class="thrive-ab-heading thrive-ab-display-archived-container">
<a class="click thrive-ab-display-archived" data-fn="display_archived" href="javascript:void(0)">
<span><?php echo __( 'Archived Variations', 'thrive-ab-page-testing' ) ?></span>
<span class="tar-arrow"></span>
</a>
<p>
<?php echo __( 'You can un archive a variation in order to reuse it in your test.', 'thrive-ab-page-testing' ) ?>
</p>
</div>
<div class="tvd-row thrive-ab-card-list" id="thrive-ab-card-list-archived" style="display:none;">
</div>
</div>

View File

@@ -0,0 +1,39 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<h2 class="tcb-modal-title"><?php echo __( 'Apply changes: reset test data?' ) ?></h2>
<div class="row">
<div class="col col-xs-12">
<p><?php echo __( "You are about to save changes to a page in a running test. Note that major design changes will invalidate the data gathered in this test so far. For this reason, we recommend that you reset the test data to zero (the test will continue running).", 'thrive-ab-page-testing' ) ?></p>
</div>
</div>
<div class="tcb-gray">
<div class="row">
<div class="col-xs-12">
<label class="tcb-checkbox padding-bottom-10">
<input type="checkbox" id="thrive-ab-reset-stats" checked="checked">
<span><?php echo __( "Reset current test stats", 'thrive-cb' ) ?></span>
</label>
</div>
</div>
</div>
<div class="tcb-modal-footer padding-top-20 control-grid">
<button type="button" class="tcb-left tve-button text-only tcb-modal-cancel">
<?php echo __( 'Cancel', 'thrive-cb' ) ?>
</button>
<button type="button" class="tcb-right tve-button medium tcb-modal-save">
<?php echo __( 'Save variation and update test', 'thrive-cb' ) ?>
</button>
</div>

View File

@@ -0,0 +1,25 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
$icon = isset( $icon ) ? $icon : '';
$name = isset( $name ) ? $name : '';
$goal = isset( $goal ) ? $goal : '';
?>
<div class="tvd-col tvd-s4 thrive-ab-goal" data-goal="<?php echo $goal ?>">
<div class="thrive-ab-goal-card">
<div class="thrive-ab-goal-icon">
<span>
<?php echo $icon ?>
</span>
</div>
<p><?php echo $name; ?></p>
</div>
</div>

View File

@@ -0,0 +1,62 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="thrive-ab-adv-settings">
<div class="tvd-row">
<div class="tvd-col tvd-s12 thrive-ab-no-padding">
<?php echo __( 'Measure revenue when...', 'thrive-ab-page-testing' ); ?>
</div>
<select name="service" id="thrive-ab-monetary-services">
<option value=""><?php echo __( 'Select how you would like to measure revenue', 'thrive-ab-page-testing' ); ?></option>
</select>
</div>
<div class="thrive-ab-monetary-service" id="sendowl">
<p>
<?php
/* translators: */
echo sprintf( __( '%s will receive revenue data automatically from SendOwl when a purchase is made.', 'thrive-ab-page-testing' ), thrive_ab()->plugin_name() );
?>
</p>
<p>
<?php
$admin_url = add_query_arg(
array(
'page' => 'tva_dashboard',
),
network_admin_url( 'admin.php' )
);
$link = '<a target="_blank" href="' . $admin_url . '#sendowl_quick_start">' . __( 'setup steps', 'thrive-ab-page-testing' ) . '</a>';
/* translators: */
echo sprintf( __( 'Make sure you complete all the SendOwl %s in Thrive Apprentice for the integration to work.', 'thrive-ab-page-testing' ), $link );
?>
</p>
</div>
<div class="thrive-ab-monetary-service" id="visit_page">
<div class="tvd-row">
<div class="tvd-col tvd-s12 thrive-ab-no-padding">
<?php echo __( 'Select one or more pages from your website, on which the user will land, and write the corresponding value of that conversion for your business. You can also create a new page and edit later.', 'thrive-ab-page-testing' ); ?>
</div>
</div>
<div id="item-forms" class="tvd-row tvd-collapse"></div>
<div class="tvd-row tvd-collapse">
<div class="tvd-col tvd-s12">
<div class="tvd-card tvd-small tvd-card-new thrive-ab-add-new-goal tvd-valign-wrapper">
<div class="tvd-card-content tvd-valign tvd-center-align">
<i class="tvd-icon-plus tvd-icon-rounded tvd-icon-medium"></i>
<h4>
<?php echo __( 'Add new thank you page', 'thrive-ab-page-testing' ); ?>
</h4>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,14 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<p>
<?php echo __( 'Measure the number of visitors who subscribe to your website. Please make sure you add at least one Lead Generation form on each variation for the conversions to be counted.', 'thrive-ab-page-testing' ); ?>
</p>

View File

@@ -0,0 +1,38 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row tvd-collapse">
<div class="tvd-col tvd-s2">
<span class="thrive-ab-variation-name">
<# if( test.get('type')=='monetary' ) { #>
<?php echo __( 'Thank You Page', 'thrive-ab-page-testing' ) ?>
<# } else { #>
<?php echo __( 'Goal Page', 'thrive-ab-page-testing' ) ?>
<# } #>
</span>
</div>
<div class="tvd-col tvd-s5 page-search"></div>
<div class="tvd-col tvd-s3" <#= test.get('type')=='monetary'? '':'style="display:none;"' #>>
<label for="revenue-<#= item.cid #>" class="thrive-ab-value-label">
<?php echo __( 'Value', 'thrive-ab-page-testing' ) ?>
</label>
</div>
<div class="tvd-col tvd-s2" <#= test.get('type')=='monetary'? '':'style="display:none;"' #>>
<div class="tvd-input-field">
<input id="revenue-<#= item.cid #>" type="number" value="<#= item.get('revenue')? item.get('revenue'):0 #>" data-bind="revenue">
<label><?php echo __( '$', 'thrive-ab-page-testing' ) ?></label>
</div>
</div>
</div>

View File

@@ -0,0 +1,27 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-switch">
<label>
<span class="thrive-ab-switch">
<?php echo __( 'One page for all variations', 'thrive-ab-page-testing' ) ?>
</span>
<input id="multi-page" type="checkbox" class="change" data-fn="switcher_changed">
<span class="tvd-lever">
<i></i>
<i></i>
</span>
<span class="thrive-ab-switch thrive-ab-inactive">
<?php echo __( 'Use separate pages for variations', 'thrive-ab-page-testing' ) ?>
</span>
</label>
</div>

View File

@@ -0,0 +1,31 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="thrive-ab-adv-settings">
<div class="tvd-row">
<div class="tvd-col tvd-s12 thrive-ab-no-padding">
<?php echo __( 'Select one or more pages, from your website, on which the user will land. You can also create a new page and edit later.', 'thrive-ab-page-testing' ) ?>
</div>
</div>
<div id="item-forms" class="tvd-row tvd-collapse"></div>
<div class="tvd-row tvd-collapse">
<div class="tvd-col tvd-s12">
<div class="tvd-card tvd-small tvd-card-new thrive-ab-add-new-goal tvd-valign-wrapper">
<div class="tvd-card-content tvd-valign tvd-center-align">
<i class="tvd-icon-plus tvd-icon-rounded tvd-icon-medium"></i>
<h4>
<?php echo __( 'Add new goal page', 'thrive-ab-page-testing' ) ?>
</h4>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,35 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-card tvd-white">
<div class="tvd-card-content">
<div class="thrive-ab-card-head tvd-row">
<div class="tvd-col tvd-s10">
<div class="thrive-ab-title-content">
<span class="thrive-ab-card-title">
<#= item.get('post_title') #>
</span>
</div>
</div>
<div class="thrive-ab-card-options tvd-col tvd-s2 thrive-ab-card-actions">
<a href="<#= item.get('preview_link') #>" target="_blank" class="tvd-tooltipped" data-tooltip="<?php echo __( 'Preview', 'thrive-ab-page-testing' ); ?>" data-position="top">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
<a class="tvd-icon-trash-o click tvd-tooltipped" data-tooltip="<?php echo __( 'Permanently delete variation', 'thrive-ab-page-testing' ); ?>" data-position="top" data-fn="delete"></a>
</div>
</div>
<div class="thrive-ab-card-thumb" style="background-image: url('<#= item.get('thumb_link') #>')"></div>
<div class="thrive-ab-card-footer tvd-row">
<a class="click" data-fn="restore"><?php echo __( 'Restore Variation', 'thrive-ab-page-testing' ) ?></a>
</div>
</div>
</div>

View File

@@ -0,0 +1,50 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-card tvd-white">
<div class="tvd-card-content">
<div class="thrive-ab-card-head tvd-row">
<div class="tvd-col tvd-s9">
<div class="thrive-ab-title-content">
<span class="thrive-ab-card-title">
<#= item.get('post_title') #>
</span>
<span id="thrive-ab-control"><#= item.get('is_control') ? '[ Control ]' : '' #></span>
<a href="javascript:void(0)" class="<#= item.get('is_control') ? '' : 'tvd-icon-pencil' #> click tvd-tooltipped" data-tooltip="<?php echo __( 'Edit variation name', 'thrive-ab-page-testing' ); ?>" data-position="top" data-fn="edit_title"></a>
</div>
<div class="thrive-ab-title-editor"></div>
</div>
<div class="thrive-ab-card-options tvd-col tvd-s3 thrive-ab-card-actions">
<a class="tvd-icon-copy click tvd-tooltipped" data-tooltip="<?php echo __( 'Duplicate this variation', 'thrive-ab-page-testing' ); ?>" data-position="top" data-fn="duplicate"></a>
<a class="tvd-icon-trash-o tab-archive click tvd-tooltipped" data-tooltip="<?php echo __( 'Archive variation', 'thrive-ab-page-testing' ); ?>" data-position="top" data-fn="archive" style="<#= item.get('is_control') ? 'display:none;' : '' #>"></a>
<a class="tvd-icon-trash-o click tvd-tooltipped" data-tooltip="<?php echo __( 'Permanently delete variation', 'thrive-ab-page-testing' ); ?>" data-position="top" data-fn="delete" style="<#= item.get('is_control') ? 'display:none;' : '' #>"></a>
</div>
</div>
<div class="thrive-ab-card-thumb" style="background-image: url('<#= item.get('thumb_link') #>')">
<div>
<a href="<#= item.get('edit_link') #>" class=""><?php echo __( 'Edit Variation', 'thrive-ab-page-testing' ) ?></a>
</div>
</div>
<div class="thrive-ab-card-footer tvd-row">
<div class="tvd-col tvd-s2">
<label for="thrive-ab-card-traffic-input"><?php echo __( 'Traffic', 'thrive-ab-page-testing' ) ?></label>
</div>
<div class="tvd-col tvd-s8 thrive-ab-variation-traffic-slider">
<input type="range" class="input change" min="0" max="100" data-fn="on_change" data-fn-input="on_input" value="<#= parseInt(item.get('traffic')) #>">
</div>
<div class="tvd-col tvd-s2 thrive-ab-variation-traffic-input">
<input class="thrive-ab-card-traffic-input input change" data-fn="on_change" data-fn-input="on_input" type="number" min="0" max="100"
value="<#= parseInt(item.get('traffic')) #>">
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,24 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-modal-content">
<h3><?php echo __( 'Revenue Conversion Goal', 'thrive-ab-page-testing' ); ?></h3>
<p><?php echo __( 'Each time a customer visits any of the pages listed below, the associated revenue is recorded', 'thrive-ab-page-testing' ); ?></p>
<div class="thrive-ap-goal-pages"></div>
</div>
<div class="tvd-modal-footer">
<div class="tvd-row">
<div class="tvd-col tvd-center tvd-s12">
<a href="javascript:void(0)" class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-green tvd-modal-close">
<?php echo __( 'OK', 'thrive-ab-page-testing' ); ?>
</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,25 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-modal-content">
<h3><?php echo __( 'Subscription Conversion Goal', 'thrive-ab-page-testing' ); ?></h3>
<div class="top-modal-pwsvg">
<?php tcb_icon('subs'); ?>
<p><?php echo __( 'A subscription to any form on your test variations is counted as a conversion', 'thrive-ab-page-testing' ); ?></p>
</div>
</div>
<div class="tvd-modal-footer">
<div class="tvd-row">
<div class="tvd-col tvd-center tvd-s12">
<a href="javascript:void(0)" class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-green tvd-modal-close">
<?php echo __( 'OK', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,17 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s6">
<span> <#= model.get( 'post_title' ) #> </span>
</div>
<div class="tvd-col tvd-s6">
<a href="<#= model.get( 'permalink' ) #>" target="_blank" class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-green top-conv-page">
<?php echo __( 'View Page', 'thrive-ab-page-testing' ); ?>
</a>
</div>
</div>

View File

@@ -0,0 +1,21 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s6">
<span> <#= model.get( 'post_title' ) #> </span>
</div>
<div class="tvd-col tvd-s1">
<span>$&nbsp;<#= model.get( 'revenue' ) #></span>
</div>
<div class="tvd-col tvd-s5">
<a href="<#= model.get( 'permalink' ) #>" target="_blank" class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-green top-conv-page">
<?php echo __( 'View Page', 'thrive-ab-page-testing' ); ?>
</a>
</div>
</div>

View File

@@ -0,0 +1,22 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-modal-content">
<h3><?php echo __( 'Revenue Conversion Goal', 'thrive-ab-page-testing' ); ?></h3>
<p class="top-sendowl-p"><?php echo __( 'Conversions and revenues are collected whenever a customer purchases a product through SendOwl', 'thrive-ab-page-testing' ); ?></p>
</div>
<div class="tvd-modal-footer">
<div class="tvd-row">
<div class="tvd-col tvd-center tvd-s12">
<a href="javascript:void(0)" class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-green tvd-modal-close">
<?php echo __( 'OK', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,24 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-modal-content">
<h3><?php echo __( 'Page Visit Conversion Goal', 'thrive-ab-page-testing' ); ?></h3>
<p><?php echo __( 'A visit to any of the pages listed below is counted as one conversion:', 'thrive-ab-page-testing' ); ?></p>
<div class="thrive-ap-goal-pages"></div>
</div>
<div class="tvd-modal-footer">
<div class="tvd-row">
<div class="tvd-col tvd-center tvd-s12">
<a href="javascript:void(0)" class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-green tvd-modal-close">
<?php echo __( 'OK', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,30 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-modal-content">
<p>
<#= this.data.description #>
</p>
</div>
<div class="tvd-modal-footer">
<div class="tvd-row">
<div class="tvd-col tvd-s12 tvd-m6">
<a href="javascript:void(0)" class="tvd-btn-flat tvd-btn-flat-primary tvd-btn-flat-light tvd-modal-close tvd-waves-effect">
<#= this.data.btn_no_txt #>
</a>
</div>
<div class="tvd-col tvd-s12 tvd-m6">
<a href="javascript:void(0)" class="tvd-waves-effect tvd-waves-light tvd-btn-flat tvd-btn-flat-primary tvd-btn-flat-light tvd-right tvd-modal-submit">
<#= this.data.btn_yes_txt #>
</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,32 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 12/14/2017
* Time: 1:06 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-modal-content">
<p><?php echo __( 'Here you can set the conditions by which a variation will be considered the winner. When a variation is considered the winner, the remaining variations will be archived and all traffic will be sent to the winner.', 'thrive-ab-page-testing' ) ?></p>
<br>
<?php include dirname( __FILE__ ) . '/html-test-automatic-winner.php'; ?>
</div>
<div class="tvd-modal-footer">
<div class="tvd-row">
<div class="tvd-col tvd-s6">
<a href="javascript:void(0)" class="tvd-btn-flat tvd-btn-flat-secondary tvd-btn-flat-dark tvd-waves-effect tvd-modal-close">
<?php echo __( 'Cancel', 'thrive-ab-page-testing' ) ?>
</a>
</div>
<div class="tvd-col tvd-s6">
<a href="javascript:void(0)" class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-green tvd-right tvd-modal-submit">
<?php echo __( 'Save Settings', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,30 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-modal-content">
<p>
<#= this.data.description #>
</p>
</div>
<div class="tvd-modal-footer">
<div class="tvd-row">
<div class="tvd-col tvd-s12 tvd-m6">
<a href="javascript:void(0)" class="tvd-btn-flat tvd-btn-flat-primary tvd-btn-flat-light tvd-modal-close tvd-waves-effect">
<#= this.data.btn_no_txt #>
</a>
</div>
<div class="tvd-col tvd-s12 tvd-m6">
<a href="javascript:void(0)" class="tvd-waves-effect tvd-waves-light tvd-btn-flat tvd-btn-flat-primary tvd-btn-flat-light tvd-right tvd-modal-submit">
<#= this.data.btn_yes_txt #>
</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,49 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 12/14/2017
* Time: 1:00 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row tvd-collapse">
<div class="tvd-col tvd-s12">
<span class="tab-label"><?php echo __( 'Enable Automatic Winner Settings', 'thrive-ab-page-testing' ) ?></span>
<div class="tvd-switch">
<label class="tvd-active">
<input type="checkbox" id="auto-win-enabled" data-bind="auto_win_enabled">
<span class="tvd-lever"></span>
</label>
</div>
</div>
</div>
<div id="auto-win-settings">
<span><?php echo __( 'Here you can set the conditions by which a form will be considered the winner.', 'thrive-ab-page-testing' ) ?></span>
<div class="tvd-row tvd-gray">
<div class="tvd-col tvd-s4">
<div class="tvd-input-field">
<input type="text" maxlength="4" id="auto_win_min_conversions" data-bind="auto_win_min_conversions"
value="<#= this.model.get('auto_win_min_conversions') #>">
<label for="auto_win_min_conversions"><?php echo __( 'Minimum conversions', 'thrive-ab-page-testing' ) ?></label>
</div>
</div>
<div class="tvd-col tvd-s4">
<div class="tvd-input-field">
<input type="text" maxlength="2" id="auto_win_min_duration" data-bind="auto_win_min_duration"
value="<#= this.model.get('auto_win_min_duration') #>">
<label for="auto_win_min_duration" class=""><?php echo __( 'Minimum duration (days)', 'thrive-ab-page-testing' ) ?></label>
</div>
</div>
<div class="tvd-col tvd-s4">
<div class="tvd-input-field">
<input type="text" maxlength="3" id="auto_win_chance_original" data-bind="auto_win_chance_original"
value="<#= this.model.get('auto_win_chance_original') #>">
<label for="auto_win_chance_original" class=""><?php echo __( 'Chance to beat original (%)', 'thrive-ab-page-testing' ) ?></label>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,27 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row tvd-collapse">
<div class="tvd-col tvd-s12">
<ul class="tvd-tabs">
<li class="tvd-tab">
<a href="javascript:void(0)" class="tvd-active">
<?php echo __( '1. Personalize your A/B Test', 'thrive-ab-page-testing' ) ?>
</a>
</li>
<li class="tvd-tab tvd-disabled">
<a href="javascript:void(0)">
<?php echo __( '2. Set the goal of the test', 'thrive-ab-page-testing' ) ?>
</a>
</li>
</ul>
</div>
</div>

View File

@@ -0,0 +1,77 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-modal-step thrive-ab-start-test">
<h3 class="tvd-modal-title"><?php echo __( 'Starting your A/B test', 'thrive-ab-page-testing' ) ?></h3>
<div class="tvd-modal-content">
<?php include dirname( __FILE__ ) . '/html-test-steps.php' ?>
<div class="thrive-ab-content">
<p><?php echo __( 'Set your test details below', 'thrive-ab-page-testing' ) ?></p>
<div class="tvd-input-field">
<input type="text" id="title" data-bind="title" value="<#= this.model.get('title') #>">
<label for="title" class=""><?php echo __( 'Split Test Name', 'thrive-ab-page-testing' ) ?></label>
</div>
<div class="tvd-input-field">
<textarea class="tvd-materialize-textarea" data-bind="notes"><#= this.model.get('notes') #></textarea>
<label for="tvd-ar-install-url" class=""><?php echo __( 'Short Description', 'thrive-ab-page-testing' ) ?></label>
</div>
<?php include dirname( __FILE__ ) . '/html-test-automatic-winner.php'; ?>
</div>
</div>
<div class="tvd-modal-footer">
<div class="tvd-row">
<div class="tvd-col tvd-s12 tvd-m6">
<a href="javascript:void(0)"
class="tvd-btn-flat tvd-btn-flat-secondary tvd-btn-flat-dark tvd-waves-effect tvd-modal-close">
<?php echo __( 'Cancel', 'thrive-ab-page-testing' ) ?>
</a>
</div>
<div class="tvd-col tvd-s12 tvd-m6">
<a href="javascript:void(0)"
class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-green tvd-right tvd-modal-next-step thrive-ab-next">
<?php echo __( 'Next', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>
</div>
</div>
<div class="tvd-modal-step thrive-ab-start-test thrive-ab-step-2">
<h3 class="tvd-modal-title"><?php echo __( 'Starting your A/B test', 'thrive-ab-page-testing' ) ?></h3>
<div class="tvd-modal-content">
<?php include dirname( __FILE__ ) . '/html-test-steps.php' ?>
<div class="tvd-row thrive-ab-set-goal">
<?php foreach ( Thrive_AB_Test_Manager::$types as $type ) : ?>
<?php Thrive_AB_Test_Manager::display_goal_option( $type ); ?>
<?php endforeach; ?>
</div>
<div id="thrive-ab-goal-settings"></div>
</div>
<div class="tvd-modal-footer">
<div class="tvd-row">
<div class="tvd-col tvd-s12 tvd-m6">
<a href="javascript:void(0)"
class="tvd-btn-flat tvd-btn-flat-secondary tvd-btn-flat-dark tvd-waves-effect tvd-modal-prev-step thrive-ab-prev">
<?php echo __( 'Back', 'thrive-ab-page-testing' ) ?>
</a>
</div>
<div class="tvd-col tvd-s12 tvd-m6">
<a href="javascript:void(0)"
class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-green tvd-right tvd-modal-submit">
<?php echo __( 'Start A/B Test', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,28 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-modal-content">
<h3 class="tvd-modal-title tab-modal-title">
<?php echo __( 'Choose Winner Landing Page', 'thrive-ab-page-testing' ) ?>
</h3>
<div id="test-view"></div>
</div>
<div class="tvd-modal-footer">
<div class="tvd-row">
<div class="tvd-col tvd-s12 tvd-m6">
<a href="javascript:void(0)"
class="tvd-btn-flat tvd-btn-flat-secondary tvd-btn-flat-dark tvd-waves-effect tvd-modal-close">
<?php echo __( 'Cancel', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,35 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-modal-content">
<div class="tvd-green">
<span class="tvd-icon-check"></span>
</div>
<p><?php echo __( 'Test completed!' ) ?></p>
<div class="tab-relative">
<?php echo tcb_icon( 'winner', true, 'sidebar' ) ?>
<span><#= this.model.get('improvement') #>%</span>
<p>
<#= this.model.get('label') #>
</p>
</div>
</div>
<div class="tvd-modal-footer">
<div class="tvd-row">
<div class="tvd-col tvd-s12 tvd-center">
<a href="javascript:void(0)"
class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-green tvd-modal-submit">
<?php echo __( 'Go to test report', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,39 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s2">
<span><#= item.get('title') #></span>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s2">
<#= item.get('conversion_rate') #>%
</div>
<div class="tvd-col tvd-s2 <#= item.get('is_control')? '': ( item.get('improvement') >= 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' ) #>">
<#= item.get('is_control')? 'N/A' : item.get('improvement')+'%' #>
</div>
<div class="tvd-col tvd-s2 <#= item.get('is_control')? '': ( item.get('chance_to_beat_orig') >= 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' ) #>">
<#= item.get('is_control')? 'N/A' : item.get('chance_to_beat_orig')+'%' #>
</div>
<div class="tvd-col tvd-s1">
<a href="javascript:void(0)" class="click" data-fn-click="set_as_winner">
<?php echo __( 'Set as winner', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>

View File

@@ -0,0 +1,23 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="thrive-ab-test-header">
<div class="tvd-row">
<div class="tvd-col tvd-s2"><?php echo __( 'Variation Name', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Content Views', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Engagements', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2"><?php echo __( 'Engagement Rate', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2"><?php echo __( 'Percentage Improvement', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2"><?php echo __( 'Chance to beat Original', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2">&nbsp;</div>
</div>
</div>
<div class="thrive-ab-test-items"></div>

View File

@@ -0,0 +1,40 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s2">
<span><#= item.get('title') #></span>
<span class="tvd-gray-accent"><#= item.get('is_control')? '(control)' : '' #></span>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') == 0 ? 'N/A' : item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') == 0 ? 'N/A' : item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue') == 0 ? 'N/A' : parseFloat(item.get('revenue')).toFixed(2) #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue_visitor') == 0 ? 'N/A' : parseFloat(item.get('revenue_visitor')).toFixed(2) #>
</div>
<div class="tvd-col tvd-s2 <#= item.get('is_control') || !item.get('improvement') ? '' : ( item.get('improvement') > 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' ) #>">
<#= item.get('is_control') || !item.get('improvement') ? 'N/A' : parseFloat(item.get('improvement')).toFixed(2)+'%' #>
</div>
<div class="tvd-col tvd-s2 <#= item.get('is_control') || !item.get('chance_to_beat_orig') ? '' : ( item.get('chance_to_beat_orig') > 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' ) #>">
<#= item.get('is_control') || !item.get('chance_to_beat_orig') ? 'N/A' : parseFloat(item.get('chance_to_beat_orig')).toFixed(2) + '%' #>
</div>
<div class="tvd-col tvd-s2 tvd-right-align">
<a href="javascript:void(0)" class="click" data-fn-click="set_as_winner">
<?php echo __( 'Set as winner', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>

View File

@@ -0,0 +1,40 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s2">
<span><#= item.get('title') #></span>
<span class="tvd-gray-accent"><#= item.get('is_control')? '(control)' : '' #></span>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') == 0 ? 'N/A' : item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') == 0 ? 'N/A' : item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') == 0 ? 'N/A' : item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') == 0 ? 'N/A' : parseFloat(item.get('conversion_rate')).toFixed(2) + '%' #>
</div>
<div class="tvd-col tvd-s2 <#= item.get('is_control') || !item.get('improvement') ? '' : ( item.get('improvement') > 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' ) #>">
<#= item.get('is_control') || !item.get('improvement') ? 'N/A' : parseFloat(item.get('improvement')).toFixed(2)+'%' #>
</div>
<div class="tvd-col tvd-s2 <#= item.get('is_control') || !item.get('chance_to_beat_orig') ? '' : ( item.get('chance_to_beat_orig') > 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' ) #>">
<#= item.get('is_control') || !item.get('chance_to_beat_orig') ? 'N/A' : parseFloat(item.get('chance_to_beat_orig')).toFixed(2) + '%' #>
</div>
<div class="tvd-col tvd-s2 tvd-right-align">
<a href="javascript:void(0)" class="click" data-fn-click="set_as_winner">
<?php echo __( 'Set as winner', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>

View File

@@ -0,0 +1,40 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s2">
<span><#= item.get('title') #></span>
<span class="tvd-gray-accent"><#= item.get('is_control')? '(control)' : '' #></span>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') == 0 ? 'N/A' : item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') == 0 ? 'N/A' : item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') == 0 ? 'N/A' : item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') == 0 ? 'N/A' : parseFloat(item.get('conversion_rate')).toFixed(2) + '%' #>
</div>
<div class="tvd-col tvd-s2 <#= item.get('is_control') || !item.get('improvement') ? '' : ( item.get('improvement') > 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' ) #>">
<#= item.get('is_control') || !item.get('improvement') ? 'N/A' : parseFloat(item.get('improvement')).toFixed(2)+'%' #>
</div>
<div class="tvd-col tvd-s2 <#= item.get('is_control') || !item.get('chance_to_beat_orig') ? '' : ( item.get('chance_to_beat_orig') > 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' ) #>">
<#= item.get('is_control') || !item.get('chance_to_beat_orig') ? 'N/A' : parseFloat(item.get('chance_to_beat_orig')).toFixed(2) + '%' #>
</div>
<div class="tvd-col tvd-s2 tvd-right-align">
<a href="javascript:void(0)" class="click" data-fn-click="set_as_winner">
<?php echo __( 'Set as winner', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>

View File

@@ -0,0 +1,24 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="thrive-ab-test-header">
<div class="tvd-row">
<div class="tvd-col tvd-s2"><?php echo __( 'Name', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Visitors', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Unique Visitors', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Revenue', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Revenue per visitor', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2"><?php echo __( 'Improvement', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2"><?php echo __( 'Chance to beat Original', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2">&nbsp;</div>
</div>
</div>
<div class="thrive-ab-test-items"></div>

View File

@@ -0,0 +1,24 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="thrive-ab-test-header">
<div class="tvd-row">
<div class="tvd-col tvd-s2"><?php echo __( 'Name', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Visitors', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Unique Visitors', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Subscriptions', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Subscription Rate', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2"><?php echo __( 'Improvement', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2"><?php echo __( 'Chance to beat Original', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2">&nbsp;</div>
</div>
</div>
<div class="thrive-ab-test-items"></div>

View File

@@ -0,0 +1,24 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="thrive-ab-test-header">
<div class="tvd-row">
<div class="tvd-col tvd-s2"><?php echo __( 'Name', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Visitors', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Unique Visitors', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Conversions', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Conversion Rate', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2"><?php echo __( 'Improvement', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2"><?php echo __( 'Chance to beat Original', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2">&nbsp;</div>
</div>
</div>
<div class="thrive-ab-test-items"></div>

View File

@@ -0,0 +1,45 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 11/27/2017
* Time: 3:09 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<td>
<#= model.get('post_title') #>
<a href="<#= model.get('preview_link') #>" target="_blank"><?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?></a>
</td>
<td>
<#= model.get('traffic') #>
</td>
<td>
<#= model.get('visitors') #>
</td>
<td>SALES!? WTF IS SALES?</td>
<td>
<#= model.get('revenue') #>
</td>
<td>
<#= model.get('revenue_visitor') #>
</td>
<td>COnversion RATE</td>
<# if( model.get('is_control') ) { #>
<td colspan="2" class="thrv-ab-variation-control">[ <?php echo __( 'This is the control', 'thrive-ab-page-testing' ); ?> ]</td>
<# }else{ #>
<td>
<#= model.get('improvement') #>
</td>
<td>
<#= model.get('chance_to_beat_orig') #>
<a class="tvd-tooltipped tvd-right click" href="javascript:void(0);" data-fn="stop_variation" data-tooltip="<?php echo __( 'Stop this variation', 'thrive-ab-page-testing' ); ?>" data-position="top">
<i class="tvd-icon-stop tvd-text-red" style="font-size: 16px;"></i>
</a>
</td>
<# } #>

View File

@@ -0,0 +1,100 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 11/27/2017
* Time: 11:21 AM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div id="thrive-ab-top-bar" class="tvd-row thrive-ab-logo-holder">
<div class="tvd-col tvd-s12 thrive-ab-logo">
<a href="<?php echo admin_url( 'admin.php?page=tab_admin_dashboard' ); ?>" class="logo-holder"></a>
</div>
</div>
<?php echo tvd_get_individual_plugin_license_message( new Thrive_AB_Product(), true ); ?>
<div class="tvd-row thrive-ab-container">
<div class="tvd-col tvd-s12">
<h1 class="thrive-ab-variation-title">
<#= model.get('title') #>
</h1>
</div>
</div>
<div class="tvd-row thrive-ab-container">
<div class="tvd-col tvd-s4 tvd-m6">
<#= model.get('notes') #>&nbsp;
</div>
<div class="tvd-col tvd-s2 tvd-m1">
<label for="tve-chart-interval-select" class="thrive-ab-interval-label">
<?php echo __( 'Graph type', 'thrive-ab-page-testing' ); ?>:
</label>
</div>
<div class="tvd-col tvd-s2 tvd-m2">
<div class="tve-chart-interval">
<div class="tvd-input-field">
<select autocomplete="off" class="change tab-graph-type" data-fn="update_chart">
<option value="conversion_rate"><?php echo __( 'Conversion rate', 'thrive-ab-page-testing' ); ?></option>
<option value="conversion"><?php echo __( 'Conversions', 'thrive-ab-page-testing' ); ?></option>
</select>
</div>
</div>
</div>
<div class="tvd-col tvd-s2 tvd-m1">
<label for="tve-chart-interval-select" class="thrive-ab-interval-label">
<?php echo __( 'Graph interval', 'thrive-ab-page-testing' ); ?>:
</label>
</div>
<div class="tvd-col tvd-s2 tvd-m2">
<div class="tve-chart-interval">
<div class="tvd-input-field">
<select autocomplete="off" class="change tab-graph-interval" data-fn="update_chart">
<option selected value="day"><?php echo __( 'Daily', 'thrive-ab-page-testing' ); ?></option>
<option value="week"><?php echo __( 'Weekly', 'thrive-ab-page-testing' ); ?></option>
<option value="month"><?php echo __( 'Monthly', 'thrive-ab-page-testing' ); ?></option>
</select>
</div>
</div>
</div>
</div>
<div class="tvd-relative tvd-row thrive-ab-container" id="thrive-ab-chart">
<div class="tvd-col tvd-s10">
<div id="tab-test-chart"></div>
</div>
<div class="tvd-col tvd-s2 thrive-ab-chart-info">
<p id="thrive-ab-chart-title">
<#= ThriveAB.test_chart.title #>
</p>
<p id="thrive-ab-chart-total-value">
<#= ThriveAB.test_chart.total_over_time #> <#= ThriveAB.test_chart.test_type_txt #>
</p>
</div>
</div>
<div id="thrive-ab-test" class="thrive-ab-container"></div>
<div class="tvd-relative tvd-row" style="display: <#= model.get('status') === 'running' ? 'block' : 'none' #>">
<div class="tvd-col tvd-s8">
<a href="<#= edit_page_link #>" class="tvd-btn-flat tvd-btn-flat-primary tvd-btn-flat-dark tvd-waves-effect">
&laquo; <?php echo __( 'Back to Page Settings', 'thrive-ab-page-testing' ) ?></a>
</div>
<div class="tvd-col tvd-s4">
<div class="tvd-right" id="thrive-ab-stop-test">
<a class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-green click" href="javascript:void(0)" data-fn="stop_test"
title="<?php echo __( 'Stop test and choose winner', 'thrive-ab-page-testing' ) ?>"><?php echo __( 'Stop test and choose winner', 'thrive-ab-page-testing' ) ?></a>
</div>
</div>
</div>
<div class="tvd-relative tvd-row" style="display: <#= model.get('status') === 'completed' ? 'block' : 'none' #>">
<div class="tvd-col tvd-s12">
<div class="tvd-right" id="thrive-ab-stop-test">
<a class="tvd-waves-effect tvd-waves-light tvd-btn tvd-btn-green click" href="<#= edit_page_link #>">
<?php echo __( 'Page settings', 'thrive-ab-page-testing' ) ?>
</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,65 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s2 tab-headline">
<span class="tab-truncate">
<a class="thrive-ab-editor-link"><#= item.get('title') #></a>
<# if( table_model.get('status') === 'completed' && parseInt(item.get('is_winner')) === 1 ) { #>
&nbsp;<span class="tab-winner-label">(<?php echo __( 'winner', 'thrive-ab-page-testing' ); ?>)</span>
<# } #>
</span>
<span class="tab-edit-controls">
<a href="<#= item.get('preview_link') #>" target="_blank">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
<# if ( table_model.get('status') !== 'completed' && item.get('editor_link') ) { #>
<a href="<#= item.get('editor_link') #>" class="top-edit-icon tvd-tooltipped" data-tooltip="<?php echo __( 'Edit variation with Architect', 'thrive-ab-page-testing' ); ?>" data-position="top"></a>
<# } #>
</span>
</div>
<div class="tvd-col tvd-s2">
<# if( table_model.get('status') === 'completed') { #>
<#= parseInt(item.get('traffic')) #>%
<# }else{ #>
<div class="thrive-ab-test-item-traffic tvd-row">
<div class="tvd-col tvd-s8 thrive-ab-variation-traffic-slider">
<input type="range" class="input change" min="0" max="100" data-fn="on_change" data-fn-input="on_input" value="<#= parseInt(item.get('traffic')) #>">
</div>
<div class="tvd-col tvd-s4 thrive-ab-variation-traffic-input">
<input class="thrive-ab-card-traffic-input input change" data-fn="on_change" data-fn-input="on_input" type="number" min="0" max="100"
value="<#= parseInt(item.get('traffic')) #>">
</div>
</div>
<# } #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue_visitor') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') #>%
</div>
<div class="tvd-col tvd-s2 tab-control-indicator">
<?php echo __( '[This is the Control]', 'thrive-ab-page-testing' ) ?>
</div>
</div>

View File

@@ -0,0 +1,59 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s3 tab-headline">
<span class="tab-truncate">
<a class="thrive-ab-editor-link"><#= item.get('title') #></a>
<# if( table_model.get('status') === 'completed' && parseInt(item.get('is_winner')) === 1 ) { #>
&nbsp;<span class="tab-winner-label">(<?php echo __( 'winner', 'thrive-ab-page-testing' ); ?>)</span>
<# } #>
</span>
<span class="tab-edit-controls">
<a href="<#= item.get('preview_link') #>" target="_blank">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
<# if ( table_model.get('status') !== 'completed' && item.get('editor_link') ) { #>
<a href="<#= item.get('editor_link') #>" class="top-edit-icon tvd-tooltipped" data-tooltip="<?php echo __( 'Edit variation with Architect', 'thrive-ab-page-testing' ); ?>" data-position="top"></a>
<# } #>
</span>
</div>
<div class="tvd-col tvd-s2">
<# if( table_model.get('status') === 'completed') { #>
<#= parseInt(item.get('traffic')) #>%
<# }else{ #>
<div class="thrive-ab-test-item-traffic tvd-row">
<div class="tvd-col tvd-s8 thrive-ab-variation-traffic-slider">
<input type="range" class="input change" min="0" max="100" data-fn="on_change" data-fn-input="on_input" value="<#= parseInt(item.get('traffic')) #>">
</div>
<div class="tvd-col tvd-s4 thrive-ab-variation-traffic-input">
<input class="thrive-ab-card-traffic-input input change" data-fn="on_change" data-fn-input="on_input" type="number" min="0" max="100"
value="<#= parseInt(item.get('traffic')) #>">
</div>
</div>
<# } #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') #>%
</div>
<div class="tvd-col tvd-s3 tab-control-indicator">
<?php echo __( '[This is the Control]', 'thrive-ab-page-testing' ) ?>
</div>
</div>

View File

@@ -0,0 +1,59 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s3 tab-headline">
<span>
<a class="thrive-ab-editor-link"><#= item.get('title') #></a>
<# if( table_model.get('status') === 'completed' && parseInt(item.get('is_winner')) === 1 ) { #>
&nbsp;<span class="tab-winner-label">(<?php echo __( 'winner', 'thrive-ab-page-testing' ); ?>)</span>
<# } #>
</span>
<span class="tab-edit-controls">
<a href="<#= item.get('preview_link') #>" target="_blank">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
<# if ( table_model.get('status') !== 'completed' && item.get('editor_link') ) { #>
<a href="<#= item.get('editor_link') #>" class="top-edit-icon tvd-tooltipped" data-tooltip="<?php echo __( 'Edit variation with Architect', 'thrive-ab-page-testing' ); ?>" data-position="top"></a>
<# } #>
</span>
</div>
<div class="tvd-col tvd-s3">
<# if( table_model.get('status') === 'completed') { #>
<#= parseInt(item.get('traffic')) #>%
<# }else{ #>
<div class="thrive-ab-test-item-traffic tvd-row">
<div class="tvd-col tvd-s8 thrive-ab-variation-traffic-slider">
<input type="range" class="input change" min="0" max="100" data-fn="on_change" data-fn-input="on_input" value="<#= parseInt(item.get('traffic')) #>">
</div>
<div class="tvd-col tvd-s4 thrive-ab-variation-traffic-input">
<input class="thrive-ab-card-traffic-input input change" data-fn="on_change" data-fn-input="on_input" type="number" min="0" max="100"
value="<#= parseInt(item.get('traffic')) #>">
</div>
</div>
<# } #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') #>%
</div>
<div class="tvd-col tvd-s2 tab-control-indicator">
<?php echo __( '[This is the Control]', 'thrive-ab-page-testing' ) ?>
</div>
</div>

View File

@@ -0,0 +1,50 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s2">
<span><#= ThriveAB.t.control #></span>
<a href="<#= item.get('preview_link') #>" target="_blank">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
</div>
<div class="tvd-col tvd-s2">
<div class="thrive-ab-test-item-traffic tvd-row">
<div class="tvd-col tvd-s8 thrive-ab-variation-traffic-slider">
<input type="range" class="input change" min="0" max="100" data-fn="on_change" data-fn-input="on_input" value="<#= parseInt(item.get('traffic')) #>">
</div>
<div class="tvd-col tvd-s4 thrive-ab-variation-traffic-input">
<input class="thrive-ab-card-traffic-input input change" data-fn="on_change" data-fn-input="on_input" type="number" min="0" max="100" value="<#= parseInt(item.get('traffic')) #>">
</div>
</div>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue_visitor') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') #>
</div>
<div class="tvd-col tvd-s1">
<?php echo __( '[This is the Control]', 'thrive-ab-page-testing' ) ?>
</div>
</div>

View File

@@ -0,0 +1,10 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<span class="click" data-fn="view_conversion_goal_details">
<?php tcb_icon( 'monetary-2' ) ?><?php echo __( 'Revenue Conversion Goal', 'thrive-ab-page-testing' ); ?>
</span>

View File

@@ -0,0 +1,10 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<span class="click" data-fn="view_conversion_goal_details">
<?php tcb_icon( 'subs' ) ?><?php echo __( 'Subscription Conversion Goal', 'thrive-ab-page-testing' ); ?>
</span>

View File

@@ -0,0 +1,10 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<span class="click" data-fn="view_conversion_goal_details">
<?php tcb_icon( 'visit_gp' ) ?><?php echo __( 'Page Visit Conversion Goal', 'thrive-ab-page-testing' ); ?>
</span>

View File

@@ -0,0 +1,74 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s2 tab-headline">
<span class="tab-truncate">
<a class="thrive-ab-editor-link"><#= item.get('title') #></a>
<# if( table_model.get('status') === 'completed' && parseInt(item.get('is_winner')) === 1 ) { #>
&nbsp;<span class="tab-winner-label">(<?php echo __( 'winner', 'thrive-ab-page-testing' ); ?>)</span>
<# } #>
</span>
<span class="tab-edit-controls">
<a href="<#= item.get('preview_link') #>" target="_blank">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
<# if ( table_model.get('status') !== 'completed' ) { #>
<a href="<#= item.get('editor_link') #>" class="top-edit-icon tvd-tooltipped" data-tooltip="<?php echo __( 'Edit variation with Architect', 'thrive-ab-page-testing' ); ?>" data-position="top"></a>
<# } #>
</span>
</div>
<div class="tvd-col tvd-s2">
<# if( table_model.get('status') === 'completed') { #>
<#= parseInt(item.get('traffic')) #>%
<# }else{ #>
<div class="thrive-ab-test-item-traffic tvd-row">
<div class="tvd-col tvd-s8 thrive-ab-variation-traffic-slider">
<input type="range" class="input change" min="0" max="100" data-fn="on_change" data-fn-input="on_input" value="<#= parseInt(item.get('traffic')) #>">
</div>
<div class="tvd-col tvd-s4 thrive-ab-variation-traffic-input">
<input class="thrive-ab-card-traffic-input input change" data-fn="on_change" data-fn-input="on_input" type="number" min="0" max="100"
value="<#= parseInt(item.get('traffic')) #>">
</div>
</div>
<# } #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue_visitor') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') #>%
</div>
<div class="tvd-col tvd-s1 <#= item.get('improvement') >= 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' #>">
<#= item.get('improvement') #>%
</div>
<div class="tvd-col tvd-s1 <#= item.get('chance_to_beat_orig') >= 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' #>">
<#= item.get('chance_to_beat_orig') #>%
<# if( table_model.get('status') === 'running' ) { #>
<a class="tvd-tooltipped tvd-right tvd-line-height click" data-fn="stop_variation" href="javascript:void(0);"
data-tooltip="<?php echo __( 'Stop this variation', 'thrive-ab-page-testing' ); ?>" data-position="top">
<i class="tvd-icon-stop tvd-text-red" style="font-size: 16px;"></i>
</a>
<# } #>
</div>
</div>

View File

@@ -0,0 +1,68 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s3 tab-headline">
<span class="tab-truncate">
<a class="thrive-ab-editor-link"><#= item.get('title') #></a>
<# if( table_model.get('status') === 'completed' && parseInt(item.get('is_winner')) === 1 ) { #>
&nbsp;<span class="tab-winner-label">(<?php echo __( 'winner', 'thrive-ab-page-testing' ); ?>)</span>
<# } #>
</span>
<span class="tab-edit-controls">
<a href="<#= item.get('preview_link') #>" target="_blank">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
<# if ( table_model.get('status') !== 'completed' && item.get('editor_link')) { #>
<a href="<#= item.get('editor_link') #>" class="top-edit-icon tvd-tooltipped" data-tooltip="<?php echo __( 'Edit variation with Architect', 'thrive-ab-page-testing' ); ?>" data-position="top"></a>
<# } #>
</span>
</div>
<div class="tvd-col tvd-s2">
<# if( table_model.get('status') === 'completed') { #>
<#= parseInt(item.get('traffic')) #>%
<# }else{ #>
<div class="thrive-ab-test-item-traffic tvd-row">
<div class="tvd-col tvd-s8 thrive-ab-variation-traffic-slider">
<input type="range" class="input change" min="0" max="100" data-fn="on_change" data-fn-input="on_input" value="<#= parseInt(item.get('traffic')) #>">
</div>
<div class="tvd-col tvd-s4 thrive-ab-variation-traffic-input">
<input class="thrive-ab-card-traffic-input input change" data-fn="on_change" data-fn-input="on_input" type="number" min="0" max="100"
value="<#= parseInt(item.get('traffic')) #>">
</div>
</div>
<# } #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') #>%
</div>
<div class="tvd-col tvd-s1 <#= item.get('improvement') >= 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' #>">
<#= item.get('improvement') #>%
</div>
<div class="tvd-col tvd-s1 <#= item.get('chance_to_beat_orig') >= 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' #>">
<#= item.get('chance_to_beat_orig') #>%
<# if( table_model.get('status') === 'running' ) { #>
<a class="tvd-tooltipped tvd-right tvd-line-height click" data-fn="stop_variation" href="javascript:void(0);"
data-tooltip="<?php echo __( 'Stop this variation', 'thrive-ab-page-testing' ); ?>" data-position="top">
<i class="tvd-icon-stop tvd-text-red" style="font-size: 16px;"></i>
</a>
<# } #>
</div>
</div>

View File

@@ -0,0 +1,49 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 12/11/2017
* Time: 9:25 AM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row tvd-tooltipped" data-tooltip="<?php echo __( 'Manually stopped on', 'thrive-ab-page-testing' ); ?> <#= item.get('stopped_date') #>" data-position="top">
<div class="tvd-col tvd-s2 tab-headline">
<span class="tab-truncate"><#= item.get('title') #></span>
<span class="tab-edit-controls">
<a href="<#= item.get('preview_link') #>" target="_blank">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
</span>
</div>
<div class="tvd-col tvd-s2">
<#= item.get('traffic') #>%
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue_visitor') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') #>%
</div>
<div class="tvd-col tvd-s1">
<#= item.get('improvement') #>%
</div>
<div class="tvd-col tvd-s1">
<#= item.get('chance_to_beat_orig') #>
</div>
</div>

View File

@@ -0,0 +1,43 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 12/11/2017
* Time: 9:25 AM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row tvd-tooltipped" data-tooltip="<?php echo __( 'Manually stopped on', 'thrive-ab-page-testing' ); ?> <#= item.get('stopped_date') #>" data-position="top">
<div class="tvd-col tvd-s3 tab-headline">
<span class="tab-truncate"><#= item.get('title') #></span>
<span class="tab-edit-controls">
<a href="<#= item.get('preview_link') #>" target="_blank">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
</span>
</div>
<div class="tvd-col tvd-s2">
<#= item.get('traffic') #>%
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') #>%
</div>
<div class="tvd-col tvd-s1">
<#= item.get('improvement') #>%
</div>
<div class="tvd-col tvd-s2">
<#= item.get('chance_to_beat_orig') #>
</div>
</div>

View File

@@ -0,0 +1,43 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 12/11/2017
* Time: 9:25 AM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row tvd-tooltipped" data-tooltip="<?php echo __( 'Manually stopped on', 'thrive-ab-page-testing' ); ?> <#= item.get('stopped_date') #>" data-position="top">
<div class="tvd-col tvd-s3 tab-headline">
<span class="tab-truncate"><#= item.get('title') #></span>
<span class="tab-edit-controls">
<a href="<#= item.get('preview_link') #>" target="_blank">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
</span>
</div>
<div class="tvd-col tvd-s3">
N/A
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') #>%
</div>
<div class="tvd-col tvd-s1">
<#= item.get('improvement') #>%
</div>
<div class="tvd-col tvd-s1">
<#= item.get('chance_to_beat_orig') #>%
</div>
</div>

View File

@@ -0,0 +1,49 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 12/11/2017
* Time: 9:25 AM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s2 tab-headline">
<span class="tab-truncate"><#= item.get('title') #></span>
<span class="tab-edit-controls">
<a href="<#= item.get('preview_link') #>" target="_blank">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
</span>
</div>
<div class="tvd-col tvd-s2">
<#= item.get('traffic') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue_visitor') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('improvement') #>
</div>
<div class="tvd-col tvd-s2">
<#= item.get('chance_to_beat_orig') #>
</div>
</div>

View File

@@ -0,0 +1,68 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s3 tab-headline">
<span class="tab-truncate">
<a class="thrive-ab-editor-link"><#= item.get('title') #></a>
<# if( table_model.get('status') === 'completed' && parseInt(item.get('is_winner')) === 1 ) { #>
<span class="tab-winner-label">(<?php echo __( 'winner', 'thrive-ab-page-testing' ); ?>)</span>
<# } #>
</span>
<span class="tab-edit-controls">
<a href="<#= item.get('preview_link') #>" target="_blank">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
<# if ( table_model.get('status') !== 'completed' && item.get('editor_link')) { #>
<a href="<#= item.get('editor_link') #>" class="top-edit-icon tvd-tooltipped" data-tooltip="<?php echo __( 'Edit variation with Architect', 'thrive-ab-page-testing' ); ?>" data-position="top"></a>
<# } #>
</span>
</div>
<div class="tvd-col tvd-s3">
<# if( table_model.get('status') === 'completed') { #>
<#= parseInt(item.get('traffic')) #>%
<# }else{ #>
<div class="thrive-ab-test-item-traffic tvd-row">
<div class="tvd-col tvd-s8 thrive-ab-variation-traffic-slider">
<input type="range" class="input change" min="0" max="100" data-fn="on_change" data-fn-input="on_input" value="<#= parseInt(item.get('traffic')) #>">
</div>
<div class="tvd-col tvd-s4 thrive-ab-variation-traffic-input">
<input class="thrive-ab-card-traffic-input input change" data-fn="on_change" data-fn-input="on_input" type="number" min="0" max="100"
value="<#= parseInt(item.get('traffic')) #>">
</div>
</div>
<# } #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') #>%
</div>
<div class="tvd-col tvd-s1 <#= item.get('improvement') >= 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' #>">
<#= item.get('improvement') #>%
</div>
<div class="tvd-col tvd-s1 <#= item.get('chance_to_beat_orig') >= 0 ? 'thrive-ab-positive' : 'thrive-ab-negative' #>">
<#= item.get('chance_to_beat_orig') #>%
<# if( table_model.get('status') === 'running' ) { #>
<a class="tvd-tooltipped tvd-right tvd-line-height click" data-fn="stop_variation" href="javascript:void(0);"
data-tooltip="<?php echo __( 'Stop this variation', 'thrive-ab-page-testing' ); ?>" data-position="top">
<i class="tvd-icon-stop tvd-text-red" style="font-size: 16px;"></i>
</a>
<# } #>
</div>
</div>

View File

@@ -0,0 +1,60 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="tvd-row">
<div class="tvd-col tvd-s2 tab-headline">
<span>
<a class="thrive-ab-editor-link" href="<#= item.get('editor_link') #>"><#= item.get('title') #></a>
</span>
<span class="tab-edit-controls">
<a href="<#= item.get('preview_link') #>" target="_blank">
<?php echo tcb_icon( 'external-link', true, 'sidebar', 'thrive-ab-dashboard-icons' ); ?>
</a>
</span>
</div>
<div class="tvd-col tvd-s2">
<div class="thrive-ab-test-item-traffic tvd-row">
<div class="tvd-col tvd-s8 thrive-ab-variation-traffic-slider">
<input type="range" class="input change" min="0" max="100" data-fn="on_change" data-fn-input="on_input" value="<#= parseInt(item.get('traffic')) #>">
</div>
<div class="tvd-col tvd-s4 thrive-ab-variation-traffic-input">
<input class="thrive-ab-card-traffic-input input change" data-fn="on_change" data-fn-input="on_input" type="number" min="0" max="100" value="<#= parseInt(item.get('traffic')) #>">
</div>
</div>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('unique_impressions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversions') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('revenue_visitor') #>
</div>
<div class="tvd-col tvd-s1">
<#= item.get('conversion_rate') #>
</div>
<div class="tvd-col tvd-s1 thrive-ab-positive">
<#= item.get('improvement') #>
</div>
<div class="tvd-col tvd-s1 thrive-ab-negative">
<#= item.get('chance_to_beat_orig') #>
<a class="tvd-tooltipped tvd-right tvd-line-height click" data-fn="stop_variation" href="javascript:void(0);" data-tooltip="<?php echo __( 'Stop this variation', 'thrive-ab-page-testing' ); ?>" data-position="top">
<i class="tvd-icon-stop tvd-text-red" style="font-size: 16px;"></i>
</a>
</div>
</div>

View File

@@ -0,0 +1,26 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="thrive-ab-test-header">
<div class="tvd-row">
<div class="tvd-col tvd-s2"><?php echo __( 'Variation Name', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2"><?php echo __( 'Traffic', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Visitors', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Unique Visitors', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Sales', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Revenue', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Revenue per Visitor', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Conversion Rate', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Improvement', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Chance to beat Original', 'thrive-ab-page-testing' ) ?></div>
</div>
</div>
<?php include dirname( __FILE__ ) . '/table-body.php'; ?>

View File

@@ -0,0 +1,24 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-ab-page-testing
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="thrive-ab-test-header">
<div class="tvd-row">
<div class="tvd-col tvd-s3"><?php echo __( 'Variation Name', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2"><?php echo __( 'Traffic', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Visitors', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Unique Visitors', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Subscriptions', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Subscription Rate', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s1"><?php echo __( 'Improvement', 'thrive-ab-page-testing' ) ?></div>
<div class="tvd-col tvd-s2"><?php echo __( 'Chance to beat Original', 'thrive-ab-page-testing' ) ?></div>
</div>
</div>
<?php include dirname( __FILE__ ) . '/table-body.php'; ?>

View File

@@ -0,0 +1,21 @@
<?php
/**
* Created by PhpStorm.
* User: Ovidiu
* Date: 12/14/2017
* Time: 12:56 PM
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Silence is golden
}
?>
<div class="thrive-ab-test-items"></div>
<div class="thrive-ab-test-footer">
<p><span></span><?php echo __( 'Changes occurred while a test is running can sometimes invalidate the test results.', 'thrive-ab-page-testing' ); ?></p>
<span id="thrive-ab-conversion-goals" class="click" data-fn="open_conversion_goal_modal"></span>
<span id="thrive-ab-auto-win-text"></span>
<button class="tvd-btn-flat tvd-btn-flat-primary tvd-btn-flat-blue tvd-waves-effect tvd-blue-text click"
data-fn="change_automatic_winner_settings"><?php echo __( 'Change', 'thrive-ab-page-testing' ) ?></button>
</div>
<div class="thrive-ab-test-stopped-items"></div>

Some files were not shown because too many files have changed in this diff Show More