HubSpot – Free Marketing Plugin for WordPress - Version 2.2.6

Version Description

(2014.12.08) =

Download this release

Release Info

Developer AndyGCook
Plugin Icon 128x128 HubSpot – Free Marketing Plugin for WordPress
Version 2.2.6
Comparing to
See all releases

Code changes from version 2.2.5 to 2.2.6

admin/inc/class-leadin-contact.php CHANGED
@@ -119,11 +119,8 @@ class LI_Contact {
119
  }
120
  else
121
  {
122
- // Set the first submission if it's not set and then leave it alone
123
- if ( ! isset($lead->last_submission) )
124
- $lead->last_submission = $event['event_date'];
125
-
126
- // Always overwrite the last_submission date which will end as last submission date
127
  $lead->first_submission = $event['event_date'];
128
 
129
  $event['form_name'] = 'form';
@@ -159,6 +156,10 @@ class LI_Contact {
159
  $sessions['session_' . $cur_array]['events']['event_' . $cur_event]['form_tags'] = $form_tags;
160
  $sessions['session_' . $cur_array]['events']['event_' . $cur_event]['activities'][] = $event;
161
 
 
 
 
 
162
  // Used for $lead->total_submissions
163
  $total_submissions++;
164
  }
119
  }
120
  else
121
  {
122
+
123
+ // Always overwrite the first_submission date which will end as last submission date
 
 
 
124
  $lead->first_submission = $event['event_date'];
125
 
126
  $event['form_name'] = 'form';
156
  $sessions['session_' . $cur_array]['events']['event_' . $cur_event]['form_tags'] = $form_tags;
157
  $sessions['session_' . $cur_array]['events']['event_' . $cur_event]['activities'][] = $event;
158
 
159
+ // Set the first submission if it's not set and then leave it alone
160
+ if ( ! isset($lead->last_submission) )
161
+ $lead->last_submission = $sessions['session_' . $cur_array]['events']['event_' . $cur_event];
162
+
163
  // Used for $lead->total_submissions
164
  $total_submissions++;
165
  }
admin/inc/class-leadin-tag-editor.php CHANGED
@@ -146,8 +146,6 @@ class LI_Tag_Editor {
146
  SET tag_deleted = 1
147
  WHERE tag_id = %d", $tag_id);
148
 
149
- echo $q;
150
-
151
  $result = $wpdb->query($q);
152
 
153
  return $result;
146
  SET tag_deleted = 1
147
  WHERE tag_id = %d", $tag_id);
148
 
 
 
149
  $result = $wpdb->query($q);
150
 
151
  return $result;
admin/leadin-admin.php CHANGED
@@ -79,16 +79,6 @@ class WPLeadInAdmin {
79
  {
80
  add_action('admin_footer', array($this, 'build_contacts_chart'));
81
  }
82
-
83
- $updater_type = '';
84
-
85
- if ( isset($options['premium']) && $options['premium'] )
86
- $updater_type = 'premium';
87
- else if ( isset($options['beta_tester']) && $options['beta_tester'] )
88
- $updater_type = 'beta';
89
-
90
- if ( $updater_type )
91
- $li_wp_updater = new WPLeadInUpdater($updater_type);
92
  }
93
 
94
  function leadin_update_check ( )
@@ -101,35 +91,13 @@ class WPLeadInAdmin {
101
  if ( !$leadin_active_power_ups )
102
  {
103
  $auto_activate = array(
104
- 'contacts',
105
- 'beta_program'
106
  );
107
 
108
  update_option('leadin_active_power_ups', serialize($auto_activate));
109
  }
110
  else
111
  {
112
- // 0.9.2 upgrade - set beta program power-up to auto-activate
113
- $activated_power_ups = unserialize($leadin_active_power_ups);
114
-
115
- // 0.9.3 bug fix for duplicate beta_program values being stored in the active power-ups array
116
- if ( !in_array('beta_program', $activated_power_ups) )
117
- {
118
- $activated_power_ups[] = 'beta_program';
119
- update_option('leadin_active_power_ups', serialize($activated_power_ups));
120
- }
121
- else
122
- {
123
- $tmp = array_count_values($activated_power_ups);
124
- $count = $tmp['beta_program'];
125
-
126
- if ( $count > 1 )
127
- {
128
- $activated_power_ups = array_unique($activated_power_ups);
129
- update_option('leadin_active_power_ups', serialize($activated_power_ups));
130
- }
131
- }
132
-
133
  // 2.0.1 upgrade - [plugin_slug]_list_sync changed to [plugin_slug]_connect
134
  $mailchimp_list_sync_key = array_search('mailchimp_list_sync', $activated_power_ups);
135
  if ( $mailchimp_list_sync_key !== FALSE )
@@ -186,7 +154,6 @@ class WPLeadInAdmin {
186
  }
187
 
188
  // Set the plugin version
189
- leadin_update_user();
190
  leadin_update_option('leadin_options', 'leadin_version', LEADIN_PLUGIN_VERSION);
191
  }
192
 
@@ -261,8 +228,6 @@ class WPLeadInAdmin {
261
  global $wp_version;
262
  $this->stats_dashboard = new LI_StatsDashboard();
263
 
264
- leadin_track_plugin_activity("Loaded Stats Page");
265
-
266
  if ( !current_user_can( 'manage_categories' ) )
267
  {
268
  wp_die(__('You do not have sufficient permissions to access this page.'));
@@ -381,12 +346,10 @@ class WPLeadInAdmin {
381
  echo '<div id="leadin" class="wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
382
 
383
  if ( $this->action == 'edit_tag' || $this->action == 'add_tag' ) {
384
- leadin_track_plugin_activity("Loaded Tag Editor");
385
  $this->leadin_render_tag_editor();
386
  }
387
  else
388
  {
389
- leadin_track_plugin_activity("Loaded Tag List");
390
  $this->leadin_render_tag_list_page();
391
  }
392
 
@@ -962,8 +925,6 @@ class WPLeadInAdmin {
962
 
963
  if ( isset( $_POST['li_updates_subscription'] ) && $_POST['li_updates_subscription'] )
964
  leadin_subscribe_user_updates();
965
-
966
- //leadin_register_user();
967
  }
968
 
969
  /**
@@ -993,7 +954,6 @@ class WPLeadInAdmin {
993
  {
994
  global $wp_version;
995
 
996
- leadin_track_plugin_activity("Loaded Onboarding Page");
997
  $li_options = get_option('leadin_options');
998
 
999
  echo '<div id="leadin" class="li-onboarding wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
@@ -1008,8 +968,6 @@ class WPLeadInAdmin {
1008
 
1009
  <?php if ( $li_options['onboarding_step'] == 1 ) : ?>
1010
 
1011
- <?php leadin_track_plugin_activity('Onboarding Step 2 - Get Contact Reports'); ?>
1012
-
1013
  <ol class="oboarding-steps-names">
1014
  <li class="oboarding-step-name completed">Activate Leadin</li>
1015
  <li class="oboarding-step-name active">Get Contact Reports</li>
@@ -1037,8 +995,6 @@ class WPLeadInAdmin {
1037
 
1038
  <?php elseif ( $li_options['onboarding_step'] == 2 ) : ?>
1039
 
1040
- <?php leadin_track_plugin_activity('Onboarding Step 3 - Grow Your Contact List'); ?>
1041
-
1042
  <ol class="oboarding-steps-names">
1043
  <li class="oboarding-step-name completed">Activate Leadin</li>
1044
  <li class="oboarding-step-name completed">Get Contact Reports</li>
@@ -1094,16 +1050,12 @@ class WPLeadInAdmin {
1094
  }
1095
 
1096
  leadin_update_option('leadin_subscribe_options', 'li_subscribe_vex_class', $vex_class_option);
1097
- leadin_track_plugin_activity('Onboarding Popup Activated');
1098
  }
1099
- else
1100
- leadin_track_plugin_activity('Onboarding Popup Not Activated');
1101
 
1102
  // Update the onboarding settings
1103
  if ( ! isset($options['onboarding_complete']) || ! $options['onboarding_complete'] )
1104
  {
1105
  leadin_update_option('leadin_options', 'onboarding_complete', 1);
1106
- leadin_track_plugin_activity('Onboarding Complete');
1107
  }
1108
  ?>
1109
 
@@ -1154,8 +1106,6 @@ class WPLeadInAdmin {
1154
  function leadin_plugin_settings ()
1155
  {
1156
  global $wp_version;
1157
-
1158
- leadin_track_plugin_activity("Loaded Settings Page");
1159
 
1160
  echo '<div id="leadin" class="li-settings wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
1161
 
@@ -1222,14 +1172,6 @@ class WPLeadInAdmin {
1222
  if( isset( $input['li_updates_subscription'] ) )
1223
  $new_input['li_updates_subscription'] = $input['li_updates_subscription'];
1224
 
1225
- if( isset( $input['beta_tester'] ) )
1226
- {
1227
- $new_input['beta_tester'] = $input['beta_tester'];
1228
- leadin_set_beta_tester_property(TRUE);
1229
- }
1230
- else
1231
- leadin_set_beta_tester_property(FALSE);
1232
-
1233
  $user_roles = get_editable_roles();
1234
  if ( count($user_roles) )
1235
  {
@@ -1293,8 +1235,6 @@ class WPLeadInAdmin {
1293
  function leadin_power_ups_page ()
1294
  {
1295
  global $wp_version;
1296
-
1297
- leadin_track_plugin_activity("Loaded Power-ups Page");
1298
 
1299
  if ( !current_user_can( 'manage_categories' ) )
1300
  {
@@ -1415,7 +1355,6 @@ class WPLeadInAdmin {
1415
 
1416
  WPLeadIn::activate_power_up( $power_up, FALSE );
1417
  //ob_end_clean();
1418
- leadin_track_plugin_activity($power_up . " power-up activated");
1419
 
1420
  if ( isset($_GET['redirect_to']) )
1421
  wp_redirect($_GET['redirect_to']);
@@ -1430,7 +1369,6 @@ class WPLeadInAdmin {
1430
  $power_up = stripslashes( $_GET['power_up'] );
1431
 
1432
  WPLeadIn::deactivate_power_up( $power_up, FALSE );
1433
- leadin_track_plugin_activity($power_up . " power-up deactivated");
1434
  wp_redirect(get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_power_ups');
1435
  exit;
1436
 
79
  {
80
  add_action('admin_footer', array($this, 'build_contacts_chart'));
81
  }
 
 
 
 
 
 
 
 
 
 
82
  }
83
 
84
  function leadin_update_check ( )
91
  if ( !$leadin_active_power_ups )
92
  {
93
  $auto_activate = array(
94
+ 'contacts'
 
95
  );
96
 
97
  update_option('leadin_active_power_ups', serialize($auto_activate));
98
  }
99
  else
100
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  // 2.0.1 upgrade - [plugin_slug]_list_sync changed to [plugin_slug]_connect
102
  $mailchimp_list_sync_key = array_search('mailchimp_list_sync', $activated_power_ups);
103
  if ( $mailchimp_list_sync_key !== FALSE )
154
  }
155
 
156
  // Set the plugin version
 
157
  leadin_update_option('leadin_options', 'leadin_version', LEADIN_PLUGIN_VERSION);
158
  }
159
 
228
  global $wp_version;
229
  $this->stats_dashboard = new LI_StatsDashboard();
230
 
 
 
231
  if ( !current_user_can( 'manage_categories' ) )
232
  {
233
  wp_die(__('You do not have sufficient permissions to access this page.'));
346
  echo '<div id="leadin" class="wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
347
 
348
  if ( $this->action == 'edit_tag' || $this->action == 'add_tag' ) {
 
349
  $this->leadin_render_tag_editor();
350
  }
351
  else
352
  {
 
353
  $this->leadin_render_tag_list_page();
354
  }
355
 
925
 
926
  if ( isset( $_POST['li_updates_subscription'] ) && $_POST['li_updates_subscription'] )
927
  leadin_subscribe_user_updates();
 
 
928
  }
929
 
930
  /**
954
  {
955
  global $wp_version;
956
 
 
957
  $li_options = get_option('leadin_options');
958
 
959
  echo '<div id="leadin" class="li-onboarding wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
968
 
969
  <?php if ( $li_options['onboarding_step'] == 1 ) : ?>
970
 
 
 
971
  <ol class="oboarding-steps-names">
972
  <li class="oboarding-step-name completed">Activate Leadin</li>
973
  <li class="oboarding-step-name active">Get Contact Reports</li>
995
 
996
  <?php elseif ( $li_options['onboarding_step'] == 2 ) : ?>
997
 
 
 
998
  <ol class="oboarding-steps-names">
999
  <li class="oboarding-step-name completed">Activate Leadin</li>
1000
  <li class="oboarding-step-name completed">Get Contact Reports</li>
1050
  }
1051
 
1052
  leadin_update_option('leadin_subscribe_options', 'li_subscribe_vex_class', $vex_class_option);
 
1053
  }
 
 
1054
 
1055
  // Update the onboarding settings
1056
  if ( ! isset($options['onboarding_complete']) || ! $options['onboarding_complete'] )
1057
  {
1058
  leadin_update_option('leadin_options', 'onboarding_complete', 1);
 
1059
  }
1060
  ?>
1061
 
1106
  function leadin_plugin_settings ()
1107
  {
1108
  global $wp_version;
 
 
1109
 
1110
  echo '<div id="leadin" class="li-settings wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
1111
 
1172
  if( isset( $input['li_updates_subscription'] ) )
1173
  $new_input['li_updates_subscription'] = $input['li_updates_subscription'];
1174
 
 
 
 
 
 
 
 
 
1175
  $user_roles = get_editable_roles();
1176
  if ( count($user_roles) )
1177
  {
1235
  function leadin_power_ups_page ()
1236
  {
1237
  global $wp_version;
 
 
1238
 
1239
  if ( !current_user_can( 'manage_categories' ) )
1240
  {
1355
 
1356
  WPLeadIn::activate_power_up( $power_up, FALSE );
1357
  //ob_end_clean();
 
1358
 
1359
  if ( isset($_GET['redirect_to']) )
1360
  wp_redirect($_GET['redirect_to']);
1369
  $power_up = stripslashes( $_GET['power_up'] );
1370
 
1371
  WPLeadIn::deactivate_power_up( $power_up, FALSE );
 
1372
  wp_redirect(get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_power_ups');
1373
  exit;
1374
 
assets/css/build/leadin-admin.css CHANGED
@@ -2,6 +2,6 @@
2
  #li_analytics-meta .li-analytics-link{float:left}#li_analytics-meta .li-analytics-link .li-analytics__face{height:35px;width:35px;margin-right:5px;margin-bottom:5px}#li_analytics-meta .hidden_face{display:none}#li_analytics-meta .show-all-faces-container{clear:both}.leadin-postbox,.powerup-list .powerup{background-color:#fff;border:1px solid #e5e5e5;-moz-box-shadow:0 1px 1px rgba(0,0,0,0.04);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}.leadin-postbox__header{margin:0;padding:8px 12px;font-size:14px;border-bottom:1px solid #eee}.leadin-postbox__content{margin:11px 0;padding:0 12px;*zoom:1}.leadin-postbox__content:after{content:"";display:table;clear:both}.leadin-postbox__table{margin:0;width:100%}.leadin-postbox__table th{padding:6px 0;text-align:left;text-transform:uppercase;letter-spacing:0.05em}.leadin-postbox__table td{padding:6px 0}.leadin-postbox__table tr,.leadin-postbox__table td,.leadin-postbox__table th{vertical-align:middle !important}.leadin-dynamic-avatar_0{background-color:#f88e4b}.leadin-dynamic-avatar_1{background-color:#64aada}.leadin-dynamic-avatar_2{background-color:#64c2b6}.leadin-dynamic-avatar_3{background-color:#cf7baa}.leadin-dynamic-avatar_4{background-color:#e7c24b}.leadin-dynamic-avatar_5{background-color:#9387da}.leadin-dynamic-avatar_6{background-color:#d6dd99}.leadin-dynamic-avatar_7{background-color:#ff4c4c}.leadin-dynamic-avatar_8{background-color:#99583d}.leadin-dynamic-avatar_9{background-color:#54cc14}@font-face{font-family:"icomoon";src:url("../../fonts/icomoon.eot?-lejfm6");src:url("../../fonts/icomoon.eot?#iefix-lejfm6") format("embedded-opentype"),url("../../fonts/icomoon.woff?-lejfm6") format("woff"),url("../../fonts/icomoon.ttf?-lejfm6") format("truetype"),url("../../fonts/icomoon.svg?-lejfm6#icomoon") format("svg");font-weight:normal;font-style:normal}.icon,.icon-profile,.icon-tag,.icon-tags,.icon-envelope,.icon-user,.icon-cog,.icon-bars,.icon-lab,.icon-bulb,.icon-mover{font-family:"icomoon";speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-profile:before{content:"\e600"}.icon-tag:before{content:"\e601"}.icon-tags:before{content:"\e608"}.icon-envelope:before{content:"\e602"}.icon-user:before{content:"\e603"}.icon-cog:before{content:"\e604"}.icon-bars:before{content:"\e605"}.icon-lab:before{content:"\e606"}.icon-bulb:before{content:"\e607"}.icon-mover:before{content:"\e609"}#leadin-footer{*zoom:1;clear:both;margin-top:48px;color:#999;border-top:1px solid #dedede}#leadin-footer:after{content:"";display:table;clear:both}#leadin-footer .support .sharing{height:18px;text-align:left}@media screen and (min-width: 500px){#leadin-footer .support,#leadin-footer .version,#leadin-footer .sharing{width:50%;float:left}#leadin-footer .sharing{text-align:right}}
3
  .button-big{padding:6px 36px !important;font-size:14px !important;height:auto !important}.oboarding-steps-names{*zoom:1;margin:0}.oboarding-steps-names:after{content:"";display:table;clear:both}.oboarding-step-name{float:left;margin:0;padding-bottom:24px;list-style:decimal inside none;font-size:18px;color:#bbb}.oboarding-step-name.active{color:#1f7d71;background-image:url(../../../images/triangle.png);background-position:bottom center;background-repeat:no-repeat}.oboarding-step-name.completed{list-style-image:url(../../../images/checkmark.png)}.oboarding-step-name+.oboarding-step-name{margin-left:72px}.oboarding-steps{margin:18px 0}@media (min-width: 1200px){.oboarding-steps{width:66.19718%;float:left;margin-right:1.40845%}}
4
  .oboarding-step-content{margin:0 auto;max-width:500px}.oboarding-step-content .description{margin:12px 0;display:block;display:none}.oboarding-step{text-align:center;display:block;padding:36px;background-color:#d3eeeb;border:2px solid #2a9;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;color:#1f7d71}.oboarding-step .form-table th{display:none}.oboarding-step .form-table td{width:auto;display:block}.oboarding-step .form-table input{width:100%;font-size:16px;line-height:1.5;padding:7px 10px;display:block}.oboarding-step .oboarding-step-title,.oboarding-step .oboarding-step-description{color:#1f7d71;padding:0;margin-bottom:36px}.oboarding-step .button-primary{margin-top:36px}.oboarding-step .oboarding-step-description{font-size:16px;text-align:left}.oboarding-step .popup-option{width:31%;float:left;text-align:left;cursor:pointer !important}.oboarding-step .popup-option img{max-width:100%;margin-top:6px;-moz-box-shadow:0 1px 2px rgba(0,0,0,0.15);-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.15);box-shadow:0 1px 2px rgba(0,0,0,0.15);-moz-border-radius:6px;-webkit-border-radius:6px;border-radius:6px}.oboarding-step .popup-option:hover img{-moz-box-shadow:0 2px 4px rgba(0,0,0,0.25);-webkit-box-shadow:0 2px 4px rgba(0,0,0,0.25);box-shadow:0 2px 4px rgba(0,0,0,0.25)}.oboarding-step .popup-option input{margin-right:8px !important}.oboarding-step .popup-option input:checked ~ img{border:2px solid #2ea2cc}.oboarding-step .popup-option+.popup-option{margin-left:3%}.oboarding-step .popup-options{*zoom:1}.oboarding-step .popup-options:after{content:"";display:table;clear:both}.oboarding-steps-help{margin-top:24px;color:#999}@media (min-width: 1200px){.oboarding-steps-help{width:15.49296%;float:left;margin-right:1.40845%;margin-top:60px}}
5
- .li-settings h3{border-left:1px solid #e5e5e5;border-right:1px solid #e5e5e5;border-top:1px solid #e5e5e5;border-bottom:1px solid #e5e5e5;margin-bottom:0px;background:#fff;padding:8px 12px;font-size:15px}.li-settings .form-table{margin-top:0px;border-left:1px solid #e5e5e5;border-right:1px solid #e5e5e5;border-bottom:1px solid #e5e5e5;background-color:#fff;-moz-box-shadow:0 1px 1px rgba(0,0,0,0.04);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}.li-settings .form-table th{padding-left:12px}.li-settings .leadin-section{background-color:#fff;border-left:1px solid #e5e5e5;border-right:1px solid #e5e5e5;font-size:14px;padding:15px 12px 5px 12px}.li-settings .leadin-section p{margin:0;padding:0}.li-settings .power-up-settings-icon{padding-right:10px;float:left;max-height:20px;margin-top:-1px}.li-settings .dashicons{margin-right:10px;float:left;margin-top:-1px}.li-settings tr.synced-list-row td.synced-list-cell{padding:3px 0px 10px 0px}.li-settings tr.synced-list-row td.synced-list-cell .icon-tag{font-size:12px}.li-settings tr.synced-list-row span.synced-list-arrow{padding:0px 10px}.li-settings tr.synced-list-row td.synced-list-edit{padding:3px 0px 10px 20px}.li-settings.pre-mp6 h3{font-family:Georgia}.li-settings.pre-mp6 select,.li-settings.pre-mp6 input{font-family:sans-serif;font-size:12px}.li-settings.pre-mp6 .form-table,.li-settings.pre-mp6 .leadin-section,.li-settings.pre-mp6 h3{background-color:#f9f9f9 !important}.li-settings.pre-mp6 .form-table{-moz-border-radius-bottomleft:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-moz-border-radius-bottomright:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px}.li-settings.pre-mp6 h3{background-color:#f9f9f9 !important;-moz-border-radius-topleft:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-topright:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px}.li-settings.pre-mp6 .leadin-section{font-size:12px;padding-left:6px}.li-settings.pre-mp6 h3{padding-left:6px;font-weight:normal;color:#464646;text-shadow:#fff 0px 1px 0px}.li-settings.pre-mp6 label{font-size:12px}.li-settings.pre-mp6 input[type="checkbox"],.li-settings.pre-mp6 input[type="radio"]{margin-right:2px}#icon-leadin{background:url("../../images/leadin-icon-32x32.png") top center no-repeat}.help-notification{background:#d9edf7;border:1px solid #bce8f1;padding:10px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.toplevel_page_leadin_stats .wp-menu-image img{width:16px;height:16px}.leadin-contact-avatar{margin-right:10px;float:left}.leadin-contacts .button{transition:background-color 0.2s}@media (min-width: 1200px){.leadin-contacts__nav{width:15.49296%;float:left;margin-right:1.40845%}.leadin-contacts__content{width:83.09859%;float:right;margin-right:0;margin-bottom:18px}.leadin-contacts__export-form{width:83.09859%;float:left;margin-right:1.40845%;padding-left:16.90141%;margin-bottom:18px}}h2.leadin-contacts__header{margin-bottom:30px}.leadin-contacts__search{float:right;padding:10px 0;padding-bottom:9px}.leadin-contacts__type-picker{margin:0 0 30px;*zoom:1}.leadin-contacts__type-picker:after{content:"";display:table;clear:both}.leadin-contacts__type-picker li{margin:0;padding:0 1em 0 0;float:left}@media (min-width: 1200px){.leadin-contacts__type-picker li{float:none;padding:0}.leadin-contacts__type-picker li+li{padding:18px 0 0}}.leadin-contacts__type-picker li a{display:block;line-height:24px;font-weight:400;font-size:16px;text-decoration:none}.leadin-contacts__type-picker li a.current{font-weight:bold}.leadin-contacts__type-picker li a.current,.leadin-contacts__type-picker li a:hover,.leadin-contacts__type-picker li a:active{color:#f67d42}.leadin-contacts__type-picker li a .icon-tag,.leadin-contacts__type-picker li a .icon-user{padding-right:1em;font-size:0.85em}.leadin-contacts__tags-header{margin:30px 0 18px;font-size:14px;text-transform:uppercase;letter-spacing:0.1em;color:#999}.leadin-contacts__filter-text{margin:0 0 18px}.leadin-contacts__filter-count{color:#f67d42}#clear-filter{font-size:0.8em;margin-left:10px}.leadin-contacts__table table th#source{width:20%}.leadin-contacts__table table th#visits,.leadin-contacts__table table th#submissions{width:8%}.leadin-contacts__table table th#status,.leadin-contacts__table table th#last_visit,.leadin-contacts__table table th#date,.leadin-contacts__table table th#pageviews{width:10%}.leadin-contacts__table table th,.leadin-contacts__table table td{display:none}.leadin-contacts__table table th:nth-child(-n+3),.leadin-contacts__table table td:nth-child(-n+3){display:table-cell}@media (min-width: 1200px){.leadin-contacts__table table th,.leadin-contacts__table table td{display:table-cell}}
6
- .leadin-contacts.pre-mp6 .table_search{float:right;padding:12px 0;padding-bottom:11px}.leadin-contacts.pre-mp6 table{background-color:#fff;border-color:#dedede}.leadin-contacts.pre-mp6 table tr.alternate{background-color:#fff}.leadin-contacts.pre-mp6 table th,.leadin-contacts.pre-mp6 table td{border-top:0;padding:12px 6px 11px}.leadin-contacts.pre-mp6 table th a,.leadin-contacts.pre-mp6 table td a{padding:0}.leadin-contacts.pre-mp6 table th[scope="col"]{background:#eee;font-family:sans-serif;font-size:12px;text-shadow:none}.leadin-contacts.pre-mp6 table td{border-color:#dedede;line-height:18px;font-size:14px}.leadin-contacts.pre-mp6 table td .row-actions{float:left}#leadin .contact-header-wrap{*zoom:1;padding:18px 0 24px}#leadin .contact-header-wrap:after{content:"";display:table;clear:both}#leadin .contact-header-wrap .contact-header-avatar,#leadin .contact-header-wrap .contact-header-info{float:left}#leadin .contact-header-info{padding-left:15px}#leadin .contact-name{line-height:30px;padding:0;margin:0}#leadin .contact-tags{margin-top:15px}#leadin .contact-tag{padding:4px 10px;color:#fff;background-color:#f67d42;text-decoration:none;font-weight:600;text-transform:uppercase;letter-spacing:0.1em;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}#leadin .contact-tag:hover{opacity:0.9}#leadin .contact-tag+.contact-tag,#leadin .contact-tag+.contact-edit-tags{margin-left:10px}#leadin .contact-tag .icon-tag{padding-right:10px}#leadin .contact-info h3{margin:0}#leadin .contact-info label{font-weight:bold;line-height:1;cursor:default}#leadin .leadin-meta-section+.leadin-meta-section{margin-top:24px}#leadin .leadin-meta-table{width:100%;text-align:left}#leadin .leadin-meta-table th{color:#666;padding-bottom:6px}#leadin .leain-meta-header,#leadin .contact-history .session-date{margin:0 0 12px;text-transform:uppercase;letter-spacing:0.05em;color:#444}#leadin .leadin-premium-tag:after{content:"premium";margin-left:10px;font-size:10px;color:#fff;background-color:#93c054;padding:2px 6px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}#leadin .contact-history{margin-left:20px}@media (min-width: 1200px){#leadin .contact-history{padding-left:20px;border-left:2px solid #dedede}}#leadin .contact-history .sessions{margin:0}#leadin .contact-history .session+.session{margin-top:30px}#leadin .contact-history .session-date{position:relative}@media (min-width: 1200px){#leadin .contact-history .session-date:before{content:"\2022";font-size:32px;line-height:0;height:31px;width:31px;position:absolute;left:-27px;top:9px;color:#dedede}}#leadin .contact-history .session-time-range{color:#999;font-weight:400}#leadin .contact-history .events{background-color:#fff;border:1px solid #dedede;-moz-box-shadow:0 1px 1px rgba(0,0,0,0.04);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}#leadin .contact-history .event{margin:0;padding:10px 20px;border-bottom:1px solid #dedede;border-left:4px solid;*zoom:1}#leadin .contact-history .event:after{content:"";display:table;clear:both}#leadin .contact-history .event:first-child{border-top:0}#leadin .contact-history .event.pageview{border-left-color:#28c;color:#28c}#leadin .contact-history .event.form-submission{border-left-color:#f67d42;color:#f67d42}#leadin .contact-history .event.source{border-left-color:#99aa1f;color:#99aa1f}#leadin .contact-history .event-title{margin:0;font-size:13px;font-weight:600}#leadin .contact-history .event-time{float:left;font-weight:400;width:75px}#leadin .contact-history .event-content{margin-left:75px}#leadin .contact-history .event-detail{margin-top:20px;color:#444}#leadin .contact-history .event-detail li+li{padding-top:6px;border-top:1px solid #eee}#leadin .contact-history .event-detail.pageview-url{color:#ccc}#leadin .contact-history .visit-source p{margin:0;color:#1f6696}#leadin .contact-history .field-label{text-transform:uppercase;letter-spacing:0.05em;color:#999;margin-bottom:6px;font-size:0.9em}#leadin .contact-history .field-value{margin:0}#leadin.pre-mp6 .events{background-color:#f9f9f9}.powerup-list{margin:0}.powerup-list .powerup{width:20%;min-width:250px;float:left;margin:20px;padding:15px}.powerup-list .powerup h2,.powerup-list .powerup p{margin:0;padding:0;color:#666;margin-bottom:15px}.powerup-list .powerup .img-containter{text-align:center;padding:30px 15px;margin-bottom:15px;background-color:#f1f1f1;color:red}.powerup-list .powerup .img-containter h2{font-size:20px}.powerup-list .powerup.activated h2,.powerup-list .powerup.activated p{color:#1f7d71}.powerup-list .powerup.activated .img-containter{background-color:#d3eeeb}@media (min-width: 1200px){.leadin-stats__top-container,.leadin-stats__chart-container,.leadin-stats__big-numbers-container{width:100%;float:right;margin-right:0}.leadin-stats__postbox_containter{width:49.29577%;float:left;margin-right:1.40845%}.leadin-stats__postbox_containter:nth-child(2n+2){width:49.29577%;float:right;margin-right:0}}h2.leadin-stats__header{margin-bottom:12px}.leadin-stats__postbox_containter .leadin-postbox,.leadin-stats__postbox_containter .powerup-list .powerup,.powerup-list .leadin-stats__postbox_containter .powerup{margin-bottom:12px}.leadin-stats__big-number{text-align:center;width:42%;float:left;padding:4%}@media (min-width: 1200px){.leadin-stats__big-number{width:25%;padding:10px}}
7
  .big-number--average .leadin-stats__big-number-top-label,.big-number--average .leadin-stats__big-number-content,.big-number--average .leadin-stats__big-number-bottom-label{color:#4ca6cf}.leadin-stats__top-container,.leadin-stats__big-number-top-label,.leadin-stats__big-number-content,.leadin-stats__big-number-bottom-label{color:#666;margin-bottom:12px}.leadin-stats__big-number-top-label{text-transform:uppercase;letter-spacing:0.05em}
2
  #li_analytics-meta .li-analytics-link{float:left}#li_analytics-meta .li-analytics-link .li-analytics__face{height:35px;width:35px;margin-right:5px;margin-bottom:5px}#li_analytics-meta .hidden_face{display:none}#li_analytics-meta .show-all-faces-container{clear:both}.leadin-postbox,.powerup-list .powerup{background-color:#fff;border:1px solid #e5e5e5;-moz-box-shadow:0 1px 1px rgba(0,0,0,0.04);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}.leadin-postbox__header{margin:0;padding:8px 12px;font-size:14px;border-bottom:1px solid #eee}.leadin-postbox__content{margin:11px 0;padding:0 12px;*zoom:1}.leadin-postbox__content:after{content:"";display:table;clear:both}.leadin-postbox__table{margin:0;width:100%}.leadin-postbox__table th{padding:6px 0;text-align:left;text-transform:uppercase;letter-spacing:0.05em}.leadin-postbox__table td{padding:6px 0}.leadin-postbox__table tr,.leadin-postbox__table td,.leadin-postbox__table th{vertical-align:middle !important}.leadin-dynamic-avatar_0{background-color:#f88e4b}.leadin-dynamic-avatar_1{background-color:#64aada}.leadin-dynamic-avatar_2{background-color:#64c2b6}.leadin-dynamic-avatar_3{background-color:#cf7baa}.leadin-dynamic-avatar_4{background-color:#e7c24b}.leadin-dynamic-avatar_5{background-color:#9387da}.leadin-dynamic-avatar_6{background-color:#d6dd99}.leadin-dynamic-avatar_7{background-color:#ff4c4c}.leadin-dynamic-avatar_8{background-color:#99583d}.leadin-dynamic-avatar_9{background-color:#54cc14}@font-face{font-family:"icomoon";src:url("../../fonts/icomoon.eot?-lejfm6");src:url("../../fonts/icomoon.eot?#iefix-lejfm6") format("embedded-opentype"),url("../../fonts/icomoon.woff?-lejfm6") format("woff"),url("../../fonts/icomoon.ttf?-lejfm6") format("truetype"),url("../../fonts/icomoon.svg?-lejfm6#icomoon") format("svg");font-weight:normal;font-style:normal}.icon,.icon-profile,.icon-tag,.icon-tags,.icon-envelope,.icon-user,.icon-cog,.icon-bars,.icon-lab,.icon-bulb,.icon-mover{font-family:"icomoon";speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-profile:before{content:"\e600"}.icon-tag:before{content:"\e601"}.icon-tags:before{content:"\e608"}.icon-envelope:before{content:"\e602"}.icon-user:before{content:"\e603"}.icon-cog:before{content:"\e604"}.icon-bars:before{content:"\e605"}.icon-lab:before{content:"\e606"}.icon-bulb:before{content:"\e607"}.icon-mover:before{content:"\e609"}#leadin-footer{*zoom:1;clear:both;margin-top:48px;color:#999;border-top:1px solid #dedede}#leadin-footer:after{content:"";display:table;clear:both}#leadin-footer .support .sharing{height:18px;text-align:left}@media screen and (min-width: 500px){#leadin-footer .support,#leadin-footer .version,#leadin-footer .sharing{width:50%;float:left}#leadin-footer .sharing{text-align:right}}
3
  .button-big{padding:6px 36px !important;font-size:14px !important;height:auto !important}.oboarding-steps-names{*zoom:1;margin:0}.oboarding-steps-names:after{content:"";display:table;clear:both}.oboarding-step-name{float:left;margin:0;padding-bottom:24px;list-style:decimal inside none;font-size:18px;color:#bbb}.oboarding-step-name.active{color:#1f7d71;background-image:url(../../../images/triangle.png);background-position:bottom center;background-repeat:no-repeat}.oboarding-step-name.completed{list-style-image:url(../../../images/checkmark.png)}.oboarding-step-name+.oboarding-step-name{margin-left:72px}.oboarding-steps{margin:18px 0}@media (min-width: 1200px){.oboarding-steps{width:66.19718%;float:left;margin-right:1.40845%}}
4
  .oboarding-step-content{margin:0 auto;max-width:500px}.oboarding-step-content .description{margin:12px 0;display:block;display:none}.oboarding-step{text-align:center;display:block;padding:36px;background-color:#d3eeeb;border:2px solid #2a9;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;color:#1f7d71}.oboarding-step .form-table th{display:none}.oboarding-step .form-table td{width:auto;display:block}.oboarding-step .form-table input{width:100%;font-size:16px;line-height:1.5;padding:7px 10px;display:block}.oboarding-step .oboarding-step-title,.oboarding-step .oboarding-step-description{color:#1f7d71;padding:0;margin-bottom:36px}.oboarding-step .button-primary{margin-top:36px}.oboarding-step .oboarding-step-description{font-size:16px;text-align:left}.oboarding-step .popup-option{width:31%;float:left;text-align:left;cursor:pointer !important}.oboarding-step .popup-option img{max-width:100%;margin-top:6px;-moz-box-shadow:0 1px 2px rgba(0,0,0,0.15);-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.15);box-shadow:0 1px 2px rgba(0,0,0,0.15);-moz-border-radius:6px;-webkit-border-radius:6px;border-radius:6px}.oboarding-step .popup-option:hover img{-moz-box-shadow:0 2px 4px rgba(0,0,0,0.25);-webkit-box-shadow:0 2px 4px rgba(0,0,0,0.25);box-shadow:0 2px 4px rgba(0,0,0,0.25)}.oboarding-step .popup-option input{margin-right:8px !important}.oboarding-step .popup-option input:checked ~ img{border:2px solid #2ea2cc}.oboarding-step .popup-option+.popup-option{margin-left:3%}.oboarding-step .popup-options{*zoom:1}.oboarding-step .popup-options:after{content:"";display:table;clear:both}.oboarding-steps-help{margin-top:24px;color:#999}@media (min-width: 1200px){.oboarding-steps-help{width:15.49296%;float:left;margin-right:1.40845%;margin-top:60px}}
5
+ .li-settings h3{border-left:1px solid #e5e5e5;border-right:1px solid #e5e5e5;border-top:1px solid #e5e5e5;border-bottom:1px solid #e5e5e5;margin-bottom:0px;background:#fff;padding:8px 12px;font-size:15px}.li-settings .form-table{margin-top:0px;border-left:1px solid #e5e5e5;border-right:1px solid #e5e5e5;border-bottom:1px solid #e5e5e5;background-color:#fff;-moz-box-shadow:0 1px 1px rgba(0,0,0,0.04);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}.li-settings .form-table th{padding-left:12px}.li-settings .leadin-section{background-color:#fff;border-left:1px solid #e5e5e5;border-right:1px solid #e5e5e5;font-size:14px;padding:15px 12px 5px 12px}.li-settings .leadin-section p{margin:0;padding:0}.li-settings.pre-mp6 h3{font-family:Georgia}.li-settings.pre-mp6 select,.li-settings.pre-mp6 input{font-family:sans-serif;font-size:12px}.li-settings.pre-mp6 .form-table,.li-settings.pre-mp6 .leadin-section,.li-settings.pre-mp6 h3{background-color:#f9f9f9 !important}.li-settings.pre-mp6 .form-table{-moz-border-radius-bottomleft:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-moz-border-radius-bottomright:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px}.li-settings.pre-mp6 h3{background-color:#f9f9f9 !important;-moz-border-radius-topleft:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-topright:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px}.li-settings.pre-mp6 .leadin-section{font-size:12px;padding-left:6px}.li-settings.pre-mp6 h3{padding-left:6px;font-weight:normal;color:#464646;text-shadow:#fff 0px 1px 0px}.li-settings.pre-mp6 label{font-size:12px}.li-settings.pre-mp6 input[type="checkbox"],.li-settings.pre-mp6 input[type="radio"]{margin-right:2px}#icon-leadin{background:url("../../images/leadin-icon-32x32.png") top center no-repeat}.help-notification{background:#d9edf7;border:1px solid #bce8f1;padding:10px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.toplevel_page_leadin_stats .wp-menu-image img{width:16px;height:16px}.leadin-contact-avatar{margin-right:10px;float:left}.power-up-settings-icon{padding-right:10px;float:left;max-height:20px;margin-top:-1px}.dashicons{margin-right:10px;float:left;margin-top:-1px}tr.synced-list-row td.synced-list-cell{padding:3px 0px 10px 0px}tr.synced-list-row td.synced-list-cell .icon-tag{font-size:12px}tr.synced-list-row span.synced-list-arrow{padding:0px 10px}tr.synced-list-row td.synced-list-edit{padding:3px 0px 10px 20px}.leadin-contacts .button{transition:background-color 0.2s}@media (min-width: 1200px){.leadin-contacts__nav{width:15.49296%;float:left;margin-right:1.40845%}.leadin-contacts__content{width:83.09859%;float:right;margin-right:0;margin-bottom:18px}.leadin-contacts__export-form{width:83.09859%;float:left;margin-right:1.40845%;padding-left:16.90141%;margin-bottom:18px}}h2.leadin-contacts__header{margin-bottom:30px}.leadin-contacts__search{float:right;padding:10px 0;padding-bottom:9px}.leadin-contacts__type-picker{margin:0 0 30px;*zoom:1}.leadin-contacts__type-picker:after{content:"";display:table;clear:both}.leadin-contacts__type-picker li{margin:0;padding:0 1em 0 0;float:left}@media (min-width: 1200px){.leadin-contacts__type-picker li{float:none;padding:0}.leadin-contacts__type-picker li+li{padding:18px 0 0}}.leadin-contacts__type-picker li a{display:block;line-height:24px;font-weight:400;font-size:16px;text-decoration:none}.leadin-contacts__type-picker li a.current{font-weight:bold}.leadin-contacts__type-picker li a.current,.leadin-contacts__type-picker li a:hover,.leadin-contacts__type-picker li a:active{color:#f67d42}.leadin-contacts__type-picker li a .icon-tag,.leadin-contacts__type-picker li a .icon-user{padding-right:1em;font-size:0.85em}.leadin-contacts__tags-header{margin:30px 0 18px;font-size:14px;text-transform:uppercase;letter-spacing:0.1em;color:#999}.leadin-contacts__filter-text{margin:0 0 18px}.leadin-contacts__filter-count{color:#f67d42}#clear-filter{font-size:0.8em;margin-left:10px}.leadin-contacts__table table th#source{width:20%}.leadin-contacts__table table th#visits,.leadin-contacts__table table th#submissions{width:8%}.leadin-contacts__table table th#status,.leadin-contacts__table table th#last_visit,.leadin-contacts__table table th#date,.leadin-contacts__table table th#pageviews{width:10%}.leadin-contacts__table table th,.leadin-contacts__table table td{display:none}.leadin-contacts__table table th:nth-child(-n+3),.leadin-contacts__table table td:nth-child(-n+3){display:table-cell}@media (min-width: 1200px){.leadin-contacts__table table th,.leadin-contacts__table table td{display:table-cell}}
6
+ .leadin-contacts.pre-mp6 .table_search{float:right;padding:12px 0;padding-bottom:11px}.leadin-contacts.pre-mp6 table{background-color:#fff;border-color:#dedede}.leadin-contacts.pre-mp6 table tr.alternate{background-color:#fff}.leadin-contacts.pre-mp6 table th,.leadin-contacts.pre-mp6 table td{border-top:0;padding:12px 6px 11px}.leadin-contacts.pre-mp6 table th a,.leadin-contacts.pre-mp6 table td a{padding:0}.leadin-contacts.pre-mp6 table th[scope="col"]{background:#eee;font-family:sans-serif;font-size:12px;text-shadow:none}.leadin-contacts.pre-mp6 table td{border-color:#dedede;line-height:18px;font-size:14px}.leadin-contacts.pre-mp6 table td .row-actions{float:left}#leadin .contact-header-wrap{*zoom:1;padding:9px 0 4px}#leadin .contact-header-wrap:after{content:"";display:table;clear:both}#leadin .contact-header-wrap .contact-header-avatar,#leadin .contact-header-wrap .contact-header-info{float:left}#leadin .contact-header-info{padding-left:15px}#leadin .contact-name{line-height:30px;padding:0;margin:0}#leadin .contact-tags{margin-top:15px}#leadin .contact-tag{padding:4px 10px;color:#fff;background-color:#f67d42;text-decoration:none;font-weight:600;text-transform:uppercase;letter-spacing:0.1em;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}#leadin .contact-tag:hover{opacity:0.9}#leadin .contact-tag+.contact-tag,#leadin .contact-tag+.contact-edit-tags{margin-left:10px}#leadin .contact-tag .icon-tag{padding-right:10px}#leadin .contact-info h3{margin:0}#leadin .contact-info label{font-weight:bold;line-height:1;cursor:default}#leadin .contact-history{margin-left:20px}@media (min-width: 1200px){#leadin .contact-history{padding-left:20px;border-left:2px solid #dedede}}#leadin .contact-history .session+.session{margin-top:30px}#leadin .contact-history .session-date{position:relative}@media (min-width: 1200px){#leadin .contact-history .session-date:before{content:"\2022";font-size:32px;line-height:0;height:31px;width:31px;position:absolute;left:-27px;top:9px;color:#dedede}}#leadin .contact-history .session-time-range{color:#999;font-weight:400}#leadin .contact-history .events{background-color:#fff;border:1px solid #dedede;-moz-box-shadow:0 1px 1px rgba(0,0,0,0.04);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}#leadin .contact-history .event{margin:0;padding:10px 20px;border-bottom:1px solid #dedede;border-left:4px solid;*zoom:1}#leadin .contact-history .event:after{content:"";display:table;clear:both}#leadin .contact-history .event:first-child{border-top:0}#leadin .contact-history .event.pageview{border-left-color:#28c;color:#28c}#leadin .contact-history .event.form-submission{border-left-color:#f67d42;color:#f67d42}#leadin .contact-history .event.source{border-left-color:#99aa1f;color:#99aa1f}#leadin .contact-history .event-title{margin:0;font-size:13px;font-weight:600}#leadin .contact-history .event-time{float:left;font-weight:400;width:75px}#leadin .contact-history .event-content{margin-left:75px}#leadin .contact-history .event-detail{margin-top:20px;color:#444}#leadin .contact-history .event-detail li+li{padding-top:6px;border-top:1px solid #eee}#leadin .contact-history .event-detail.pageview-url{color:#ccc}#leadin .contact-history .visit-source p{margin:0;color:#1f6696}#leadin .contact-history .field-label{text-transform:uppercase;letter-spacing:0.05em;color:#999;margin-bottom:6px;font-size:0.9em}#leadin .contact-history .field-value{margin:0}#leadin.pre-mp6 .events{background-color:#f9f9f9}.powerup-list{margin:0}.powerup-list .powerup{width:20%;min-width:250px;float:left;margin:20px;padding:15px}.powerup-list .powerup h2,.powerup-list .powerup p{margin:0;padding:0;color:#666;margin-bottom:15px}.powerup-list .powerup .img-containter{text-align:center;padding:30px 15px;margin-bottom:15px;background-color:#f1f1f1;color:red}.powerup-list .powerup .img-containter h2{font-size:20px}.powerup-list .powerup.activated h2,.powerup-list .powerup.activated p{color:#1f7d71}.powerup-list .powerup.activated .img-containter{background-color:#d3eeeb}@media (min-width: 1200px){.leadin-stats__top-container,.leadin-stats__chart-container,.leadin-stats__big-numbers-container{width:100%;float:right;margin-right:0}.leadin-stats__postbox_containter{width:49.29577%;float:left;margin-right:1.40845%}.leadin-stats__postbox_containter:nth-child(2n+2){width:49.29577%;float:right;margin-right:0}}h2.leadin-stats__header{margin-bottom:12px}.leadin-stats__postbox_containter .leadin-postbox,.leadin-stats__postbox_containter .powerup-list .powerup,.powerup-list .leadin-stats__postbox_containter .powerup{margin-bottom:12px}.leadin-stats__big-number{text-align:center;width:42%;float:left;padding:4%}@media (min-width: 1200px){.leadin-stats__big-number{width:25%;padding:10px}}
7
  .big-number--average .leadin-stats__big-number-top-label,.big-number--average .leadin-stats__big-number-content,.big-number--average .leadin-stats__big-number-bottom-label{color:#4ca6cf}.leadin-stats__top-container,.leadin-stats__big-number-top-label,.leadin-stats__big-number-content,.leadin-stats__big-number-bottom-label{color:#666;margin-bottom:12px}.leadin-stats__big-number-top-label{text-transform:uppercase;letter-spacing:0.05em}
assets/js/build/leadin-tracking.js CHANGED
@@ -331,19 +331,7 @@ function leadin_submit_form ( $form, $ )
331
 
332
  // Set phone number
333
  if ( lower_label_text == 'phone' || lower_label_text == 'phone' )
334
- lead_phone = $value;
335
-
336
- /*
337
- @TODO
338
- √ Look at contact labels for last 50 installations and look for patterns
339
- √ Modify ajax methods to take in a first + last name
340
- √ Roll in premium updates inside the interface for the contact records
341
- √ Modify the contact list to show first + last names
342
- - Retroactively try to parse out all the names from previous submissions
343
- - What's the overhead for this going to look like on update
344
- */
345
-
346
-
347
  });
348
 
349
  var radio_groups = [];
331
 
332
  // Set phone number
333
  if ( lower_label_text == 'phone' || lower_label_text == 'phone' )
334
+ lead_phone = $value;
 
 
 
 
 
 
 
 
 
 
 
 
335
  });
336
 
337
  var radio_groups = [];
inc/class-emailer.php CHANGED
@@ -43,18 +43,20 @@ class LI_Emailer {
43
  $options = get_option('leadin_options');
44
  $to = ( $options['li_email'] ? $options['li_email'] : get_bloginfo('admin_email') ); // Get email from plugin settings, if none set, use admin email
45
 
46
- $return_status = '';
 
 
 
 
47
  if ( $history->lead->total_visits > 1 )
48
- $return_status = ' by a returning visitor ';
49
 
50
  if ( $history->lead->total_submissions > 1 )
51
- $return_status = ' by a returning contact ';
52
 
53
- $subject = "Form submission " . $return_status . " on " . get_bloginfo('name') . " - " . $history->lead->lead_email;
54
  $email_sent = wp_mail($to, $subject, $body, $headers);
55
 
56
- if ( $email_sent )
57
- leadin_track_plugin_activity('Contact Notification Sent');
58
 
59
  return $email_sent;
60
  }
@@ -82,7 +84,6 @@ class LI_Emailer {
82
  function build_submission_details ( $url ) {
83
  $format = '<table class="row submission-detail" style="border-spacing: 0;border-collapse: collapse;padding: 0px;vertical-align: top;text-align: left;width: 100%%;position: relative;display: block;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="wrapper last" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 10px 20px 0px 0px;vertical-align: top;text-align: left;position: relative;padding-right: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><table class="twelve columns" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;margin: 0 auto;width: 580px;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="text-pad" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0px 0px 10px;vertical-align: top;text-align: left;padding-left: 10px;padding-right: 10px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><h3 style="color: #666;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 18px;">New submission on <a href="%s" style="color: #2ba6cb;text-decoration: none;">%s</a></h3></td><td class="expander" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;visibility: hidden;width: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"></td></tr></table></td></tr></table>' . "\r\n";
84
  $built_submission_details = sprintf($format, $url, get_bloginfo('name'));
85
- $built_submission_details .= '<img src="' . $this->create_tracking_pixel() . '"/>';
86
 
87
  return $built_submission_details;
88
  }
@@ -354,30 +355,4 @@ class LI_Emailer {
354
 
355
  return $powered_by;
356
  }
357
-
358
- /**
359
- * Creates Mixpanel tracking email pixel
360
- *
361
- * @return string specs @ https://mixpanel.com/docs/api-documentation/pixel-based-event-tracking
362
- */
363
- function create_tracking_pixel ( )
364
- {
365
- $url_properties = array(
366
- 'token' => MIXPANEL_PROJECT_TOKEN
367
- );
368
-
369
- $leadin_user = leadin_get_current_user();
370
- $leadin_user_properties = array(
371
- 'distinct_id' => $leadin_user['user_id'],
372
- '$wp-url' => $leadin_user['wp_url'],
373
- '$wp-version' => $leadin_user['wp_version'],
374
- '$li-version' => $leadin_user['li_version']
375
- );
376
-
377
- $properties = array_merge($url_properties, $leadin_user_properties);
378
-
379
- $params = array ( 'event' => 'Contact Notification Opened', 'properties' => $properties );
380
-
381
- return 'http://api.mixpanel.com/track/?data=' . base64_encode(json_encode($params)) . '&ip=1&img=1';
382
- }
383
  }
43
  $options = get_option('leadin_options');
44
  $to = ( $options['li_email'] ? $options['li_email'] : get_bloginfo('admin_email') ); // Get email from plugin settings, if none set, use admin email
45
 
46
+ $tag_status = '';
47
+ if ( count($history->lead->last_submission['form_tags']) )
48
+ $tag_status = 'tagged as "' . $history->lead->last_submission['form_tags'][0]['tag_text'] . '" ';
49
+
50
+ $return_status = ( $tag_status ? '' : ' ' );
51
  if ( $history->lead->total_visits > 1 )
52
+ $return_status = 'by a returning visitor ';
53
 
54
  if ( $history->lead->total_submissions > 1 )
55
+ $return_status = 'by a returning contact ';
56
 
57
+ $subject = "Form submission " . $tag_status . $return_status . "on " . get_bloginfo('name') . " - " . $history->lead->lead_email;
58
  $email_sent = wp_mail($to, $subject, $body, $headers);
59
 
 
 
60
 
61
  return $email_sent;
62
  }
84
  function build_submission_details ( $url ) {
85
  $format = '<table class="row submission-detail" style="border-spacing: 0;border-collapse: collapse;padding: 0px;vertical-align: top;text-align: left;width: 100%%;position: relative;display: block;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="wrapper last" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 10px 20px 0px 0px;vertical-align: top;text-align: left;position: relative;padding-right: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><table class="twelve columns" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;margin: 0 auto;width: 580px;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="text-pad" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0px 0px 10px;vertical-align: top;text-align: left;padding-left: 10px;padding-right: 10px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><h3 style="color: #666;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 18px;">New submission on <a href="%s" style="color: #2ba6cb;text-decoration: none;">%s</a></h3></td><td class="expander" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;visibility: hidden;width: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"></td></tr></table></td></tr></table>' . "\r\n";
86
  $built_submission_details = sprintf($format, $url, get_bloginfo('name'));
 
87
 
88
  return $built_submission_details;
89
  }
355
 
356
  return $powered_by;
357
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
  }
inc/class-leadin.php CHANGED
@@ -36,6 +36,8 @@ class WPLeadIn {
36
  else
37
  add_action('wp_enqueue_scripts', array($this, 'add_leadin_frontend_scripts'));
38
  }
 
 
39
  }
40
 
41
  //=============================================
@@ -208,8 +210,7 @@ class WPLeadIn {
208
  LEADIN_PLUGIN_DIR . '/power-ups/contacts.php',
209
  LEADIN_PLUGIN_DIR . '/power-ups/subscribe-widget.php',
210
  LEADIN_PLUGIN_DIR . '/power-ups/mailchimp-connect.php',
211
- LEADIN_PLUGIN_DIR . '/power-ups/constant-contact-connect.php',
212
- LEADIN_PLUGIN_DIR . '/power-ups/beta-program.php'
213
  ));
214
 
215
  closedir( $dir );
@@ -242,7 +243,7 @@ class WPLeadIn {
242
  return array();
243
  }
244
 
245
- public static function activate_power_up( $power_up_slug, $exit = TRUE )
246
  {
247
  if ( ! strlen( $power_up_slug ) )
248
  return FALSE;
@@ -273,12 +274,12 @@ class WPLeadIn {
273
  }
274
  }
275
 
276
- public static function deactivate_power_up( $power_up_slug, $exit = TRUE )
277
  {
278
  if ( ! strlen( $power_up_slug ) )
279
  return FALSE;
280
 
281
- // If it's already active, then don't do it again
282
  $active = self::is_power_up_active($power_up_slug);
283
  if ( ! $active )
284
  return TRUE;
@@ -292,7 +293,61 @@ class WPLeadIn {
292
  {
293
  exit;
294
  }
 
295
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
  }
297
  }
298
 
36
  else
37
  add_action('wp_enqueue_scripts', array($this, 'add_leadin_frontend_scripts'));
38
  }
39
+
40
+ //add_action( 'admin_notices', array($this, 'deactivate_leadin_notice') );
41
  }
42
 
43
  //=============================================
210
  LEADIN_PLUGIN_DIR . '/power-ups/contacts.php',
211
  LEADIN_PLUGIN_DIR . '/power-ups/subscribe-widget.php',
212
  LEADIN_PLUGIN_DIR . '/power-ups/mailchimp-connect.php',
213
+ LEADIN_PLUGIN_DIR . '/power-ups/constant-contact-connect.php'
 
214
  ));
215
 
216
  closedir( $dir );
243
  return array();
244
  }
245
 
246
+ public static function activate_power_up ( $power_up_slug, $exit = TRUE )
247
  {
248
  if ( ! strlen( $power_up_slug ) )
249
  return FALSE;
274
  }
275
  }
276
 
277
+ public static function deactivate_power_up ( $power_up_slug, $exit = TRUE )
278
  {
279
  if ( ! strlen( $power_up_slug ) )
280
  return FALSE;
281
 
282
+ // If it's already deactivated, then don't do it again
283
  $active = self::is_power_up_active($power_up_slug);
284
  if ( ! $active )
285
  return TRUE;
293
  {
294
  exit;
295
  }
296
+ }
297
 
298
+ /**
299
+ * Throws an error for when the premium version and the free version are activated in tandem
300
+ */
301
+ function deactivate_leadin_notice ()
302
+ {
303
+ ?>
304
+ <div id="message" class="update-nag">
305
+ <?php
306
+ _e(
307
+ '<p>' .
308
+ '<a style="font-size: 14px; float: right; color: #ccc; text-decoration: none; margin-top: -15px;" href="#">&#10006;</a>' .
309
+ '<b>Leadin Pro is now avaialble!</b>' .
310
+ '</p>' .
311
+ '<p>' .
312
+ 'Leadin Pro includes all the features you\'ve come to love from our plugin along with some powerful new ones too. <a href="#">See all the features</a>' .
313
+ '</p>' .
314
+ '<p>' .
315
+ 'The launch of Leadin Pro also means that we are no longer supporting the version of Leadin hosted by the WordPress Plugin Directory.' .
316
+ 'Read more about why we are making this change on <a href="http://leadin.com/the-move-to-pro">the Leadin blog</a>. ' .
317
+ '</p>' .
318
+ '<p>' .
319
+ 'If you run have any questions or concerns, please feel free to email us - <a href="mailto:support@leadin.com">support@leadin.com</a>' .
320
+ '</p>' .
321
+ '<p>' .
322
+ '<a class="button button-primary" href="http://leadin.com">Download Leadin Pro for Free</a> ' .
323
+ '</p>',
324
+ 'my-text-domain'
325
+ );
326
+ ?>
327
+ </div>
328
+ <?php
329
+ }
330
+
331
+ /* Display a notice that can be dismissed */
332
+
333
+ function example_admin_notice() {
334
+ global $current_user ;
335
+ $user_id = $current_user->ID;
336
+ /* Check that the user hasn't already clicked to ignore the message */
337
+ if ( ! get_user_meta($user_id, 'example_ignore_notice') ) {
338
+ echo '<div class="updated"><p>';
339
+ printf(__('This is an annoying nag message. Why do people make these? | <a href="%1$s">Hide Notice</a>'), '?example_nag_ignore=0');
340
+ echo "</p></div>";
341
+ }
342
+ }
343
+
344
+ function example_nag_ignore() {
345
+ global $current_user;
346
+ $user_id = $current_user->ID;
347
+ /* If user clicks to ignore the notice, add that to their user meta */
348
+ if ( isset($_GET['example_nag_ignore']) && '0' == $_GET['example_nag_ignore'] ) {
349
+ add_user_meta($user_id, 'example_ignore_notice', 'true', true);
350
+ }
351
  }
352
  }
353
 
inc/leadin-ajax-functions.php CHANGED
@@ -280,30 +280,35 @@ function leadin_insert_form_submission ()
280
  }
281
 
282
  // Apply the tag relationship to contacts for class rules
283
- $form_classes = explode(',', $form_selector_classes);
284
- foreach ( $form_classes as $class )
285
- {
286
- $q = $wpdb->prepare("SELECT tag_id, tag_synced_lists FROM $wpdb->li_tags WHERE tag_form_selectors LIKE '%%%s%%' AND tag_deleted = 0", '.' . $class);
287
- $tagged_lists = $wpdb->get_results($q);
288
 
289
- if ( count($tagged_lists) )
 
 
290
  {
291
- foreach ( $tagged_lists as $list )
292
- {
293
- $tag_added = leadin_apply_tag_to_contact($list->tag_id, $contact->hashkey, $submission_hash);
294
 
295
- $contact_type = 'tagged contact';
296
-
297
- if ( $tag_added && $list->tag_synced_lists )
298
  {
299
- foreach ( unserialize($list->tag_synced_lists) as $synced_list )
300
- {
301
- // e.g. leadin_constant_contact_connect_wp
302
- $leadin_esp_wp = 'leadin_' . $synced_list['esp'] . '_connect_wp';
303
- global ${$leadin_esp_wp};
304
 
305
- if ( ${$leadin_esp_wp}->activated )
306
- ${$leadin_esp_wp}->push_contact_to_list($synced_list['list_id'], $email, $first_name, $last_name, $phone);
 
 
 
 
 
 
 
 
 
 
 
307
  }
308
  }
309
  }
@@ -327,8 +332,6 @@ function leadin_insert_form_submission ()
327
  else if ( strstr($form_selector_id, 'commentform') )
328
  $contact_type = 'comment';
329
 
330
- leadin_track_plugin_activity("New lead", array("contact_type" => $contact_type));
331
-
332
  return $rows_updated;
333
  }
334
 
@@ -372,7 +375,6 @@ add_action('wp_ajax_nopriv_leadin_check_visitor_status', 'leadin_check_visitor_s
372
  */
373
  function leadin_subscribe_show ()
374
  {
375
- leadin_track_plugin_activity('widget shown');
376
  die();
377
  }
378
 
280
  }
281
 
282
  // Apply the tag relationship to contacts for class rules
283
+ if ( $form_selector_classes )
284
+ $form_classes = explode(',', $form_selector_classes);
 
 
 
285
 
286
+ if ( count($form_classes) )
287
+ {
288
+ foreach ( $form_classes as $class )
289
  {
290
+ $q = $wpdb->prepare("SELECT tag_id, tag_synced_lists FROM $wpdb->li_tags WHERE tag_form_selectors LIKE '%%%s%%' AND tag_deleted = 0", '.' . $class);
291
+ $tagged_lists = $wpdb->get_results($q);
 
292
 
293
+ if ( count($tagged_lists) )
294
+ {
295
+ foreach ( $tagged_lists as $list )
296
  {
297
+ $tag_added = leadin_apply_tag_to_contact($list->tag_id, $contact->hashkey, $submission_hash);
 
 
 
 
298
 
299
+ $contact_type = 'tagged contact';
300
+
301
+ if ( $tag_added && $list->tag_synced_lists )
302
+ {
303
+ foreach ( unserialize($list->tag_synced_lists) as $synced_list )
304
+ {
305
+ // e.g. leadin_constant_contact_connect_wp
306
+ $leadin_esp_wp = 'leadin_' . $synced_list['esp'] . '_connect_wp';
307
+ global ${$leadin_esp_wp};
308
+
309
+ if ( ${$leadin_esp_wp}->activated )
310
+ ${$leadin_esp_wp}->push_contact_to_list($synced_list['list_id'], $email, $first_name, $last_name, $phone);
311
+ }
312
  }
313
  }
314
  }
332
  else if ( strstr($form_selector_id, 'commentform') )
333
  $contact_type = 'comment';
334
 
 
 
335
  return $rows_updated;
336
  }
337
 
375
  */
376
  function leadin_subscribe_show ()
377
  {
 
378
  die();
379
  }
380
 
inc/leadin-functions.php CHANGED
@@ -107,70 +107,6 @@ function leadin_get_current_user ()
107
  return $leadin_user;
108
  }
109
 
110
- /**
111
- * Register Leadin user
112
- *
113
- * @return bool
114
- */
115
- function leadin_register_user ()
116
- {
117
- //@MP hack
118
- return FALSE;
119
-
120
- if ( ! function_exists('curl_init') )
121
- return false;
122
-
123
-
124
- $leadin_user = leadin_get_current_user();
125
-
126
- // @push mixpanel event for updated email
127
-
128
- $mp = new LI_Mixpanel(MIXPANEL_PROJECT_TOKEN);
129
- $mp->identify($leadin_user['user_id']);
130
- $mp->createAlias( $leadin_user['user_id'], $leadin_user['alias']);
131
- $mp->people->set( $leadin_user['user_id'], array(
132
- '$email' => $leadin_user['email'],
133
- '$wp-url' => $leadin_user['wp_url'],
134
- '$wp-version' => $leadin_user['wp_version'],
135
- '$li-version' => $leadin_user['li_version']
136
- ));
137
-
138
- $mp->people->setOnce( $leadin_user['user_id'], array(
139
- '$li-source' => LEADIN_SOURCE,
140
- '$created' => date('Y-m-d H:i:s')
141
- ));
142
-
143
- return true;
144
- }
145
-
146
- /**
147
- * Register Leadin user
148
- *
149
- * @return bool
150
- */
151
- function leadin_update_user ()
152
- {
153
- //@MP hack
154
- return FALSE;
155
-
156
- if ( ! function_exists('curl_init') )
157
- return false;
158
-
159
- $leadin_user = leadin_get_current_user();
160
-
161
- $mp = new LI_Mixpanel(MIXPANEL_PROJECT_TOKEN);
162
- $mp->people->set( $leadin_user['user_id'], array(
163
- "distinct_id" => md5(get_bloginfo('wpurl')),
164
- '$wp-url' => get_bloginfo('wpurl'),
165
- '$wp-version' => $leadin_user['wp_version'],
166
- '$li-version' => $leadin_user['li_version']
167
- ));
168
-
169
- leadin_track_plugin_activity("Upgraded Plugin");
170
-
171
- return true;
172
- }
173
-
174
  /**
175
  * Subscribe user to user updates in MailChimp
176
  *
@@ -197,125 +133,9 @@ function leadin_subscribe_user_updates ()
197
  "merge_vars" => array('EMAIL' => $leadin_user['email'], 'WEBSITE' => get_site_url() )
198
  ));
199
 
200
- leadin_track_plugin_activity('Onboarding Opted-into User Updates');
201
-
202
  return $contact_synced;
203
  }
204
 
205
- /**
206
- * Set Beta propertey on Leadin user in Mixpanel
207
- *
208
- * @return bool
209
- */
210
- function leadin_set_beta_tester_property ( $beta_tester )
211
- {
212
- //@MP hack
213
- return FALSE;
214
-
215
- if ( ! function_exists('curl_init') )
216
- return false;
217
-
218
-
219
- $leadin_user = leadin_get_current_user();
220
- $mp = new LI_Mixpanel(MIXPANEL_PROJECT_TOKEN);
221
- $mp->people->set( $leadin_user['user_id'], array(
222
- '$beta_tester' => $beta_tester
223
- ));
224
- }
225
-
226
- /**
227
- * Set the status property (activated, deactivated, bad url)
228
- *
229
- * @return bool
230
- */
231
- function leadin_set_install_status ( $li_status )
232
- {
233
- //@MP hack
234
- return FALSE;
235
-
236
- if ( ! function_exists('curl_init') )
237
- return false;
238
-
239
- $leadin_user = leadin_get_current_user();
240
-
241
- $properties = array(
242
- '$li-status' => $li_status
243
- );
244
-
245
- if ( $li_status == 'activated' )
246
- $properties['$last_activated'] = date('Y-m-d H:i:s');
247
- else
248
- $properties['$last_deactivated'] = date('Y-m-d H:i:s');
249
-
250
- $mp = new LI_Mixpanel(MIXPANEL_PROJECT_TOKEN);
251
- $mp->people->set( $leadin_user['user_id'], $properties);
252
- }
253
-
254
-
255
- /**
256
- * Send Mixpanel event when plugin is activated/deactivated
257
- *
258
- * @param bool
259
- *
260
- * @return bool
261
- */
262
- function leadin_track_plugin_registration_hook ( $activated )
263
- {
264
- //@MP hack
265
- return FALSE;
266
-
267
- if ( $activated )
268
- {
269
- leadin_register_user();
270
- leadin_track_plugin_activity("Activated Plugin");
271
- leadin_set_install_status('activated');
272
- }
273
- else
274
- {
275
- leadin_track_plugin_activity("Deactivated Plugin");
276
- leadin_set_install_status('deactivated');
277
- }
278
-
279
- return TRUE;
280
- }
281
-
282
- /**
283
- * Track plugin activity in MixPanel
284
- *
285
- * @param string
286
- *
287
- * @return array
288
- */
289
- function leadin_track_plugin_activity ( $activity_desc, $custom_properties = array() )
290
- {
291
- //@MP hack
292
- return FALSE;
293
-
294
- if ( ! function_exists('curl_init') )
295
- return false;
296
-
297
- $leadin_user = leadin_get_current_user();
298
-
299
- global $wp_version;
300
- global $current_user;
301
- get_currentuserinfo();
302
- $user_id = md5(get_bloginfo('wpurl'));
303
-
304
- $default_properties = array(
305
- "distinct_id" => $user_id,
306
- '$wp-url' => get_bloginfo('wpurl'),
307
- '$wp-version' => $wp_version,
308
- '$li-version' => LEADIN_PLUGIN_VERSION
309
- );
310
-
311
- $properties = array_merge((array)$default_properties, (array)$custom_properties);
312
-
313
- $mp = new LI_Mixpanel(MIXPANEL_PROJECT_TOKEN);
314
- $mp->track($activity_desc, $properties);
315
-
316
- return true;
317
- }
318
-
319
  /**
320
  * Logs a debug statement to /wp-content/debug.log
321
  *
107
  return $leadin_user;
108
  }
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  /**
111
  * Subscribe user to user updates in MailChimp
112
  *
133
  "merge_vars" => array('EMAIL' => $leadin_user['email'], 'WEBSITE' => get_site_url() )
134
  ));
135
 
 
 
136
  return $contact_synced;
137
  }
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  /**
140
  * Logs a debug statement to /wp-content/debug.log
141
  *
leadin.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Leadin
4
  Plugin URI: http://leadin.com
5
  Description: Leadin is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
6
- Version: 2.2.5
7
  Author: Andy Cook, Nelson Joyce
8
  Author URI: http://leadin.com
9
  License: GPL2
@@ -26,10 +26,7 @@ if ( !defined('LEADIN_DB_VERSION') )
26
  define('LEADIN_DB_VERSION', '2.2.4');
27
 
28
  if ( !defined('LEADIN_PLUGIN_VERSION') )
29
- define('LEADIN_PLUGIN_VERSION', '2.2.5');
30
-
31
- if ( !defined('MIXPANEL_PROJECT_TOKEN') )
32
- define('MIXPANEL_PROJECT_TOKEN', 'a9615503ec58a6bce2c646a58390eac1');
33
 
34
  if ( !defined('MC_KEY') )
35
  define('MC_KEY', '934aaed05049dde737d308be26167eef-us3');
@@ -47,14 +44,12 @@ require_once(LEADIN_PLUGIN_DIR . '/inc/class-emailer.php');
47
  require_once(LEADIN_PLUGIN_DIR . '/inc/class-leadin-updater.php');
48
  require_once(LEADIN_PLUGIN_DIR . '/admin/leadin-admin.php');
49
 
50
- require_once(LEADIN_PLUGIN_DIR . '/lib/mixpanel/LI_Mixpanel.php');
51
  require_once(LEADIN_PLUGIN_DIR . '/inc/class-leadin.php');
52
 
53
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/subscribe-widget.php');
54
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/contacts.php');
55
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/mailchimp-connect.php');
56
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/constant-contact-connect.php');
57
- require_once(LEADIN_PLUGIN_DIR . '/power-ups/beta-program.php');
58
 
59
  //=============================================
60
  // Hooks & Filters
@@ -69,45 +64,6 @@ register_deactivation_hook( __FILE__, 'deactivate_leadin');
69
  // Activate on newly created wpmu blog
70
  add_action('wpmu_new_blog', 'activate_leadin_on_new_blog', 10, 6);
71
 
72
- if ( isset($_GET['error']) && $_GET['error'] == 'true' )
73
- {
74
- if ( isset($_GET['plugin']) && $_GET['plugin'] == ( LEADIN_PLUGIN_SLUG != 'leadin' ? 'leadin/leadin.php' : 'leadin-premium/leadin-premium.php' ) )
75
- {
76
- if ( function_exists('activate_leadin') )
77
- {
78
- include_once(ABSPATH . 'wp-admin/includes/plugin.php');
79
- include_once(ABSPATH . 'wp-includes/pluggable.php');
80
-
81
- add_action( 'admin_notices', 'deactivate_leadin_notice' );
82
- }
83
- }
84
- }
85
-
86
- /**
87
- * Throws an error for when the premium version and the free version are activated in tandem
88
- */
89
- function deactivate_leadin_notice ()
90
- {
91
- ?>
92
- <div id="message" class="error">
93
- <?php
94
- _e(
95
- '<p>' .
96
- '<b>There was a slight error while activating Leadin Premium, but don\'t panic... there\'s an easy fix.</b>' .
97
- '</p>' .
98
- '<p>' .
99
- 'Leadin and Leadin Premium are like two rival siblings - they don\'t play nice together. ' .
100
- 'Deactivate <b>Leadin</b> and then try activating <b>Leadin Premium</b> again, and everything should start working fine.' .
101
- '</p>' .
102
- '<p>' .
103
- 'If you run into any issues and can\'t get Leadin Premium working, please email us for help - <a href="mailto:support@leadin.com">support@leadin.com</a>',
104
- 'my-text-domain'
105
- );
106
- ?>
107
- </div>
108
- <?php
109
- }
110
-
111
  /**
112
  * Activate the plugin
113
  */
@@ -131,7 +87,6 @@ function activate_leadin ( $network_wide )
131
  switch_to_blog($blog_id);
132
  add_leadin_defaults();
133
  $activated[] = $blog_id;
134
- //leadin_track_plugin_registration_hook(TRUE);
135
  }
136
 
137
  // Switch back to the current blog
@@ -140,12 +95,8 @@ function activate_leadin ( $network_wide )
140
  // Store the array for a later function
141
  update_site_option('leadin_activated', $activated);
142
  }
143
- else
144
- {
145
- //leadin_track_plugin_registration_hook(TRUE);
146
 
147
- add_leadin_defaults();
148
- }
149
  }
150
 
151
  /**
@@ -169,7 +120,6 @@ function add_leadin_defaults ( )
169
  'ignore_settings_popup' => 0,
170
  'data_recovered' => 1,
171
  'delete_flags_fixed' => 1,
172
- 'beta_tester' => 0,
173
  'converted_to_tags' => 1,
174
  'names_added_to_contacts' => 1
175
  );
@@ -193,8 +143,7 @@ function add_leadin_defaults ( )
193
  if ( !$leadin_active_power_ups )
194
  {
195
  $auto_activate = array(
196
- 'contacts',
197
- 'beta_program'
198
  );
199
 
200
  update_option('leadin_active_power_ups', serialize($auto_activate));
@@ -219,14 +168,11 @@ function deactivate_leadin ( $network_wide )
219
  foreach ( $blog_ids as $blog_id )
220
  {
221
  switch_to_blog($blog_id);
222
- //leadin_track_plugin_registration_hook(FALSE);
223
  }
224
 
225
  // Switch back to the current blog
226
  switch_to_blog($current_blog);
227
  }
228
- //else
229
- //leadin_track_plugin_registration_hook(FALSE);
230
  }
231
 
232
  function activate_leadin_on_new_blog ( $blog_id, $user_id, $domain, $path, $site_id, $meta )
3
  Plugin Name: Leadin
4
  Plugin URI: http://leadin.com
5
  Description: Leadin is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
6
+ Version: 2.2.6
7
  Author: Andy Cook, Nelson Joyce
8
  Author URI: http://leadin.com
9
  License: GPL2
26
  define('LEADIN_DB_VERSION', '2.2.4');
27
 
28
  if ( !defined('LEADIN_PLUGIN_VERSION') )
29
+ define('LEADIN_PLUGIN_VERSION', '2.2.6');
 
 
 
30
 
31
  if ( !defined('MC_KEY') )
32
  define('MC_KEY', '934aaed05049dde737d308be26167eef-us3');
44
  require_once(LEADIN_PLUGIN_DIR . '/inc/class-leadin-updater.php');
45
  require_once(LEADIN_PLUGIN_DIR . '/admin/leadin-admin.php');
46
 
 
47
  require_once(LEADIN_PLUGIN_DIR . '/inc/class-leadin.php');
48
 
49
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/subscribe-widget.php');
50
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/contacts.php');
51
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/mailchimp-connect.php');
52
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/constant-contact-connect.php');
 
53
 
54
  //=============================================
55
  // Hooks & Filters
64
  // Activate on newly created wpmu blog
65
  add_action('wpmu_new_blog', 'activate_leadin_on_new_blog', 10, 6);
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  /**
68
  * Activate the plugin
69
  */
87
  switch_to_blog($blog_id);
88
  add_leadin_defaults();
89
  $activated[] = $blog_id;
 
90
  }
91
 
92
  // Switch back to the current blog
95
  // Store the array for a later function
96
  update_site_option('leadin_activated', $activated);
97
  }
 
 
 
98
 
99
+ add_leadin_defaults();
 
100
  }
101
 
102
  /**
120
  'ignore_settings_popup' => 0,
121
  'data_recovered' => 1,
122
  'delete_flags_fixed' => 1,
 
123
  'converted_to_tags' => 1,
124
  'names_added_to_contacts' => 1
125
  );
143
  if ( !$leadin_active_power_ups )
144
  {
145
  $auto_activate = array(
146
+ 'contacts'
 
147
  );
148
 
149
  update_option('leadin_active_power_ups', serialize($auto_activate));
168
  foreach ( $blog_ids as $blog_id )
169
  {
170
  switch_to_blog($blog_id);
 
171
  }
172
 
173
  // Switch back to the current blog
174
  switch_to_blog($current_blog);
175
  }
 
 
176
  }
177
 
178
  function activate_leadin_on_new_blog ( $blog_id, $user_id, $domain, $path, $site_id, $meta )
lib/mixpanel/Base/LI_MixpanelBase.php DELETED
@@ -1,68 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * This a Base class which all Mixpanel classes extend from to provide some very basic
5
- * debugging and logging functionality. It also serves to persist $_options across the library.
6
- *
7
- */
8
-
9
-
10
-
11
- class LI_Base_MixpanelBase {
12
-
13
-
14
- /**
15
- * Default options that can be overridden via the $options constructor arg
16
- * @var array
17
- */
18
- private $_defaults = array(
19
- "max_batch_size" => 50, // the max batch size Mixpanel will accept is 50,
20
- "max_queue_size" => 1000, // the max num of items to hold in memory before flushing
21
- "debug" => false, // enable/disable debug mode
22
- "consumer" => "curl", // which consumer to use
23
- "host" => "api.mixpanel.com", // the host name for api calls
24
- "events_endpoint" => "/track", // host relative endpoint for events
25
- "people_endpoint" => "/engage", // host relative endpoint for people updates
26
- "use_ssl" => true, // use ssl when available
27
- "error_callback" => null // callback to use on consumption failures
28
- );
29
-
30
-
31
- /**
32
- * An array of options to be used by the Mixpanel library.
33
- * @var array
34
- */
35
- protected $_options = array();
36
-
37
-
38
- /**
39
- * Construct a new MixpanelBase object and merge custom options with defaults
40
- * @param array $options
41
- */
42
- public function __construct($options = array()) {
43
- $options = array_merge($this->_defaults, $options);
44
- $this->_options = $options;
45
- }
46
-
47
-
48
- /**
49
- * Log a message to PHP's error log
50
- * @param $msg
51
- */
52
- protected function _log($msg) {
53
- $arr = debug_backtrace();
54
- $class = $arr[0]['class'];
55
- $line = $arr[0]['line'];
56
- error_log ( "[ $class - line $line ] : " . $msg );
57
- }
58
-
59
-
60
- /**
61
- * Returns true if in debug mode, false if in production mode
62
- * @return bool
63
- */
64
- protected function _debug() {
65
- return array_key_exists("debug", $this->_options) && $this->_options["debug"] == true;
66
- }
67
-
68
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/mixpanel/ConsumerStrategies/LI_AbstractConsumer.php DELETED
@@ -1,58 +0,0 @@
1
- <?php
2
-
3
- require_once(dirname(__FILE__) . "/../Base/LI_MixpanelBase.php");
4
-
5
- /**
6
- * Provides some base methods for use by a Consumer implementation
7
- */
8
- abstract class LI_ConsumerStrategies_AbstractConsumer extends LI_Base_MixpanelBase {
9
-
10
- /**
11
- * Creates a new AbstractConsumer
12
- * @param array $options
13
- */
14
- function __construct($options = array()) {
15
-
16
- parent::__construct($options);
17
-
18
- if ($this->_debug()) {
19
- $this->_log("Instantiated new Consumer");
20
- }
21
-
22
- }
23
-
24
- /**
25
- * Encode an array to be persisted
26
- * @param array $params
27
- * @return string
28
- */
29
- protected function _encode($params) {
30
- return base64_encode(json_encode($params));
31
- }
32
-
33
- /**
34
- * Handles errors that occur in a consumer
35
- * @param $code
36
- * @param $msg
37
- */
38
- protected function _handleError($code, $msg) {
39
- if (isset($this->_options['error_callback'])) {
40
- $handler = $this->_options['error_callback'];
41
- call_user_func($handler, $code, $msg);
42
- }
43
-
44
- if ($this->_debug()) {
45
- $arr = debug_backtrace();
46
- $class = get_class($arr[0]['object']);
47
- $line = $arr[0]['line'];
48
- error_log ( "[ $class - line $line ] : " . print_r($msg, true) );
49
- }
50
- }
51
-
52
- /**
53
- * Persist a batch of messages in whatever way the implementer sees fit
54
- * @param array $batch an array of messages to consume
55
- * @return boolean success or fail
56
- */
57
- abstract function persist($batch);
58
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/mixpanel/ConsumerStrategies/LI_CurlConsumer.php DELETED
@@ -1,222 +0,0 @@
1
- <?php
2
-
3
- require_once(dirname(__FILE__) . "/LI_AbstractConsumer.php");
4
-
5
- /**
6
- * Consumes messages and sends them to a host/endpoint using cURL
7
- */
8
- class LI_ConsumerStrategies_CurlConsumer extends LI_ConsumerStrategies_AbstractConsumer {
9
-
10
- /**
11
- * @var string the host to connect to (e.g. api.mixpanel.com)
12
- */
13
- protected $_host;
14
-
15
-
16
- /**
17
- * @var string the host-relative endpoint to write to (e.g. /engage)
18
- */
19
- protected $_endpoint;
20
-
21
-
22
- /**
23
- * @var int connect_timeout The number of seconds to wait while trying to connect. Default is 5 seconds.
24
- */
25
- protected $_connect_timeout;
26
-
27
-
28
- /**
29
- * @var int timeout The maximum number of seconds to allow cURL call to execute. Default is 30 seconds.
30
- */
31
- protected $_timeout;
32
-
33
-
34
- /**
35
- * @var string the protocol to use for the cURL connection
36
- */
37
- protected $_protocol;
38
-
39
-
40
- /**
41
- * @var bool|null true to fork the cURL process (using exec) or false to use PHP's cURL extension. false by default
42
- */
43
- protected $_fork = null;
44
-
45
-
46
- /**
47
- * Creates a new LI_CurlConsumer and assigns properties from the $options array
48
- * @param array $options
49
- * @throws Exception
50
- */
51
- function __construct($options) {
52
- parent::__construct($options);
53
-
54
- $this->_host = $options['host'];
55
- $this->_endpoint = $options['endpoint'];
56
- $this->_connect_timeout = array_key_exists('connect_timeout', $options) ? $options['connect_timeout'] : 5;
57
- $this->_timeout = array_key_exists('timeout', $options) ? $options['timeout'] : 30;
58
- $this->_protocol = array_key_exists('use_ssl', $options) && $options['use_ssl'] == true ? "https" : "http";
59
- $this->_fork = array_key_exists('fork', $options) ? ($options['fork'] == true) : false;
60
-
61
- // ensure the environment is workable for the given settings
62
- /*if ($this->_fork == true) {
63
- $exists = function_exists('exec');
64
- if (!$exists) {
65
- throw new Exception('The "exec" function must exist to use the cURL consumer in "fork" mode. Try setting fork = false or use another consumer.');
66
- }
67
- $disabled = explode(', ', ini_get('disable_functions'));
68
- $enabled = !in_array('exec', $disabled);
69
- if (!$enabled) {
70
- throw new Exception('The "exec" function must be enabled to use the cURL consumer in "fork" mode. Try setting fork = false or use another consumer.');
71
- }
72
- } else {
73
- if (!function_exists('curl_init')) {
74
- throw new Exception('The cURL PHP extension is required to use the cURL consumer with fork = false. Try setting fork = true or use another consumer.');
75
- }
76
- }*/
77
- }
78
-
79
-
80
- /**
81
- * Write to the given host/endpoint using either a forked cURL process or using PHP's cURL extension
82
- * @param array $batch
83
- * @return bool
84
- */
85
- public function persist($batch) {
86
- if (count($batch) > 0) {
87
- $data = "data=" . $this->_encode($batch);
88
- $url = $this->_protocol . "://" . $this->_host . $this->_endpoint;
89
- if ($this->_fork) {
90
- return $this->_execute_forked($url, $data);
91
- } else {
92
- return $this->_execute($url, $data);
93
- }
94
- } else {
95
- return true;
96
- }
97
- }
98
-
99
-
100
- /**
101
- * Write using the cURL php extension
102
- * @param $url
103
- * @param $data
104
- * @return bool
105
- */
106
- protected function _execute($url, $data) {
107
- if ($this->_debug()) {
108
- $this->_log("Making blocking cURL call to $url");
109
- }
110
-
111
- $ch = curl_init();
112
- curl_setopt($ch, CURLOPT_URL, $url);
113
- curl_setopt($ch, CURLOPT_HEADER, 0);
114
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->_connect_timeout);
115
- curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeout);
116
- curl_setopt($ch, CURLOPT_POST, 1);
117
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
118
- curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
119
- $response = curl_exec($ch);
120
- if (false === $response) {
121
- $curl_error = curl_error($ch);
122
- $curl_errno = curl_errno($ch);
123
- curl_close($ch);
124
- $this->_handleError($curl_errno, $curl_error);
125
- return false;
126
- } else {
127
- curl_close($ch);
128
- if (trim($response) == "1") {
129
- return true;
130
- } else {
131
- $this->_handleError(0, $response);
132
- return false;
133
- }
134
- }
135
- }
136
-
137
-
138
- /**
139
- * Write using a forked cURL process
140
- * @param $url
141
- * @param $data
142
- * @return bool
143
- */
144
- protected function _execute_forked($url, $data) {
145
-
146
- if ($this->_debug()) {
147
- $this->_log("Making forked cURL call to $url");
148
- }
149
-
150
- $exec = 'curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d ' . $data . ' "' . $url . '"';
151
-
152
- if(!$this->_debug()) {
153
- $exec .= " >/dev/null 2>&1 &";
154
- }
155
-
156
- exec($exec, $output, $return_var);
157
-
158
- if ($return_var != 0) {
159
- $this->_handleError($return_var, $output);
160
- }
161
-
162
- return $return_var == 0;
163
- }
164
-
165
- /**
166
- * @return int
167
- */
168
- public function getConnectTimeout()
169
- {
170
- return $this->_connect_timeout;
171
- }
172
-
173
- /**
174
- * @return string
175
- */
176
- public function getEndpoint()
177
- {
178
- return $this->_endpoint;
179
- }
180
-
181
- /**
182
- * @return bool|null
183
- */
184
- public function getFork()
185
- {
186
- return $this->_fork;
187
- }
188
-
189
- /**
190
- * @return string
191
- */
192
- public function getHost()
193
- {
194
- return $this->_host;
195
- }
196
-
197
- /**
198
- * @return array
199
- */
200
- public function getOptions()
201
- {
202
- return $this->_options;
203
- }
204
-
205
- /**
206
- * @return string
207
- */
208
- public function getProtocol()
209
- {
210
- return $this->_protocol;
211
- }
212
-
213
- /**
214
- * @return int
215
- */
216
- public function getTimeout()
217
- {
218
- return $this->_timeout;
219
- }
220
-
221
-
222
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/mixpanel/ConsumerStrategies/LI_FileConsumer.php DELETED
@@ -1,39 +0,0 @@
1
- <?php
2
-
3
- require_once(dirname(__FILE__) . "/LI_AbstractConsumer.php");
4
- /**
5
- * Consumes messages and writes them to a file
6
- */
7
- class ConsumerStrategies_LI_FileConsumer extends LI_ConsumerStrategies_AbstractConsumer {
8
-
9
- /**
10
- * @var string path to a file that we want to write the messages to
11
- */
12
- private $_file;
13
-
14
-
15
- /**
16
- * Creates a new LI_FileConsumer and assigns properties from the $options array
17
- * @param array $options
18
- */
19
- function __construct($options) {
20
- parent::__construct($options);
21
-
22
- // what file to write to?
23
- $this->_file = array_key_exists("file", $options) ? $options['file'] : dirname(__FILE__)."/../../messages.txt";
24
- }
25
-
26
-
27
- /**
28
- * Append $batch to a file
29
- * @param array $batch
30
- * @return bool
31
- */
32
- public function persist($batch) {
33
- if (count($batch) > 0) {
34
- return file_put_contents($this->_file, json_encode($batch)."\n", FILE_APPEND | LOCK_EX) !== false;
35
- } else {
36
- return true;
37
- }
38
- }
39
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/mixpanel/ConsumerStrategies/LI_SocketConsumer.php DELETED
@@ -1,309 +0,0 @@
1
- <?php
2
- /**
3
- * Portions of this class were borrowed from
4
- * https://github.com/segmentio/analytics-php/blob/master/lib/Analytics/Consumer/Socket.php.
5
- * Thanks for the work!
6
- *
7
- * WWWWWW||WWWWWW
8
- * W W W||W W W
9
- * ||
10
- * ( OO )__________
11
- * / | \
12
- * /o o| MIT \
13
- * \___/||_||__||_|| *
14
- * || || || ||
15
- * _||_|| _||_||
16
- * (__|__|(__|__|
17
- * (The MIT License)
18
- *
19
- * Copyright (c) 2013 Segment.io Inc. friends@segment.io
20
- *
21
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
22
- * documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the
23
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
24
- * permit persons to whom the Software is furnished to do so, subject to the following conditions:
25
- *
26
- * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
27
- * Software.
28
- *
29
- * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
30
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
31
- * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
32
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33
- */
34
-
35
- require_once(dirname(__FILE__) . "/LI_AbstractConsumer.php");
36
-
37
- /**
38
- * Consumes messages and writes them to host/endpoint using a persistent socket
39
- */
40
- class LI_ConsumerStrategies_SocketConsumer extends LI_ConsumerStrategies_AbstractConsumer {
41
-
42
- /**
43
- * @var string the host to connect to (e.g. api.mixpanel.com)
44
- */
45
- private $_host;
46
-
47
-
48
- /**
49
- * @var string the host-relative endpoint to write to (e.g. /engage)
50
- */
51
- private $_endpoint;
52
-
53
-
54
- /**
55
- * @var int connect_timeout the socket connection timeout in seconds
56
- */
57
- private $_connect_timeout;
58
-
59
-
60
- /**
61
- * @var string the protocol to use for the socket connection
62
- */
63
- private $_protocol;
64
-
65
-
66
- /**
67
- * @var resource holds the socket resource
68
- */
69
- private $_socket;
70
-
71
- /**
72
- * @var bool whether or not to wait for a response
73
- */
74
- private $_async;
75
-
76
-
77
- /**
78
- * Creates a new SocketConsumer and assigns properties from the $options array
79
- * @param array $options
80
- */
81
- public function __construct($options = array()) {
82
- parent::__construct($options);
83
-
84
-
85
- $this->_host = $options['host'];
86
- $this->_endpoint = $options['endpoint'];
87
- $this->_connect_timeout = array_key_exists('connect_timeout', $options) ? $options['connect_timeout'] : 5;
88
- $this->_async = array_key_exists('async', $options) && $options['async'] === false ? false : true;
89
-
90
- if (array_key_exists('use_ssl', $options) && $options['use_ssl'] == true) {
91
- $this->_protocol = "ssl";
92
- $this->_port = 443;
93
- } else {
94
- $this->_protocol = "tcp";
95
- $this->_port = 80;
96
- }
97
- }
98
-
99
-
100
- /**
101
- * Write using a persistent socket connection.
102
- * @param array $batch
103
- * @return bool
104
- */
105
- public function persist($batch) {
106
-
107
- $socket = $this->_getSocket();
108
- if (!is_resource($socket)) {
109
- return false;
110
- }
111
-
112
- $data = "data=".$this->_encode($batch);
113
-
114
- $body = "";
115
- $body.= "POST ".$this->_endpoint." HTTP/1.1\r\n";
116
- $body.= "Host: " . $this->_host . "\r\n";
117
- $body.= "Content-Type: application/x-www-form-urlencoded\r\n";
118
- $body.= "Accept: application/json\r\n";
119
- $body.= "Content-length: " . strlen($data) . "\r\n";
120
- $body.= "\r\n";
121
- $body.= $data;
122
-
123
- return $this->_write($socket, $body);
124
- }
125
-
126
-
127
- /**
128
- * Return cached socket if open or create a new persistent socket
129
- * @return bool|resource
130
- */
131
- private function _getSocket() {
132
- if(is_resource($this->_socket)) {
133
-
134
- if ($this->_debug()) {
135
- $this->_log("Using existing socket");
136
- }
137
-
138
- return $this->_socket;
139
- } else {
140
-
141
- if ($this->_debug()) {
142
- $this->_log("Creating new socket at ".time());
143
- }
144
-
145
- return $this->_createSocket();
146
- }
147
- }
148
-
149
- /**
150
- * Attempt to open a new socket connection, cache it, and return the resource
151
- * @param bool $retry
152
- * @return bool|resource
153
- */
154
- private function _createSocket($retry = true) {
155
- try {
156
- $socket = pfsockopen($this->_protocol . "://" . $this->_host, $this->_port, $err_no, $err_msg, $this->_connect_timeout);
157
-
158
- if ($this->_debug()) {
159
- $this->_log("Opening socket connection to " . $this->_protocol . "://" . $this->_host . ":" . $this->_port);
160
- }
161
-
162
- if ($err_no != 0) {
163
- $this->_handleError($err_no, $err_msg);
164
- return $retry == true ? $this->_createSocket(false) : false;
165
- } else {
166
- // cache the socket
167
- $this->_socket = $socket;
168
- return $socket;
169
- }
170
-
171
- } catch (Exception $e) {
172
- $this->_handleError($e->getCode(), $e->getMessage());
173
- return $retry == true ? $this->_createSocket(false) : false;
174
- }
175
- }
176
-
177
- /**
178
- * Attempt to close and dereference a socket resource
179
- */
180
- private function _destroySocket() {
181
- $socket = $this->_socket;
182
- $this->_socket = null;
183
- fclose($socket);
184
- }
185
-
186
-
187
- /**
188
- * Write $data through the given $socket
189
- * @param $socket
190
- * @param $data
191
- * @param bool $retry
192
- * @return bool
193
- */
194
- private function _write($socket, $data, $retry = true) {
195
-
196
- $bytes_sent = 0;
197
- $bytes_total = strlen($data);
198
- $socket_closed = false;
199
- $success = true;
200
- $max_bytes_per_write = 8192;
201
-
202
- // if we have no data to write just return true
203
- if ($bytes_total == 0) {
204
- return true;
205
- }
206
-
207
- // try to write the data
208
- while (!$socket_closed && $bytes_sent < $bytes_total) {
209
-
210
- try {
211
- $bytes = fwrite($socket, $data, $max_bytes_per_write);
212
-
213
- if ($this->_debug()) {
214
- $this->_log("Socket wrote ".$bytes." bytes");
215
- }
216
-
217
- // if we actually wrote data, then remove the written portion from $data left to write
218
- if ($bytes > 0) {
219
- $data = substr($data, $max_bytes_per_write);
220
- }
221
-
222
- } catch (Exception $e) {
223
- $this->_handleError($e->getCode(), $e->getMessage());
224
- $socket_closed = true;
225
- }
226
-
227
- if (isset($bytes) && $bytes) {
228
- $bytes_sent += $bytes;
229
- } else {
230
- $socket_closed = true;
231
- }
232
- }
233
-
234
- // create a new socket if the current one is closed and retry the message
235
- if ($socket_closed) {
236
-
237
- $this->_destroySocket();
238
-
239
- if ($retry) {
240
- if ($this->_debug()) {
241
- $this->_log("Retrying socket write...");
242
- }
243
- $socket = $this->_getSocket();
244
- if ($socket) return $this->_write($socket, $data, false);
245
- }
246
-
247
- return false;
248
- }
249
-
250
-
251
- // only wait for the response in debug mode or if we explicitly want to be synchronous
252
- if ($this->_debug() || !$this->_async) {
253
- $res = $this->handleResponse(fread($socket, 2048));
254
- if ($res["status"] != "200") {
255
- $this->_handleError($res["status"], $res["body"]);
256
- $success = false;
257
- }
258
- }
259
-
260
- return $success;
261
- }
262
-
263
-
264
- /**
265
- * Parse the response from a socket write (only used for debugging)
266
- * @param $response
267
- * @return array
268
- */
269
- private function handleResponse($response) {
270
-
271
- $lines = explode("\n", $response);
272
-
273
- // extract headers
274
- $headers = array();
275
- foreach($lines as $line) {
276
- $kvsplit = explode(":", $line);
277
- if (count($kvsplit) == 2) {
278
- $header = $kvsplit[0];
279
- $value = $kvsplit[1];
280
- $headers[$header] = trim($value);
281
- }
282
-
283
- }
284
-
285
- // extract status
286
- $line_one_exploded = explode(" ", $lines[0]);
287
- $status = $line_one_exploded[1];
288
-
289
- // extract body
290
- $body = $lines[count($lines) - 1];
291
-
292
- // if the connection has been closed lets kill the socket
293
- if ($headers['Connection'] == "close") {
294
- $this->_destroySocket();
295
- if ($this->_debug()) {
296
- $this->_log("Server told us connection closed so lets destroy the socket so it'll reconnect on next call");
297
- }
298
- }
299
-
300
- $ret = array(
301
- "status" => $status,
302
- "body" => $body,
303
- );
304
-
305
- return $ret;
306
- }
307
-
308
-
309
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/mixpanel/LI_Mixpanel.php DELETED
@@ -1,305 +0,0 @@
1
- <?php
2
-
3
- require_once(dirname(__FILE__) . "/Base/LI_MixpanelBase.php");
4
- require_once(dirname(__FILE__) . "/Producers/LI_MixpanelPeople.php");
5
- require_once(dirname(__FILE__) . "/Producers/LI_MixpanelEvents.php");
6
-
7
- /**
8
- * This is the main class for the Mixpanel PHP Library which provides all of the methods you need to track events and
9
- * create/update profiles.
10
- *
11
- * Architecture
12
- * -------------
13
- *
14
- * This library is built such that all messages are buffered in an in-memory "queue"
15
- * The queue will be automatically flushed at the end of every request. Alternatively, you can call "flush()" manually
16
- * at any time. Flushed messages will be passed to a Consumer's "persist" method. The library comes with a handful of
17
- * Consumers. The "LI_CurlConsumer" is used by default which will send the messages to Mixpanel using forked cURL processes.
18
- * You can implement your own custom Consumer to customize how a message is sent to Mixpanel. This can be useful when
19
- * you want to put messages onto a distributed queue (such as ActiveMQ or Kestrel) instead of writing to Mixpanel in
20
- * the user thread.
21
- *
22
- * Options
23
- * -------------
24
- *
25
- * <table width="100%" cellpadding="5">
26
- * <tr>
27
- * <th>Option</th>
28
- * <th>Description</th>
29
- * <th>Default</th>
30
- * </tr>
31
- * <tr>
32
- * <td>max_queue_size</td>
33
- * <td>The maximum number of items to buffer in memory before flushing</td>
34
- * <td>1000</td>
35
- * </tr>
36
- * <tr>
37
- * <td>debug</td>
38
- * <td>Enable/disable debug mode</td>
39
- * <td>false</td>
40
- * </tr>
41
- * <tr>
42
- * <td>consumer</td>
43
- * <td>The consumer to use for writing messages</td>
44
- * <td>curl</td>
45
- * </tr>
46
- * <tr>
47
- * <td>consumers</td>
48
- * <td>An array of custom consumers in the format array(consumer_key => class_name)</td>
49
- * <td>null</td>
50
- * </tr>
51
- * <tr>
52
- * <td>host</td>
53
- * <td>The host name for api calls (used by some consumers)</td>
54
- * <td>api.mixpanel.com</td>
55
- * </tr>
56
- * <tr>
57
- * <td>events_endpoint</td>
58
- * <td>The endpoint for tracking events (relative to the host)</td>
59
- * <td>/events</td>
60
- * </tr>
61
- * <tr>
62
- * <td>people_endpoint</td>
63
- * <td>The endpoint for making people updates (relative to the host)</td>
64
- * <td>/engage</td>
65
- * </tr>
66
- * <tr>
67
- * <td>use_ssl</td>
68
- * <td>Tell the consumer whether or not to use ssl (when available)</td>
69
- * <td>true</td>
70
- * </tr>
71
- * <tr>
72
- * <td>error_callback</td>
73
- * <td>The name of a function to be called on consumption failures</td>
74
- * <td>null</td>
75
- * </tr>
76
- * <tr>
77
- * <td>connect_timeout</td>
78
- * <td>In both the SocketConsumer and LI_CurlConsumer, this is used for the connection timeout (i.e. How long it has take to actually make a connection).
79
- * <td>5</td>
80
- * </tr>
81
- * <tr>
82
- * <td>timeout</td>
83
- * <td>In the LI_CurlConsumer (non-forked), it is used to determine how long the cURL call has to execute.
84
- * <td>30</td>
85
- * </tr>
86
- * </table>
87
- *
88
- * Example: Tracking an Event
89
- * -------------
90
- *
91
- * $mp = Mixpanel::getInstance("MY_TOKEN");
92
- *
93
- * $mp->track("My Event");
94
- *
95
- * Example: Setting Profile Properties
96
- * -------------
97
- *
98
- * $mp = Mixpanel::getInstance("MY_TOKEN", array("use_ssl" => false));
99
- *
100
- * $mp->people->set(12345, array(
101
- * '$first_name' => "John",
102
- * '$last_name' => "Doe",
103
- * '$email' => "john.doe@example.com",
104
- * '$phone' => "5555555555",
105
- * 'Favorite Color' => "red"
106
- * ));
107
- *
108
- */
109
- class LI_Mixpanel extends LI_Base_MixpanelBase {
110
-
111
-
112
- /**
113
- * An instance of the MixpanelPeople class (used to create/update profiles)
114
- * @var MixpanelPeople
115
- */
116
- public $people;
117
-
118
-
119
- /**
120
- * An instance of the MixpanelEvents class
121
- * @var Producers_MixpanelEvents
122
- */
123
- private $_events;
124
-
125
-
126
- /**
127
- * An instance of the Mixpanel class (for singleton use)
128
- * @var Mixpanel
129
- */
130
- public $instance;
131
-
132
-
133
- /**
134
- * Instantiates a new Mixpanel instance.
135
- * @param $token
136
- * @param array $options
137
- */
138
- public function __construct($token, $options = array()) {
139
- parent::__construct($options);
140
- $this->people = new LI_Producers_MixpanelPeople($token, $options);
141
- $this->_events = new LI_Producers_MixpanelEvents($token, $options);
142
- }
143
-
144
-
145
- /**
146
- * Returns a singleton instance of Mixpanel
147
- * @param $token
148
- * @param array $options
149
- * @return Mixpanel
150
- */
151
- public static function getInstance($token, $options = array()) {
152
-
153
-
154
-
155
-
156
- $this->instance = new LI_Mixpanel($token, $options);
157
-
158
-
159
- }
160
-
161
-
162
- /**
163
- * Add an array representing a message to be sent to Mixpanel to the in-memory queue.
164
- * @param array $message
165
- */
166
- public function enqueue($message = array()) {
167
- $this->_events->enqueue($message);
168
- }
169
-
170
-
171
- /**
172
- * Add an array representing a list of messages to be sent to Mixpanel to a queue.
173
- * @param array $messages
174
- */
175
- public function enqueueAll($messages = array()) {
176
- $this->_events->enqueueAll($messages);
177
- }
178
-
179
-
180
- /**
181
- * Flush the events queue
182
- * @param int $desired_batch_size
183
- */
184
- public function flush($desired_batch_size = 50) {
185
- $this->_events->flush($desired_batch_size);
186
- }
187
-
188
-
189
- /**
190
- * Empty the events queue
191
- */
192
- public function reset() {
193
- $this->_events->reset();
194
- }
195
-
196
-
197
- /**
198
- * Identify the user you want to associate to tracked events
199
- * @param string|int $user_id
200
- */
201
- public function identify($user_id) {
202
- $this->_events->identify($user_id);
203
- }
204
-
205
- /**
206
- * Track an event defined by $event associated with metadata defined by $properties
207
- * @param string $event
208
- * @param array $properties
209
- */
210
- public function track($event, $properties = array()) {
211
- $this->_events->track($event, $properties);
212
- }
213
-
214
-
215
- /**
216
- * Register a property to be sent with every event.
217
- *
218
- * If the property has already been registered, it will be
219
- * overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class instance.
220
- * @param string $property
221
- * @param mixed $value
222
- */
223
- public function register($property, $value) {
224
- $this->_events->register($property, $value);
225
- }
226
-
227
-
228
- /**
229
- * Register multiple properties to be sent with every event.
230
- *
231
- * If any of the properties have already been registered,
232
- * they will be overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class
233
- * instance.
234
- * @param array $props_and_vals
235
- */
236
- public function registerAll($props_and_vals = array()) {
237
- $this->_events->registerAll($props_and_vals);
238
- }
239
-
240
-
241
- /**
242
- * Register a property to be sent with every event.
243
- *
244
- * If the property has already been registered, it will NOT be
245
- * overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class instance.
246
- * @param $property
247
- * @param $value
248
- */
249
- public function registerOnce($property, $value) {
250
- $this->_events->registerOnce($property, $value);
251
- }
252
-
253
-
254
- /**
255
- * Register multiple properties to be sent with every event.
256
- *
257
- * If any of the properties have already been registered,
258
- * they will NOT be overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class
259
- * instance.
260
- * @param array $props_and_vals
261
- */
262
- public function registerAllOnce($props_and_vals = array()) {
263
- $this->_events->registerAllOnce($props_and_vals);
264
- }
265
-
266
-
267
- /**
268
- * Un-register an property to be sent with every event.
269
- * @param string $property
270
- */
271
- public function unregister($property) {
272
- $this->_events->unregister($property);
273
- }
274
-
275
-
276
- /**
277
- * Un-register a list of properties to be sent with every event.
278
- * @param array $properties
279
- */
280
- public function unregisterAll($properties) {
281
- $this->_events->unregisterAll($properties);
282
- }
283
-
284
-
285
- /**
286
- * Get a property that is set to be sent with every event
287
- * @param string $property
288
- * @return mixed
289
- */
290
- public function getProperty($property)
291
- {
292
- return $this->_events->getProperty($property);
293
- }
294
-
295
-
296
- /**
297
- * Alias an existing id with a different unique id. This is helpful when you want to associate a generated id
298
- * (such as a session id) to a user id or username.
299
- * @param string|int $original_id
300
- * @param string|int $new_id
301
- */
302
- public function createAlias($original_id, $new_id) {
303
- $this->_events->createAlias($original_id, $new_id);
304
- }
305
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/mixpanel/Producers/LI_MixpanelBaseProducer.php DELETED
@@ -1,230 +0,0 @@
1
- <?php
2
-
3
- require_once(dirname(__FILE__) . "/../Base/LI_MixpanelBase.php");
4
- require_once(dirname(__FILE__) . "/../ConsumerStrategies/LI_FileConsumer.php");
5
- require_once(dirname(__FILE__) . "/../ConsumerStrategies/LI_CurlConsumer.php");
6
- require_once(dirname(__FILE__) . "/../ConsumerStrategies/LI_SocketConsumer.php");
7
-
8
- if (!function_exists('json_encode')) {
9
- throw new Exception('The JSON PHP extension is required.');
10
- }
11
-
12
- /**
13
- * Provides some base methods for use by a message Producer
14
- */
15
- abstract class LI_Producers_MixpanelBaseProducer extends LI_Base_MixpanelBase {
16
-
17
-
18
- /**
19
- * @var string a token associated to a Mixpanel project
20
- */
21
- protected $_token;
22
-
23
-
24
- /**
25
- * @var array a queue to hold messages in memory before flushing in batches
26
- */
27
- private $_queue = array();
28
-
29
-
30
- /**
31
- * @var LI_ConsumerStrategies_AbstractConsumer the consumer to use when flushing messages
32
- */
33
- private $_consumer = null;
34
-
35
-
36
- /**
37
- * @var array The list of available consumers
38
- */
39
- private $_consumers = array(
40
- "file" => "LI_ConsumerStrategies_FileConsumer",
41
- "curl" => "LI_ConsumerStrategies_CurlConsumer",
42
- "socket" => "LI_ConsumerStrategies_SocketConsumer"
43
- );
44
-
45
-
46
- /**
47
- * If the queue reaches this size we'll auto-flush to prevent out of memory errors
48
- * @var int
49
- */
50
- protected $_max_queue_size = 1000;
51
-
52
-
53
- /**
54
- * Creates a new MixpanelBaseProducer, assings Mixpanel project token, registers custom Consumers, and instantiates
55
- * the desired consumer
56
- * @param $token
57
- * @param array $options
58
- */
59
- public function __construct($token, $options = array()) {
60
-
61
- parent::__construct($options);
62
-
63
- // register any customer consumers
64
- if (array_key_exists("consumers", $options)) {
65
- $this->_consumers = array_merge($this->_consumers, $options['consumers']);
66
- }
67
-
68
- // set max queue size
69
- if (array_key_exists("max_queue_size", $options)) {
70
- $this->_max_queue_size = $options['max_queue_size'];
71
- }
72
-
73
- // associate token
74
- $this->_token = $token;
75
-
76
- if ($this->_debug()) {
77
- $this->_log("Using token: ".$this->_token);
78
- }
79
-
80
- // instantiate the chosen consumer
81
- $this->_consumer = $this->_getConsumer();
82
-
83
- }
84
-
85
-
86
- /**
87
- * Flush the queue when we destruct the client with retries
88
- */
89
- public function __destruct() {
90
- $attempts = 0;
91
- $max_attempts = 10;
92
- $success = false;
93
- while (!$success && $attempts < $max_attempts) {
94
- if ($this->_debug()) {
95
- $this->_log("destruct flush attempt #".($attempts+1));
96
- }
97
- $success = $this->flush();
98
- $attempts++;
99
- }
100
- }
101
-
102
-
103
- /**
104
- * Iterate the queue and write in batches using the instantiated Consumer Strategy
105
- * @param int $desired_batch_size
106
- * @return bool whether or not the flush was successful
107
- */
108
- public function flush($desired_batch_size = 50) {
109
- $queue_size = count($this->_queue);
110
- $succeeded = true;
111
- if ($this->_debug()) {
112
- $this->_log("Flush called - queue size: ".$queue_size);
113
- }
114
-
115
- while($queue_size > 0 && $succeeded) {
116
- $batch_size = min(array($queue_size, $desired_batch_size, $this->_options['max_batch_size']));
117
- $batch = array_splice($this->_queue, 0, $batch_size);
118
- $succeeded = $this->_persist($batch);
119
-
120
- if (!$succeeded) {
121
- if ($this->_debug()) {
122
- $this->_log("Batch consumption failed!");
123
- }
124
- $this->_queue = array_merge($batch, $this->_queue);
125
-
126
- if ($this->_debug()) {
127
- $this->_log("added batch back to queue, queue size is now $queue_size");
128
- }
129
- }
130
-
131
- $queue_size = count($this->_queue);
132
-
133
- if ($this->_debug()) {
134
- $this->_log("Batch of $batch_size consumed, queue size is now $queue_size");
135
- }
136
- }
137
- return $succeeded;
138
- }
139
-
140
-
141
- /**
142
- * Empties the queue without persisting any of the messages
143
- */
144
- public function reset() {
145
- $this->_queue = array();
146
- }
147
-
148
-
149
- /**
150
- * Returns the in-memory queue
151
- * @return array
152
- */
153
- public function getQueue() {
154
- return $this->_queue;
155
- }
156
-
157
- /**
158
- * Returns the current Mixpanel project token
159
- * @return string
160
- */
161
- public function getToken() {
162
- return $this->_token;
163
- }
164
-
165
-
166
- /**
167
- * Given a strategy type, return a new PersistenceStrategy object
168
- * @return LI_ConsumerStrategies_AbstractConsumer
169
- */
170
- protected function _getConsumer() {
171
- $key = $this->_options['consumer'];
172
- $Strategy = $this->_consumers[$key];
173
- if ($this->_debug()) {
174
- $this->_log("Using consumer: " . $key . " -> " . $Strategy);
175
- }
176
- $this->_options['endpoint'] = $this->_getEndpoint();
177
-
178
- return new $Strategy($this->_options);
179
- }
180
-
181
-
182
- /**
183
- * Add an array representing a message to be sent to Mixpanel to a queue.
184
- * @param array $message
185
- */
186
- public function enqueue($message = array()) {
187
- array_push($this->_queue, $message);
188
-
189
- // force a flush if we've reached our threshold
190
- if (count($this->_queue) > $this->_max_queue_size) {
191
- $this->flush();
192
- }
193
-
194
- if ($this->_debug()) {
195
- $this->_log("Queued message: ".json_encode($message));
196
- }
197
- }
198
-
199
-
200
- /**
201
- * Add an array representing a list of messages to be sent to Mixpanel to a queue.
202
- * @param array $messages
203
- */
204
- public function enqueueAll($messages = array()) {
205
- foreach($messages as $message) {
206
- $this->enqueue($message);
207
- }
208
-
209
- }
210
-
211
-
212
- /**
213
- * Given an array of messages, persist it with the instantiated Persistence Strategy
214
- * @param $message
215
- * @return mixed
216
- */
217
- protected function _persist($message) {
218
- return $this->_consumer->persist($message);
219
- }
220
-
221
-
222
-
223
-
224
- /**
225
- * Return the endpoint that should be used by a consumer that consumes messages produced by this producer.
226
- * @return string
227
- */
228
- abstract function _getEndpoint();
229
-
230
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/mixpanel/Producers/LI_MixpanelEvents.php DELETED
@@ -1,165 +0,0 @@
1
- <?php
2
-
3
- require_once(dirname(__FILE__) . "/LI_MixpanelBaseProducer.php");
4
- require_once(dirname(__FILE__) . "/LI_MixpanelPeople.php");
5
- require_once(dirname(__FILE__) . "/../ConsumerStrategies/LI_CurlConsumer.php");
6
-
7
- /**
8
- * Provides an API to track events on Mixpanel
9
- */
10
- class LI_Producers_MixpanelEvents extends LI_Producers_MixpanelBaseProducer {
11
-
12
- /**
13
- * An array of properties to attach to every tracked event
14
- * @var array
15
- */
16
- private $_super_properties = array("mp_lib" => "php");
17
-
18
-
19
- /**
20
- * Track an event defined by $event associated with metadata defined by $properties
21
- * @param string $event
22
- * @param array $properties
23
- */
24
- public function track($event, $properties = array()) {
25
-
26
- // if no token is passed in, use current token
27
- if (!array_key_exists("token", $properties)) $properties['token'] = $this->_token;
28
-
29
- // if no time is passed in, use the current time
30
- if (!array_key_exists('time', $properties)) $properties['time'] = time();
31
-
32
- $params['event'] = $event;
33
- $params['properties'] = array_merge($this->_super_properties, $properties);
34
-
35
- $this->enqueue($params);
36
- }
37
-
38
-
39
- /**
40
- * Register a property to be sent with every event. If the property has already been registered, it will be
41
- * overwritten.
42
- * @param string $property
43
- * @param mixed $value
44
- */
45
- public function register($property, $value) {
46
- $this->_super_properties[$property] = $value;
47
- }
48
-
49
-
50
- /**
51
- * Register multiple properties to be sent with every event. If any of the properties have already been registered,
52
- * they will be overwritten.
53
- * @param array $props_and_vals
54
- */
55
- public function registerAll($props_and_vals = array()) {
56
- foreach($props_and_vals as $property => $value) {
57
- $this->register($property, $value);
58
- }
59
- }
60
-
61
-
62
- /**
63
- * Register a property to be sent with every event. If the property has already been registered, it will NOT be
64
- * overwritten.
65
- * @param $property
66
- * @param $value
67
- */
68
- public function registerOnce($property, $value) {
69
- if (!isset($this->_super_properties[$property])) {
70
- $this->register($property, $value);
71
- }
72
- }
73
-
74
-
75
- /**
76
- * Register multiple properties to be sent with every event. If any of the properties have already been registered,
77
- * they will NOT be overwritten.
78
- * @param array $props_and_vals
79
- */
80
- public function registerAllOnce($props_and_vals = array()) {
81
- foreach($props_and_vals as $property => $value) {
82
- if (!isset($this->_super_properties[$property])) {
83
- $this->register($property, $value);
84
- }
85
- }
86
- }
87
-
88
-
89
- /**
90
- * Un-register an property to be sent with every event.
91
- * @param string $property
92
- */
93
- public function unregister($property) {
94
- unset($this->_super_properties[$property]);
95
- }
96
-
97
-
98
- /**
99
- * Un-register a list of properties to be sent with every event.
100
- * @param array $properties
101
- */
102
- public function unregisterAll($properties) {
103
- foreach($properties as $property) {
104
- $this->unregister($property);
105
- }
106
- }
107
-
108
-
109
- /**
110
- * Get a property that is set to be sent with every event
111
- * @param string $property
112
- * @return mixed
113
- */
114
- public function getProperty($property) {
115
- return $this->_super_properties[$property];
116
- }
117
-
118
-
119
- /**
120
- * Identify the user you want to associate to tracked events
121
- * @param string|int $user_id
122
- */
123
- public function identify($user_id) {
124
- $this->register("distinct_id", $user_id);
125
- }
126
-
127
-
128
- /**
129
- * Alias an existing id with a different unique id. This is helpful when you want to associate a generated id to
130
- * a username or e-mail address.
131
- *
132
- * Because aliasing can be extremely vulnerable to race conditions and ordering issues, we'll make a synchronous
133
- * call directly to Mixpanel when this method is called. If it fails we'll throw an Exception as subsequent
134
- * events are likely to be incorrectly tracked.
135
- * @param string|int $original_id
136
- * @param string|int $new_id
137
- * @return array $msg
138
- * @throws Exception
139
- */
140
- public function createAlias($original_id, $new_id) {
141
- $msg = array(
142
- "event" => '$create_alias',
143
- "properties" => array("distinct_id" => $original_id, "alias" => $new_id, "token" => $this->_token)
144
- );
145
-
146
- $options = array_merge($this->_options, array("endpoint" => $this->_getEndpoint(), "fork" => false));
147
- $LI_CurlConsumer = new LI_ConsumerStrategies_CurlConsumer($options);
148
- $success = $LI_CurlConsumer->persist(array($msg));
149
- if (!$success) {
150
- //error_log("Creating Mixpanel Alias (original id: $original_id, new id: $new_id) failed");
151
- //throw new Exception("Tried to create an alias but the call was not successful");
152
- } else {
153
- return $msg;
154
- }
155
- }
156
-
157
-
158
- /**
159
- * Returns the "events" endpoint
160
- * @return string
161
- */
162
- function _getEndpoint() {
163
- return $this->_options['events_endpoint'];
164
- }
165
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/mixpanel/Producers/LI_MixpanelPeople.php DELETED
@@ -1,139 +0,0 @@
1
- <?php
2
-
3
- require_once(dirname(__FILE__) . "/LI_MixpanelBaseProducer.php");
4
-
5
- /**
6
- * Provides an API to create/update profiles on Mixpanel
7
- */
8
- class LI_Producers_MixpanelPeople extends LI_Producers_MixpanelBaseProducer {
9
-
10
- /**
11
- * Internal method to prepare a message given the message data
12
- * @param $distinct_id
13
- * @param $operation
14
- * @param $value
15
- * @param null $ip
16
- * @return array
17
- */
18
- private function _constructPayload($distinct_id, $operation, $value, $ip = null) {
19
- $payload = array(
20
- '$token' => $this->_token,
21
- '$distinct_id' => $distinct_id,
22
- $operation => $value
23
- );
24
- if ($ip !== null) $payload['$ip'] = $ip;
25
- return $payload;
26
- }
27
-
28
- /**
29
- * Set properties on a user record. If the profile does not exist, it creates it with these properties.
30
- * If it does exist, it sets the properties to these values, overwriting existing values.
31
- * @param string|int $distinct_id the distinct_id or alias of a user
32
- * @param array $props associative array of properties to set on the profile
33
- * @param string|null $ip the ip address of the client (used for geo-location)
34
- */
35
- public function set($distinct_id, $props, $ip = null) {
36
- $payload = $this->_constructPayload($distinct_id, '$set', $props, $ip);
37
- $this->enqueue($payload);
38
- }
39
-
40
- /**
41
- * Set properties on a user record. If the profile does not exist, it creates it with these properties.
42
- * If it does exist, it sets the properties to these values but WILL NOT overwrite existing values.
43
- * @param string|int $distinct_id the distinct_id or alias of a user
44
- * @param array $props associative array of properties to set on the profile
45
- * @param string|null $ip the ip address of the client (used for geo-location)
46
- */
47
- public function setOnce($distinct_id, $props, $ip = null) {
48
- $payload = $this->_constructPayload($distinct_id, '$set_once', $props, $ip);
49
- $this->enqueue($payload);
50
- }
51
-
52
- /**
53
- * Unset properties on a user record. If the profile does not exist, it creates it with no properties.
54
- * If it does exist, it unsets these properties. NOTE: In other libraries we use 'unset' which is
55
- * a reserved word in PHP.
56
- * @param string|int $distinct_id the distinct_id or alias of a user
57
- * @param array $props associative array of properties to unset on the profile
58
- * @param string|null $ip the ip address of the client (used for geo-location)
59
- */
60
- public function remove($distinct_id, $props, $ip = null) {
61
- $payload = $this->_constructPayload($distinct_id, '$unset', $props, $ip);
62
- $this->enqueue($payload);
63
- }
64
-
65
- /**
66
- * Increments the value of a property on a user record. If the profile does not exist, it creates it and sets the
67
- * property to the increment value.
68
- * @param string|int $distinct_id the distinct_id or alias of a user
69
- * @param $prop string the property to increment
70
- * @param int $val the amount to increment the property by
71
- * @param string|null $ip the ip address of the client (used for geo-location)
72
- */
73
- public function increment($distinct_id, $prop, $val, $ip = null) {
74
- $payload = $this->_constructPayload($distinct_id, '$add', array("$prop" => $val), $ip);
75
- $this->enqueue($payload);
76
- }
77
-
78
- /**
79
- * Adds $val to a list located at $prop. If the property does not exist, it will be created. If $val is a string
80
- * and the list is empty or does not exist, a new list with one value will be created.
81
- * @param string|int $distinct_id the distinct_id or alias of a user
82
- * @param string $prop the property that holds the list
83
- * @param string|array $val items to add to the list
84
- * @param string|null $ip the ip address of the client (used for geo-location)
85
- */
86
- public function append($distinct_id, $prop, $val, $ip = null) {
87
- $operation = gettype($val) == "array" ? '$union' : '$append';
88
- $payload = $this->_constructPayload($distinct_id, $operation, array("$prop" => $val), $ip);
89
- $this->enqueue($payload);
90
- }
91
-
92
- /**
93
- * Adds a transaction to the user's profile for revenue tracking
94
- * @param string|int $distinct_id the distinct_id or alias of a user
95
- * @param string $amount the transaction amount e.g. "20.50"
96
- * @param null $timestamp the timestamp of when the transaction occurred (default to current timestamp)
97
- * @param string|null $ip the ip address of the client (used for geo-location)
98
- */
99
- public function trackCharge($distinct_id, $amount, $timestamp = null, $ip = null) {
100
- $timestamp = $timestamp == null ? time() : $timestamp;
101
- $date_iso = date("c", $timestamp);
102
- $transaction = array(
103
- '$time' => $date_iso,
104
- '$amount' => $amount
105
- );
106
- $val = array('$transactions' => $transaction);
107
- $payload = $this->_constructPayload($distinct_id, '$append', $val, $ip);
108
- $this->enqueue($payload);
109
- }
110
-
111
- /**
112
- * Clear all transactions stored on a user's profile
113
- * @param string|int $distinct_id the distinct_id or alias of a user
114
- * @param string|null $ip the ip address of the client (used for geo-location)
115
- */
116
- public function clearCharges($distinct_id, $ip = null) {
117
- $payload = $this->_constructPayload($distinct_id, '$set', array('$transactions' => array()), $ip);
118
- $this->enqueue($payload);
119
- }
120
-
121
- /**
122
- * Delete this profile from Mixpanel
123
- * @param string|int $distinct_id the distinct_id or alias of a user
124
- * @param string|null $ip the ip address of the client (used for geo-location)
125
- */
126
- public function deleteUser($distinct_id, $ip = null) {
127
- $payload = $this->_constructPayload($distinct_id, '$delete', "", $ip);
128
- $this->enqueue($payload);
129
- }
130
-
131
- /**
132
- * Returns the "engage" endpoint
133
- * @return string
134
- */
135
- function _getEndpoint() {
136
- return $this->_options['people_endpoint'];
137
- }
138
-
139
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
power-ups/constant-contact-connect.php CHANGED
@@ -113,8 +113,6 @@ class WPConstantContactConnect extends WPLeadIn {
113
 
114
  if ( $this->cc_id )
115
  {
116
- leadin_track_plugin_activity('Contact Pushed to List', array('esp_connector' => 'constant_contact'));
117
-
118
  return $this->constant_contact->add_subscription($this->cc_id, $list_id, 'ACTION_BY_CLIENT');
119
  }
120
  else
@@ -135,8 +133,6 @@ class WPConstantContactConnect extends WPLeadIn {
135
  if ( $phone )
136
  $contact['WorkPhone'] = $phone;
137
 
138
- leadin_track_plugin_activity('Contact Pushed to List', array('esp_connector' => 'constant_contact'));
139
-
140
  return $this->constant_contact->add_contact($contact, array($list_id));
141
  }
142
  }
@@ -161,8 +157,6 @@ class WPConstantContactConnect extends WPLeadIn {
161
 
162
  if ( $cc_id )
163
  {
164
- leadin_track_plugin_activity('Contact Removed from List', array('esp_connector' => 'constant_contact'));
165
-
166
  return $this->constant_contact->remove_subscription($cc_id, $list_id);
167
  }
168
  else
113
 
114
  if ( $this->cc_id )
115
  {
 
 
116
  return $this->constant_contact->add_subscription($this->cc_id, $list_id, 'ACTION_BY_CLIENT');
117
  }
118
  else
133
  if ( $phone )
134
  $contact['WorkPhone'] = $phone;
135
 
 
 
136
  return $this->constant_contact->add_contact($contact, array($list_id));
137
  }
138
  }
157
 
158
  if ( $cc_id )
159
  {
 
 
160
  return $this->constant_contact->remove_subscription($cc_id, $list_id);
161
  }
162
  else
power-ups/contacts/admin/contacts-admin.php CHANGED
@@ -60,11 +60,9 @@ class WPLeadInContactsAdmin extends WPLeadInAdmin {
60
  echo '<div id="leadin" class="wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
61
 
62
  if ( $this->action != 'view' ) {
63
- leadin_track_plugin_activity("Loaded Contact List Page");
64
  $this->leadin_render_list_page();
65
  }
66
  else {
67
- leadin_track_plugin_activity("Loaded Contact Detail Page");
68
  $this->leadin_render_contact_detail($_GET['lead']);
69
  }
70
 
@@ -492,6 +490,7 @@ if ( isset($_POST['export-all']) || isset($_POST['export-selected']) )
492
  {
493
  global $wpdb;
494
  leadin_set_wpdb_tables();
 
495
 
496
  $sitename = sanitize_key(get_bloginfo('name'));
497
 
@@ -505,11 +504,11 @@ if ( isset($_POST['export-all']) || isset($_POST['export-selected']) )
505
  header('Content-Type: text/csv; charset=' . get_option('blog_charset'), TRUE);
506
 
507
  $column_headers = array(
508
- 'Email', 'Original source', 'Status', 'Visits', 'Page views', 'Forms', 'Last visit', 'Created on'
509
  );
510
 
511
  $fields = array(
512
- 'lead_email', 'lead_source', 'visits', 'lead_pageviews', 'lead_form_submissions', 'last_visit', 'lead_date'
513
  );
514
 
515
  $headers = array();
@@ -594,19 +593,18 @@ if ( isset($_POST['export-all']) || isset($_POST['export-selected']) )
594
  $q = $wpdb->prepare("
595
  SELECT
596
  l.lead_id AS lead_id,
597
- LOWER(DATE_FORMAT(l.lead_date, %s)) AS lead_date, l.lead_ip, l.lead_source, l.lead_email, l.hashkey,
598
  COUNT(DISTINCT s.form_id) AS lead_form_submissions,
599
  COUNT(DISTINCT p.pageview_id) AS lead_pageviews,
600
- LOWER(DATE_FORMAT(MAX(p.pageview_date), %s)) AS last_visit,
601
  ( SELECT COUNT(DISTINCT pageview_id) FROM $wpdb->li_pageviews WHERE lead_hashkey = l.hashkey AND pageview_session_start = 1 AND pageview_deleted = 0 ) AS visits,
602
- ( SELECT MAX(pageview_source) AS pageview_source FROM $wpdb->li_pageviews WHERE lead_hashkey = l.hashkey AND pageview_session_start = 1 AND pageview_deleted = 0 ) AS pageview_source
603
  FROM
604
  $wpdb->li_leads l
605
  LEFT JOIN $wpdb->li_submissions s ON l.hashkey = s.lead_hashkey
606
  LEFT JOIN $wpdb->li_pageviews p ON l.hashkey = p.lead_hashkey
607
- WHERE l.lead_email != '' AND l.lead_deleted = 0 " .
608
- ( isset ($_POST['export-selected']) ? " AND l.lead_id IN ( " . $_POST['leadin_selected_contacts'] . " ) " : "" ) .
609
- " AND l.hashkey != '' ", '%Y/%m/%d %l:%i%p', '%Y/%m/%d %l:%i%p');
610
 
611
  $q .= $mysql_contact_type_filter;
612
  $q .= ( $mysql_search_filter ? $mysql_search_filter : "" );
60
  echo '<div id="leadin" class="wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
61
 
62
  if ( $this->action != 'view' ) {
 
63
  $this->leadin_render_list_page();
64
  }
65
  else {
 
66
  $this->leadin_render_contact_detail($_GET['lead']);
67
  }
68
 
490
  {
491
  global $wpdb;
492
  leadin_set_wpdb_tables();
493
+ leadin_set_mysql_timezone_offset();
494
 
495
  $sitename = sanitize_key(get_bloginfo('name'));
496
 
504
  header('Content-Type: text/csv; charset=' . get_option('blog_charset'), TRUE);
505
 
506
  $column_headers = array(
507
+ 'Email', 'First Name', 'Last Name', 'Original source', 'Visits', 'Page views', 'Forms', 'Last visit', 'Created on'
508
  );
509
 
510
  $fields = array(
511
+ 'lead_email', 'lead_first_name', 'lead_last_name', 'lead_source', 'visits', 'lead_pageviews', 'lead_form_submissions', 'last_visit', 'lead_date'
512
  );
513
 
514
  $headers = array();
593
  $q = $wpdb->prepare("
594
  SELECT
595
  l.lead_id AS lead_id,
596
+ LOWER(DATE_SUB(l.lead_date, INTERVAL %d HOUR)) AS lead_date, l.lead_ip, l.lead_source, l.lead_email, l.hashkey, l.lead_first_name, l.lead_last_name,
597
  COUNT(DISTINCT s.form_id) AS lead_form_submissions,
598
  COUNT(DISTINCT p.pageview_id) AS lead_pageviews,
599
+ LOWER(DATE_SUB(MAX(p.pageview_date), INTERVAL %d HOUR)) AS last_visit,
600
  ( SELECT COUNT(DISTINCT pageview_id) FROM $wpdb->li_pageviews WHERE lead_hashkey = l.hashkey AND pageview_session_start = 1 AND pageview_deleted = 0 ) AS visits,
601
+ ( SELECT MIN(pageview_source) AS pageview_source FROM $wpdb->li_pageviews WHERE lead_hashkey = l.hashkey AND pageview_session_start = 1 AND pageview_deleted = 0 ) AS pageview_source
602
  FROM
603
  $wpdb->li_leads l
604
  LEFT JOIN $wpdb->li_submissions s ON l.hashkey = s.lead_hashkey
605
  LEFT JOIN $wpdb->li_pageviews p ON l.hashkey = p.lead_hashkey
606
+ WHERE l.lead_email != '' AND l.lead_deleted = 0 AND l.hashkey != '' " .
607
+ ( isset ($_POST['export-selected']) ? " AND l.lead_id IN ( " . $_POST['leadin_selected_contacts'] . " ) " : "" ), $wpdb->db_hour_offset, $wpdb->db_hour_offset);
 
608
 
609
  $q .= $mysql_contact_type_filter;
610
  $q .= ( $mysql_search_filter ? $mysql_search_filter : "" );
power-ups/mailchimp-connect.php CHANGED
@@ -111,8 +111,6 @@ class WPMailChimpConnect extends WPLeadIn {
111
  )
112
  ));
113
 
114
- leadin_track_plugin_activity('Contact Pushed to List', array('esp_connector' => 'mailchimp'));
115
-
116
  return $contact_synced;
117
  }
118
 
@@ -139,8 +137,6 @@ class WPMailChimpConnect extends WPLeadIn {
139
  "send_notify" => FALSE
140
  ));
141
 
142
- leadin_track_plugin_activity('Contact Removed from List', array('esp_connector' => 'mailchimp'));
143
-
144
  return $contact_removed;
145
  }
146
 
@@ -174,8 +170,6 @@ class WPMailChimpConnect extends WPLeadIn {
174
  "batch" => $batch_contacts
175
  ));
176
 
177
- leadin_track_plugin_activity('Bulk Contacts Pushed to List', array('esp_connector' => 'mailchimp'));
178
-
179
  return $list_updated;
180
  }
181
 
111
  )
112
  ));
113
 
 
 
114
  return $contact_synced;
115
  }
116
 
137
  "send_notify" => FALSE
138
  ));
139
 
 
 
140
  return $contact_removed;
141
  }
142
 
170
  "batch" => $batch_contacts
171
  ));
172
 
 
 
173
  return $list_updated;
174
  }
175
 
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: andygcook, nelsonjoyce
3
  Tags: crm, contacts, lead tracking, click tracking, visitor tracking, analytics, marketing automation, inbound marketing, subscription, marketing, lead generation, mailchimp, constant contact, newsletter, popup, popover, email list, email, contacts database, contact form, forms, form widget, popup form
4
  Requires at least: 3.7
5
  Tested up to: 4.0
6
- Stable tag: 2.2.5
7
 
8
  Leadin is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
9
 
@@ -107,8 +107,16 @@ You betcha! Leadin should work just fine on Multisite right out-of-the-box witho
107
 
108
  == Changelog ==
109
 
110
- - Current version: 2.2.5
111
- - Current version release: 2014-11-20
 
 
 
 
 
 
 
 
112
 
113
  = 2.2.5 (2014.11.20) =
114
  - Bug fixes
3
  Tags: crm, contacts, lead tracking, click tracking, visitor tracking, analytics, marketing automation, inbound marketing, subscription, marketing, lead generation, mailchimp, constant contact, newsletter, popup, popover, email list, email, contacts database, contact form, forms, form widget, popup form
4
  Requires at least: 3.7
5
  Tested up to: 4.0
6
+ Stable tag: 2.2.6
7
 
8
  Leadin is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
9
 
107
 
108
  == Changelog ==
109
 
110
+ - Current version: 2.2.6
111
+ - Current version release: 2014-12-08
112
+
113
+ = 2.2.6 (2014.12.08) =
114
+ = Enhancements =
115
+ - Added names to contact export
116
+ - Added “tagged as” to contact notification email subject lines
117
+
118
+ - Bug fixes
119
+ - Fixed bug with non-tagged contacts being added to tagged lists
120
 
121
  = 2.2.5 (2014.11.20) =
122
  - Bug fixes