Plugin Directory

Changeset 1190425


Ignore:
Timestamp:
06/30/2015 05:30:49 PM (11 years ago)
Author:
iterative
Message:

Deploying 1.2. The API has not been updated, but this is backwards compatible.

Location:
iterative-headlines
Files:
4 edited
16 copied

Legend:

Unmodified
Added
Removed
  • iterative-headlines/tags/1.2/headlines.php

    r1187282 r1190425  
    5252function iterative_end_session() {
    5353    session_destroy ();
     54}
     55
     56add_action( 'admin_notices', 'iterative_admin_notices' );
     57global $iterative_notices;
     58$iterative_notices = array();
     59function iterative_admin_notices() {
     60    return;
     61    global $iterative_notices;
     62    foreach($iterative_notices as $in) {
     63    ?>
     64        <div class="updated">
     65        <p><?php _e( $in ); ?></p>
     66        </div>
     67    <?php
     68    }
    5469}
    5570
     
    267282   
    268283    $advice = (IterativeAPI::getAdvice($post->ID, $adviceTitles));
    269     $pms = IterativeAPI::getParameters($post->ID);
     284    $pms = IterativeAPI::getParameters($post->ID, 'sts');
    270285    if(isset($pms[md5($title)])) {
    271286        $baseline = $pms[md5($title)];
  • iterative-headlines/tags/1.2/headlines_api.php

    r1187282 r1190425  
    88    //          -> Receive probabilities for each variant.
    99    private static $api_endpoint = "http://api.pathfinding.ca/";
     10    private static $api_version = 1.2;
     11    private static $reject_age = 86400;
     12    private static $request_age = 14440;
    1013    public static function getURL($page) {
    1114        return static::$api_endpoint . $page;
    1215    }
     16
     17    public static function makeRequest($endpoint, $blob=[]) {
     18        $url_parameters = http_build_query($blob);
     19        $url = static::$api_endpoint . "{$endpoint}?" . $url_parameters . "&v=" . static::$api_version;
     20        //echo $url . "\n";
     21        $request = wp_remote_get($url);
     22        $response = json_decode(wp_remote_retrieve_body( $request ), true);
     23        if(isset($response['error'])) {
     24            global $iterative_notices;
     25            $iterative_notices[] = $response['error'];
     26            if(is_admin()) {
     27                ?>
     28                    <div class="updated">
     29                    <p><strong>Error:</strong> <?php _e( $response['error']); ?></p>
     30                    </div>
     31                    <?php
     32            }
     33        }
     34        if(isset($response['special'])) {
     35            if($response['special'] == "DISABLE") {
     36                deactivate_plugins( plugin_basename( __FILE__ ) );
     37            } else if($response['special'] == "DELIVER" && is_admin()) {
     38                echo "<p>" . $response['error'] . "</p>";
     39            }
     40        }
     41        return $response;
     42    }
     43
    1344    public static function getGUID() {
    1445        // if it isn't defined locally, get it from the server
     
    1849            $guid = static::serverGUID($meta);
    1950            $settings['headlines']['guid'] = $guid;
    20 
    2151            update_option("iterative_settings", $settings);
    22 
    2352        } else {
    2453            $guid = $settings['headlines']['guid'];
     
    2958   
    3059    private static function serverGUID($meta=null) {
    31         $url_parameters = http_build_query(['meta' => json_encode($meta)]);
    32         $request = wp_remote_get(static::$api_endpoint . "unique?" . $url_parameters);
    33         $response = json_decode(wp_remote_retrieve_body( $request ), true);
     60        $response = makeRequest("unique", array('meta' => json_encode($meta)));
    3461        return $response['unique_id'];
    3562    }
     
    5279            $meta = [];
    5380        $parameters = ['experiment_id' => $post_id, 'unique_id' => $unique_id, 'type'=>$type, 'variants' => json_encode($send), 'meta' => json_encode($meta)];
    54         $url_parameters = http_build_query($parameters);
    55    
    56         $request = wp_remote_get(static::$api_endpoint . "experiment?" . $url_parameters);
    57         //echo static::$api_endpoint . "experiment?" . $url_parameters;
    58        
    59 
    60         $response = json_decode(wp_remote_retrieve_body($request), true);
     81        $response = static::makeRequest("experiment", $parameters);
     82die();
    6183        $response['timestamp'] = time();
    6284        update_post_meta($post_id, "_iterative_parameters_{$type}", $response);
     
    7294    }
    7395
    74         public static function getAdvice($post_id, $variants) {
    75                 $variants = json_encode($variants);
    76                 $type = static::getType();
    77                 $parameters = ['experiment_id' => $post_id, 'unique_id' => static::getGUID(), 'type'=>$type, 'variants'=>$variants];
    78                 $url_parameters = http_build_query($parameters);
    79                 $request = wp_remote_get(static::$api_endpoint . "advice?" . $url_parameters);
    80                 $response = json_decode(wp_remote_retrieve_body($request), true);
    81                 if(isset($response['parameters']) && !empty($response['parameters']))
    82                         update_post_meta($post_id, "_iterative_parameters_{$type}", $response['parameters']);
    83                 return $response['messages'];
    84         }
    85 
    86     public static function getParameters($post_id) {
     96    public static function getAdvice($post_id, $variants) {
     97        $variants = json_encode($variants);
     98        $type = static::getType();
     99        $parameters = ['experiment_id' => $post_id, 'unique_id' => static::getGUID(), 'type'=>$type, 'variants'=>$variants];
     100        $response = static::makeRequest("advice", $parameters);
     101
     102            if(isset($response['parameters']) && !empty($response['parameters']))
     103            update_post_meta($post_id, "_iterative_parameters_{$type}", $response['parameters']);
     104
     105        return $response['messages'];
     106        }
     107
     108    public static function getParameters($post_id, $model_type=null) {
    87109        $type = static::getType();
    88110
    89111        // get the most recent parameters. if they don't exist, call serverProbabilities.
    90         $post_meta = get_post_meta($post_id, "_iterative_parameters_{$type}", true);
    91         if($post_meta == "" || $response['timestamp'] > time()+60*60*4)
     112        if($model_type === null) die("NO MT?");
     113        $post_meta = get_post_meta($post_id, "_iterative_parameters_{$model_type}_{$type}", true);
     114        if($post_meta == "" || $response['timestamp'] > time()+static::$request_age)
    92115            return static::serverProbabilities($post_id, $type);
    93116        else return $post_meta;
     
    96119
    97120    private static function serverProbabilities($post_id, $type) {
    98         // ask the server for the probabilities of each variant. store them.
    99        
    100         $parameters = ['experiment_id' => $post_id, 'unique_id' => static::getGUID(), 'type'=>$type];
    101         $url_parameters = http_build_query($parameters);
    102        
    103         $request = wp_remote_get(static::$api_endpoint . "parameters?" . $url_parameters);
    104         $response = json_decode(wp_remote_retrieve_body($request), true);
     121        // ask the server for the probabilities/model of each variant. store them.
     122        $parameters = ['experiment_id' => $post_id, 'unique_id' => static::getGUID(), 'type'=>$type, 'model'=>'sts'];
     123        $response = static::makeRequest("parameters", $parameters);
    105124        $response['timestamp'] = time();
     125
     126        if(!isset($response['model_type'])) {
     127            $response['model_type'] = 'sts';
     128            $response['model_version'] = 0;
     129            $response['model_priority'] = 10;
     130        }
     131
     132        $model_variables = array();
     133        foreach($response as $key=>$value) {
     134            if(substr($key, 0, 6) == "model_") $model_variables[substr($key, 6)] = $value;
     135        }
     136
     137        $models = get_post_meta($post_id, "_iterative_models_{$type}", true);
     138        if(!is_array($models))
     139            $models = array();
     140
     141        $models[$response['model_type']] = $model_variables;
     142
    106143        // store the parameters.
    107         update_post_meta($post_id, "_iterative_parameters_{$type}", $response);
     144        update_post_meta($post_id, "_iterative_parameters_{$response['model_type']}_{$type}", $response);
     145        update_post_meta($post_id, "_iterative_models_{$type}", $models);
    108146        return $response;
    109147    }
     
    128166
    129167    public static function selectVariant($post_id, $variant_hashes) {
    130         // return the hash of a single variant... tell the server that this user has that selected.
    131         // tell the server right away about the variant, but in the future, do it more intelligently (users may see more than one variant on a page load).
     168        // support models.
     169
    132170        $user_id = static::getUserID();
    133171        $unique_id = static::getGUID();
    134         $settings = get_option("iterative_settings");
    135         if(isset($settings['headlines']) && isset($settings['headlines']['goal']))
    136             $type = $settings['headlines']['goal'];
    137         else
    138             $type = ITERATIVE_GOAL_CLICKS;
    139 
    140 
     172       
    141173        if(($variant = static::getVariantForUserID($post_id, $user_id))!==null && in_array($variant, $variant_hashes)) {
    142174            return $variant;   
    143175        } else {
    144             $parameters = static::getParameters($post_id, $type);
    145 
    146             $best = -INF;
    147             $best_hash = null;
    148 
    149             foreach($variant_hashes as $vh) {
    150                 if(!isset($parameters[$vh])) {
    151                     $parameters = IterativeAPI::updateExperiment($post_id, iterative_get_variants($post_id));
     176            // select the right model.
     177            $type = static::getType();
     178            $models = get_post_meta($post_id, "_iterative_models_{$type}", true);
     179            $best_model = current($models);
     180            $second_model = current($models);
     181            foreach($models as $model) {
     182                if($model === $best_model) continue;
     183
     184                if($model['priority'] > $best_model['priority']) {
     185                    $second_model = $best_model;
     186                    $best_model = $model;
     187                } else if($model['priority'] == $best_model['priority']) {
     188                    $second_model = $model;
     189                    // TODO: decide whether to overwrite based on whether it is available or not.
    152190                }
    153 
    154                 $draw = iterative_ib(iterative_urf($parameters[$vh]['c'],1), $parameters[$vh]['a'], $parameters[$vh]['b']);
    155                 if($draw > $best)
    156                 {
    157                     $best = $draw;
    158                     $best_hash = $vh;
    159                 }
    160             }
    161 
    162             $parameters = ['unique_id' => $unique_id, 'user'=>$user_id, 'variant'=>$best_hash, 'experiment_id' => $post_id];
    163             $url_parameters = http_build_query($parameters);
    164 
    165             wp_remote_get(static::$api_endpoint . "variant?" . $url_parameters);
    166             static::storeVariantForUserID($post_id, $user_id, $best_hash);
    167             return $best_hash;
    168         }
     191            }
     192            if($best_model['timestamp'] < time()-static::$reject_age)
     193                $best_model = $second_model;
     194
     195            $method = "model_" . $best_model['type'] . "_" . $best_model['version'];
     196            $hash = static::model_sts_0($post_id, $variant_hashes);
     197            static::tellServerVariantForUserID($unique_id, $user_id, $hash, $post_id);
     198            static::storeVariantForUserID($post_id, $user_id, $hash);
     199
     200            return $hash;
     201        }
     202    }
     203
     204    public static function tellServerVariantForUserID($unique_id, $user_id, $hash, $post_id) {
     205        $variants = get_post_meta($post_id, "_iterative_variants", true);
     206                if(isset($variants[$user_id]) && $variants[$user_id] == $hash) return;
     207        $parameters = ['unique_id' => $unique_id, 'user'=>$user_id, 'variant'=>$hash, 'experiment_id' => $post_id];
     208        static::makeRequest("variant", $parameters);
    169209    }
    170210
     
    227267        return static::$api_endpoint . "js/success?experiment_id=" . $experiment_id . "&user=" . static::getUserID() . "&unique_id=" . static::getGUID() . "&type=" . $type . "&variant_id=" . $variant_id;
    228268    }
     269
     270
     271    // models.
     272    public static function model_sts_0($post_id, $variant_hashes) {
     273        // return the hash of a single variant... tell the server that this user has that selected.
     274        // tell the server right away about the variant, but in the future, do it more intelligently (users may see more than one variant on a page load).
     275        $type = static::getType();
     276        $parameters = static::getParameters($post_id, "sts");
     277       
     278        $best = -INF;
     279        $best_hash = null;
     280
     281        foreach($variant_hashes as $vh) {
     282            if(!isset($parameters[$vh])) {
     283                // our experiment is somehow out of date.
     284                $parameters = IterativeAPI::updateExperiment($post_id, iterative_get_variants($post_id));
     285            }
     286
     287            $draw = iterative_ib(iterative_urf($parameters[$vh]['c'],1), $parameters[$vh]['a'], $parameters[$vh]['b']);
     288            if($draw > $best)
     289            {
     290                $best = $draw;
     291                $best_hash = $vh;
     292            }
     293        }
     294
     295        return $best_hash;
     296    }
    229297}
    230298
  • iterative-headlines/tags/1.2/headlines_options.php

    r1187282 r1190425  
    7676    }
    7777    </script>
    78     <p><label><input type='radio' class='headline-goal' name='iterative_settings[headlines][goal]' <?php checked( $options['headlines']['goal'], ITERATIVE_GOAL_CLICKS ); ?> value='<?php echo ITERATIVE_GOAL_CLICKS; ?>'> I want more of my readers to view my posts.</label></p>
     78    <!-- premium. <p><label><input type='radio' class='headline-goal' name='iterative_settings[headlines][goal]' <?php checked( $options['headlines']['goal'], ITERATIVE_GOAL_CLICKS ); ?> value='<?php echo ITERATIVE_GOAL_CLICKS; ?>'> I want my posts to go viral! <strong>Get me more shares, links, readers and clicks.</strong> <small class="recommended">Recommended</small></label></p>
     79    <p class='description headline-goal-description'>This.</p>-->
     80   
     81    <p><label><input type='radio' class='headline-goal' name='iterative_settings[headlines][goal]' <?php checked( $options['headlines']['goal'], ITERATIVE_GOAL_CLICKS ); ?> value='<?php echo ITERATIVE_GOAL_CLICKS; ?>'> I want more of my readers to read my posts.</label></p>
    7982    <p class='description headline-goal-description'>This will optimize your headlines to increase the number of users who click through from other pages on your site.</p>
    8083    <p><label><input type='radio' class='headline-goal' name='iterative_settings[headlines][goal]' <?php checked( $options['headlines']['goal'], ITERATIVE_GOAL_COMMENTS ); ?> value='<?php echo ITERATIVE_GOAL_COMMENTS; ?>'> I want my readers to comment on my posts.</label></p>
     
    125128        .cta-top a { color:white; }
    126129        .cta-top a:hover { text-shadow:0 1px 8px rgba(0,0,0,0.498039) ;; }
    127         .notyet,.premium {
     130        .notyet,.premium,.recommended {
    128131          border-radius:5px;
    129132          font: normal normal bold 12px "Averia Sans Libre", Helvetica, sans-serif;
     
    146149          background: -moz-linear-gradient(180deg, rgb(218,218,218) 0, rgb(157,157,157) 100%), rgb(218,218,218);
    147150          background: linear-gradient(180deg, rgb(218,218,218) 0, rgb(157,157,157) 100%), rgb(218,218,218);
     151        }
     152        .recommended {
     153          background: -webkit-linear-gradient(180deg, rgb(23, 204, 8) 0, rgb(9, 119, 26) 100%), rgb(27, 169, 48);
     154          background: -moz-linear-gradient(180deg, rgb(23, 204, 8) 0, rgb(9, 119, 26) 100%), rgb(27, 169, 48);
     155          background: linear-gradient(180deg, rgb(23, 204, 8) 0, rgb(9, 119, 26) 100%), rgb(27, 169, 48);
    148156        }
    149157        .iterative { color: #d41f28; font-weight:bold; font-family:Helvetica, arial, sans; }
  • iterative-headlines/tags/1.2/readme.txt

    r1187282 r1190425  
    44Requires at least: 3.0.1
    55Tested up to: 4.2.2
    6 Stable tag: 1.1
     6Stable tag: 1.2
    77License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    6969* First release!
    7070
     71= 1.1 =
     72* Bug fixes.
     73
     74= 1.2 =
     75* New API compatibility. Speed improvements.
     76 
    7177== Upgrade Notice ==
    7278
    7379= 1.0 =
    7480This is the initial release.
     81
     82= 1.2 =
     83Much faster. The plugin now caches all results locally and no longer has any major effect on load time. Also, full support for UTF-8.
  • iterative-headlines/trunk/headlines.php

    r1187278 r1190425  
    5252function iterative_end_session() {
    5353    session_destroy ();
     54}
     55
     56add_action( 'admin_notices', 'iterative_admin_notices' );
     57global $iterative_notices;
     58$iterative_notices = array();
     59function iterative_admin_notices() {
     60    return;
     61    global $iterative_notices;
     62    foreach($iterative_notices as $in) {
     63    ?>
     64        <div class="updated">
     65        <p><?php _e( $in ); ?></p>
     66        </div>
     67    <?php
     68    }
    5469}
    5570
     
    267282   
    268283    $advice = (IterativeAPI::getAdvice($post->ID, $adviceTitles));
    269     $pms = IterativeAPI::getParameters($post->ID);
     284    $pms = IterativeAPI::getParameters($post->ID, 'sts');
    270285    if(isset($pms[md5($title)])) {
    271286        $baseline = $pms[md5($title)];
  • iterative-headlines/trunk/headlines_api.php

    r1187275 r1190425  
    88    //          -> Receive probabilities for each variant.
    99    private static $api_endpoint = "http://api.pathfinding.ca/";
     10    private static $api_version = 1.2;
     11    private static $reject_age = 86400;
     12    private static $request_age = 14440;
    1013    public static function getURL($page) {
    1114        return static::$api_endpoint . $page;
    1215    }
     16
     17    public static function makeRequest($endpoint, $blob=[]) {
     18        $url_parameters = http_build_query($blob);
     19        $url = static::$api_endpoint . "{$endpoint}?" . $url_parameters . "&v=" . static::$api_version;
     20        //echo $url . "\n";
     21        $request = wp_remote_get($url);
     22        $response = json_decode(wp_remote_retrieve_body( $request ), true);
     23        if(isset($response['error'])) {
     24            global $iterative_notices;
     25            $iterative_notices[] = $response['error'];
     26            if(is_admin()) {
     27                ?>
     28                    <div class="updated">
     29                    <p><strong>Error:</strong> <?php _e( $response['error']); ?></p>
     30                    </div>
     31                    <?php
     32            }
     33        }
     34        if(isset($response['special'])) {
     35            if($response['special'] == "DISABLE") {
     36                deactivate_plugins( plugin_basename( __FILE__ ) );
     37            } else if($response['special'] == "DELIVER" && is_admin()) {
     38                echo "<p>" . $response['error'] . "</p>";
     39            }
     40        }
     41        return $response;
     42    }
     43
    1344    public static function getGUID() {
    1445        // if it isn't defined locally, get it from the server
     
    1849            $guid = static::serverGUID($meta);
    1950            $settings['headlines']['guid'] = $guid;
    20 
    2151            update_option("iterative_settings", $settings);
    22 
    2352        } else {
    2453            $guid = $settings['headlines']['guid'];
     
    2958   
    3059    private static function serverGUID($meta=null) {
    31         $url_parameters = http_build_query(['meta' => json_encode($meta)]);
    32         $request = wp_remote_get(static::$api_endpoint . "unique?" . $url_parameters);
    33         $response = json_decode(wp_remote_retrieve_body( $request ), true);
     60        $response = makeRequest("unique", array('meta' => json_encode($meta)));
    3461        return $response['unique_id'];
    3562    }
     
    5279            $meta = [];
    5380        $parameters = ['experiment_id' => $post_id, 'unique_id' => $unique_id, 'type'=>$type, 'variants' => json_encode($send), 'meta' => json_encode($meta)];
    54         $url_parameters = http_build_query($parameters);
    55    
    56         $request = wp_remote_get(static::$api_endpoint . "experiment?" . $url_parameters);
    57         //echo static::$api_endpoint . "experiment?" . $url_parameters;
    58        
    59 
    60         $response = json_decode(wp_remote_retrieve_body($request), true);
     81        $response = static::makeRequest("experiment", $parameters);
     82die();
    6183        $response['timestamp'] = time();
    6284        update_post_meta($post_id, "_iterative_parameters_{$type}", $response);
     
    7294    }
    7395
    74         public static function getAdvice($post_id, $variants) {
    75                 $variants = json_encode($variants);
    76                 $type = static::getType();
    77                 $parameters = ['experiment_id' => $post_id, 'unique_id' => static::getGUID(), 'type'=>$type, 'variants'=>$variants];
    78                 $url_parameters = http_build_query($parameters);
    79                 $request = wp_remote_get(static::$api_endpoint . "advice?" . $url_parameters);
    80                 $response = json_decode(wp_remote_retrieve_body($request), true);
    81                 if(isset($response['parameters']) && !empty($response['parameters']))
    82                         update_post_meta($post_id, "_iterative_parameters_{$type}", $response['parameters']);
    83                 return $response['messages'];
    84         }
    85 
    86     public static function getParameters($post_id) {
     96    public static function getAdvice($post_id, $variants) {
     97        $variants = json_encode($variants);
     98        $type = static::getType();
     99        $parameters = ['experiment_id' => $post_id, 'unique_id' => static::getGUID(), 'type'=>$type, 'variants'=>$variants];
     100        $response = static::makeRequest("advice", $parameters);
     101
     102            if(isset($response['parameters']) && !empty($response['parameters']))
     103            update_post_meta($post_id, "_iterative_parameters_{$type}", $response['parameters']);
     104
     105        return $response['messages'];
     106        }
     107
     108    public static function getParameters($post_id, $model_type=null) {
    87109        $type = static::getType();
    88110
    89111        // get the most recent parameters. if they don't exist, call serverProbabilities.
    90         $post_meta = get_post_meta($post_id, "_iterative_parameters_{$type}", true);
    91         if($post_meta == "" || $response['timestamp'] > time()+60*60*4)
     112        if($model_type === null) die("NO MT?");
     113        $post_meta = get_post_meta($post_id, "_iterative_parameters_{$model_type}_{$type}", true);
     114        if($post_meta == "" || $response['timestamp'] > time()+static::$request_age)
    92115            return static::serverProbabilities($post_id, $type);
    93116        else return $post_meta;
     
    96119
    97120    private static function serverProbabilities($post_id, $type) {
    98         // ask the server for the probabilities of each variant. store them.
    99        
    100         $parameters = ['experiment_id' => $post_id, 'unique_id' => static::getGUID(), 'type'=>$type];
    101         $url_parameters = http_build_query($parameters);
    102        
    103         $request = wp_remote_get(static::$api_endpoint . "parameters?" . $url_parameters);
    104         $response = json_decode(wp_remote_retrieve_body($request), true);
     121        // ask the server for the probabilities/model of each variant. store them.
     122        $parameters = ['experiment_id' => $post_id, 'unique_id' => static::getGUID(), 'type'=>$type, 'model'=>'sts'];
     123        $response = static::makeRequest("parameters", $parameters);
    105124        $response['timestamp'] = time();
     125
     126        if(!isset($response['model_type'])) {
     127            $response['model_type'] = 'sts';
     128            $response['model_version'] = 0;
     129            $response['model_priority'] = 10;
     130        }
     131
     132        $model_variables = array();
     133        foreach($response as $key=>$value) {
     134            if(substr($key, 0, 6) == "model_") $model_variables[substr($key, 6)] = $value;
     135        }
     136
     137        $models = get_post_meta($post_id, "_iterative_models_{$type}", true);
     138        if(!is_array($models))
     139            $models = array();
     140
     141        $models[$response['model_type']] = $model_variables;
     142
    106143        // store the parameters.
    107         update_post_meta($post_id, "_iterative_parameters_{$type}", $response);
     144        update_post_meta($post_id, "_iterative_parameters_{$response['model_type']}_{$type}", $response);
     145        update_post_meta($post_id, "_iterative_models_{$type}", $models);
    108146        return $response;
    109147    }
     
    128166
    129167    public static function selectVariant($post_id, $variant_hashes) {
    130         // return the hash of a single variant... tell the server that this user has that selected.
    131         // tell the server right away about the variant, but in the future, do it more intelligently (users may see more than one variant on a page load).
     168        // support models.
     169
    132170        $user_id = static::getUserID();
    133171        $unique_id = static::getGUID();
    134         $settings = get_option("iterative_settings");
    135         if(isset($settings['headlines']) && isset($settings['headlines']['goal']))
    136             $type = $settings['headlines']['goal'];
    137         else
    138             $type = ITERATIVE_GOAL_CLICKS;
    139 
    140 
     172       
    141173        if(($variant = static::getVariantForUserID($post_id, $user_id))!==null && in_array($variant, $variant_hashes)) {
    142174            return $variant;   
    143175        } else {
    144             $parameters = static::getParameters($post_id, $type);
    145 
    146             $best = -INF;
    147             $best_hash = null;
    148 
    149             foreach($variant_hashes as $vh) {
    150                 if(!isset($parameters[$vh])) {
    151                     $parameters = IterativeAPI::updateExperiment($post_id, iterative_get_variants($post_id));
     176            // select the right model.
     177            $type = static::getType();
     178            $models = get_post_meta($post_id, "_iterative_models_{$type}", true);
     179            $best_model = current($models);
     180            $second_model = current($models);
     181            foreach($models as $model) {
     182                if($model === $best_model) continue;
     183
     184                if($model['priority'] > $best_model['priority']) {
     185                    $second_model = $best_model;
     186                    $best_model = $model;
     187                } else if($model['priority'] == $best_model['priority']) {
     188                    $second_model = $model;
     189                    // TODO: decide whether to overwrite based on whether it is available or not.
    152190                }
    153 
    154                 $draw = iterative_ib(iterative_urf($parameters[$vh]['c'],1), $parameters[$vh]['a'], $parameters[$vh]['b']);
    155                 if($draw > $best)
    156                 {
    157                     $best = $draw;
    158                     $best_hash = $vh;
    159                 }
    160             }
    161 
    162             $parameters = ['unique_id' => $unique_id, 'user'=>$user_id, 'variant'=>$best_hash, 'experiment_id' => $post_id];
    163             $url_parameters = http_build_query($parameters);
    164 
    165             wp_remote_get(static::$api_endpoint . "variant?" . $url_parameters);
    166             static::storeVariantForUserID($post_id, $user_id, $best_hash);
    167             return $best_hash;
    168         }
     191            }
     192            if($best_model['timestamp'] < time()-static::$reject_age)
     193                $best_model = $second_model;
     194
     195            $method = "model_" . $best_model['type'] . "_" . $best_model['version'];
     196            $hash = static::model_sts_0($post_id, $variant_hashes);
     197            static::tellServerVariantForUserID($unique_id, $user_id, $hash, $post_id);
     198            static::storeVariantForUserID($post_id, $user_id, $hash);
     199
     200            return $hash;
     201        }
     202    }
     203
     204    public static function tellServerVariantForUserID($unique_id, $user_id, $hash, $post_id) {
     205        $variants = get_post_meta($post_id, "_iterative_variants", true);
     206                if(isset($variants[$user_id]) && $variants[$user_id] == $hash) return;
     207        $parameters = ['unique_id' => $unique_id, 'user'=>$user_id, 'variant'=>$hash, 'experiment_id' => $post_id];
     208        static::makeRequest("variant", $parameters);
    169209    }
    170210
     
    227267        return static::$api_endpoint . "js/success?experiment_id=" . $experiment_id . "&user=" . static::getUserID() . "&unique_id=" . static::getGUID() . "&type=" . $type . "&variant_id=" . $variant_id;
    228268    }
     269
     270
     271    // models.
     272    public static function model_sts_0($post_id, $variant_hashes) {
     273        // return the hash of a single variant... tell the server that this user has that selected.
     274        // tell the server right away about the variant, but in the future, do it more intelligently (users may see more than one variant on a page load).
     275        $type = static::getType();
     276        $parameters = static::getParameters($post_id, "sts");
     277       
     278        $best = -INF;
     279        $best_hash = null;
     280
     281        foreach($variant_hashes as $vh) {
     282            if(!isset($parameters[$vh])) {
     283                // our experiment is somehow out of date.
     284                $parameters = IterativeAPI::updateExperiment($post_id, iterative_get_variants($post_id));
     285            }
     286
     287            $draw = iterative_ib(iterative_urf($parameters[$vh]['c'],1), $parameters[$vh]['a'], $parameters[$vh]['b']);
     288            if($draw > $best)
     289            {
     290                $best = $draw;
     291                $best_hash = $vh;
     292            }
     293        }
     294
     295        return $best_hash;
     296    }
    229297}
    230298
  • iterative-headlines/trunk/headlines_options.php

    r1187275 r1190425  
    7676    }
    7777    </script>
    78     <p><label><input type='radio' class='headline-goal' name='iterative_settings[headlines][goal]' <?php checked( $options['headlines']['goal'], ITERATIVE_GOAL_CLICKS ); ?> value='<?php echo ITERATIVE_GOAL_CLICKS; ?>'> I want more of my readers to view my posts.</label></p>
     78    <!-- premium. <p><label><input type='radio' class='headline-goal' name='iterative_settings[headlines][goal]' <?php checked( $options['headlines']['goal'], ITERATIVE_GOAL_CLICKS ); ?> value='<?php echo ITERATIVE_GOAL_CLICKS; ?>'> I want my posts to go viral! <strong>Get me more shares, links, readers and clicks.</strong> <small class="recommended">Recommended</small></label></p>
     79    <p class='description headline-goal-description'>This.</p>-->
     80   
     81    <p><label><input type='radio' class='headline-goal' name='iterative_settings[headlines][goal]' <?php checked( $options['headlines']['goal'], ITERATIVE_GOAL_CLICKS ); ?> value='<?php echo ITERATIVE_GOAL_CLICKS; ?>'> I want more of my readers to read my posts.</label></p>
    7982    <p class='description headline-goal-description'>This will optimize your headlines to increase the number of users who click through from other pages on your site.</p>
    8083    <p><label><input type='radio' class='headline-goal' name='iterative_settings[headlines][goal]' <?php checked( $options['headlines']['goal'], ITERATIVE_GOAL_COMMENTS ); ?> value='<?php echo ITERATIVE_GOAL_COMMENTS; ?>'> I want my readers to comment on my posts.</label></p>
     
    125128        .cta-top a { color:white; }
    126129        .cta-top a:hover { text-shadow:0 1px 8px rgba(0,0,0,0.498039) ;; }
    127         .notyet,.premium {
     130        .notyet,.premium,.recommended {
    128131          border-radius:5px;
    129132          font: normal normal bold 12px "Averia Sans Libre", Helvetica, sans-serif;
     
    146149          background: -moz-linear-gradient(180deg, rgb(218,218,218) 0, rgb(157,157,157) 100%), rgb(218,218,218);
    147150          background: linear-gradient(180deg, rgb(218,218,218) 0, rgb(157,157,157) 100%), rgb(218,218,218);
     151        }
     152        .recommended {
     153          background: -webkit-linear-gradient(180deg, rgb(23, 204, 8) 0, rgb(9, 119, 26) 100%), rgb(27, 169, 48);
     154          background: -moz-linear-gradient(180deg, rgb(23, 204, 8) 0, rgb(9, 119, 26) 100%), rgb(27, 169, 48);
     155          background: linear-gradient(180deg, rgb(23, 204, 8) 0, rgb(9, 119, 26) 100%), rgb(27, 169, 48);
    148156        }
    149157        .iterative { color: #d41f28; font-weight:bold; font-family:Helvetica, arial, sans; }
  • iterative-headlines/trunk/readme.txt

    r1187281 r1190425  
    44Requires at least: 3.0.1
    55Tested up to: 4.2.2
    6 Stable tag: 1.1
     6Stable tag: 1.2
    77License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    6969* First release!
    7070
     71= 1.1 =
     72* Bug fixes.
     73
     74= 1.2 =
     75* New API compatibility. Speed improvements.
     76 
    7177== Upgrade Notice ==
    7278
    7379= 1.0 =
    7480This is the initial release.
     81
     82= 1.2 =
     83Much faster. The plugin now caches all results locally and no longer has any major effect on load time. Also, full support for UTF-8.
Note: See TracChangeset for help on using the changeset viewer.