Google Analytics for WordPress by MonsterInsights - Version 4.2

Version Description

  • Google Authentication now happens using OAuth. The requests have become signed as an extra security measure and tokens have become more stable, as opposed to the prior tokens used with AuthSub.
  • Added support for cross-domain tracking.
  • Fixed various small bugs.
Download this release

Release Info

Developer joostdevalk
Plugin Icon 128x128 Google Analytics for WordPress by MonsterInsights
Version 4.2
Comparing to
See all releases

Code changes from version 4.1.3 to 4.2

googleanalytics.php CHANGED
@@ -1,1500 +1,1569 @@
1
- <?php
2
- /*
3
- Plugin Name: Google Analytics for WordPress
4
- Plugin URI: http://yoast.com/wordpress/google-analytics/#utm_source=wordpress&utm_medium=plugin&utm_campaign=google-analytics-for-wordpress&utm_content=v411
5
- Description: This plugin makes it simple to add Google Analytics to your WordPress blog, adding lots of features, eg. custom variables and automatic clickout and download tracking.
6
- Author: Joost de Valk
7
- Version: 4.1.3
8
- Requires at least: 2.8
9
- Author URI: http://yoast.com/
10
- License: GPL
11
- */
12
-
13
- // This plugin was originally based on Rich Boakes' Analytics plugin: http://boakes.org/analytics
14
-
15
- define('GAWP_VERSION', '4.1.3');
16
-
17
- /*
18
- * Admin User Interface
19
- */
20
-
21
- if ( is_admin() && ( !defined('DOING_AJAX') || !DOING_AJAX ) && !class_exists( 'GA_Admin' ) ) {
22
-
23
- require_once plugin_dir_path( __FILE__ ) . 'yst_plugin_tools.php';
24
-
25
- class GA_Admin extends Yoast_GA_Plugin_Admin {
26
-
27
- var $hook = 'google-analytics-for-wordpress';
28
- var $filename = 'google-analytics-for-wordpress/googleanalytics.php';
29
- var $longname = 'Google Analytics Configuration';
30
- var $shortname = 'Google Analytics';
31
- var $ozhicon = 'images/chart_curve.png';
32
- var $optionname = 'Yoast_Google_Analytics';
33
- var $homepage = 'http://yoast.com/wordpress/google-analytics/';
34
- var $toc = '';
35
-
36
- /**
37
- * PHP4 Constructor
38
- */
39
- function GA_Admin() {
40
- $this->__construct();
41
- }
42
-
43
- /**
44
- * Constructur, load all required stuff.
45
- */
46
- function __construct() {
47
- $this->upgrade();
48
-
49
- $this->plugin_url = plugins_url( '', __FILE__ ).'/';
50
-
51
- // Register the settings page
52
- add_action( 'admin_menu', array(&$this, 'register_settings_page') );
53
-
54
- // Register the contextual help for the settings page
55
- add_action( 'contextual_help', array(&$this, 'plugin_help'), 10, 3 );
56
-
57
- // Give the settings page a nice icon in Ozh's menu
58
- add_filter( 'ozh_adminmenu_icon', array(&$this, 'add_ozh_adminmenu_icon' ) );
59
-
60
- // Give the plugin a settings link in the plugin overview
61
- add_filter( 'plugin_action_links', array(&$this, 'add_action_link'), 10, 2 );
62
-
63
- // Print Scripts and Styles
64
- add_action('admin_print_scripts', array(&$this, 'config_page_scripts') );
65
- add_action('admin_print_styles', array(&$this, 'config_page_styles') );
66
-
67
- // Setup the dashboard news widget
68
- add_action('wp_dashboard_setup', array(&$this, 'widget_setup') );
69
-
70
- // Print stuff in the settings page's head
71
- add_action('admin_head', array(&$this, 'config_page_head') );
72
-
73
- // Drop a warning on each page of the admin when Google Analytics hasn't been configured
74
- add_action('admin_footer', array(&$this, 'warning') );
75
-
76
- // Save settings
77
- // TODO: replace with Options API
78
- add_action('admin_init', array(&$this, 'save_settings') );
79
- }
80
-
81
- function config_page_head() {
82
- global $current_screen;
83
- if ( 'settings_page_'.$this->hook == $current_screen->id ) {
84
- $options = get_option( $this->optionname );
85
- if (!empty($options['uastring'])) {
86
- $uastring = $options['uastring'];
87
- } else {
88
- $uastring = '';
89
- }
90
-
91
- ?>
92
- <script type="text/javascript">
93
- function makeSublist(parent,child,childVal) {
94
- jQuery("body").append("<select style='display:none' id='"+parent+child+"'></select>");
95
- jQuery('#'+parent+child).html(jQuery("#"+child+" option"));
96
-
97
- var parentValue = jQuery('#'+parent).val();
98
- jQuery('#'+child).html(jQuery("#"+parent+child+" .sub_"+parentValue).clone());
99
-
100
- childVal = (typeof childVal == "undefined")? "" : childVal ;
101
- jQuery("#"+child).val(childVal).attr('selected','selected');
102
-
103
- jQuery('#'+parent).change(function(){
104
- var parentValue = jQuery('#'+parent).val();
105
- jQuery('#'+child).html(jQuery("#"+parent+child+" .sub_"+parentValue).clone());
106
- jQuery('#'+child).trigger("change");
107
- jQuery('#'+child).focus();
108
- });
109
- }
110
- jQuery(document).ready(function(){
111
- makeSublist('ga_account', 'uastring_sel', '<?php echo $uastring; ?>');
112
- jQuery('#position').change(function(){
113
- if (jQuery('#position').val() == 'header') {
114
- jQuery('#position_header').css("display","block");
115
- jQuery('#position_manual').css("display","none");
116
- } else {
117
- jQuery('#position_header').css("display","none");
118
- jQuery('#position_manual').css("display","block");
119
- }
120
- }).change();
121
- jQuery('#switchtomanual').change(function() {
122
- if ( jQuery('#switchtomanual').is(':checked') ) {
123
- jQuery('#uastring_manual').css('display','block');
124
- jQuery('#uastring_automatic').css('display','none');
125
- } else {
126
- jQuery('#uastring_manual').css('display','none');
127
- jQuery('#uastring_automatic').css('display','block');
128
- }
129
- }).change();
130
- jQuery('#trackoutbound').change(function(){
131
- if ( jQuery('#trackoutbound').is(':checked') ) {
132
- jQuery('#internallinktracking').css("display","block");
133
- jQuery('.internallinktracking').css("display","list-item");
134
- } else {
135
- jQuery('#internallinktracking').css("display","none");
136
- jQuery('.internallinktracking').css("display","none");
137
- }
138
- }).change();
139
- jQuery('#advancedsettings').change(function(){
140
- if ( jQuery('#advancedsettings').is(':checked') ) {
141
- jQuery('#advancedgasettings').css("display","block");
142
- jQuery('#customvarsettings').css("display","block");
143
- jQuery('.advancedgasettings').css("display","list-item");
144
- jQuery('.customvarsettings').css("display","list-item");
145
- } else {
146
- jQuery('#advancedgasettings').css("display","none");
147
- jQuery('#customvarsettings').css("display","none");
148
- jQuery('.advancedgasettings').css("display","none");
149
- jQuery('.customvarsettings').css("display","none");
150
- }
151
- }).change();
152
- jQuery('#extrase').change(function(){
153
- if ( jQuery('#extrase').is(':checked') ) {
154
- jQuery('#extrasebox').css("display","block");
155
- } else {
156
- jQuery('#extrasebox').css("display","none");
157
- }
158
- }).change();
159
- jQuery('#gajslocalhosting').change(function(){
160
- if ( jQuery('#gajslocalhosting').is(':checked') ) {
161
- jQuery('#localhostingbox').css("display","block");
162
- } else {
163
- jQuery('#localhostingbox').css("display","none");
164
- }
165
- }).change();
166
- jQuery('#customvarsettings :input').change(function() {
167
- if (jQuery("#customvarsettings :input:checked").size() > 5) {
168
- alert("<?php _e('The maximum number of allowed custom variables in Google Analytics is 5, please unselect one of the other custom variables before selecting this one.'); ?>");
169
- jQuery(this).attr('checked', false);
170
- };
171
- });
172
- jQuery('#uastring').change(function(){
173
- if ( jQuery('#switchtomanual').is(':checked') ) {
174
- if (!jQuery(this).val().match(/^UA-[\d-]+$/)) {
175
- alert("<?php _e('That\'s not a valid UA ID, please make sure it matches the expected pattern of: UA-XXXXXX-X, and that there are no spaces or other characters in the input field.'); ?>");
176
- jQuery(this).focus();
177
- }
178
- }
179
- });
180
- });
181
- </script>
182
- <link rel="shortcut icon" href="<?php echo $this->plugin_url; ?>images/favicon.ico" />
183
- <?php
184
- }
185
- }
186
-
187
- function plugin_help($contextual_help, $screen_id, $screen) {
188
- if ( $screen_id == 'settings_page_'.$this->hook ) {
189
-
190
- $contextual_help = '<h2>'.__('Having problems?').'</h2>'.
191
- '<p>'.sprintf( __("If you're having problems with this plugin, please refer to its <a href='%s'>FAQ page</a>."), 'http://yoast.com/wordpress/google-analytics/ga-wp-faq/' ).'</p>';
192
- }
193
- return $contextual_help;
194
- }
195
-
196
- function toc( $modules ) {
197
- $output = '<ul>';
198
- foreach ($modules as $module => $key) {
199
- $output .= '<li class="'.$key.'"><a href="#'.$key.'">'.$module.'</a></li>';
200
- }
201
- $output .= '</ul>';
202
- return $output;
203
- }
204
-
205
- function save_settings() {
206
- $options = get_option( $this->optionname );
207
-
208
- if ( isset($_REQUEST['reset']) && $_REQUEST['reset'] == "true" && isset($_REQUEST['plugin']) && $_REQUEST['plugin'] == 'google-analytics-for-wordpress') {
209
- $options = $this->set_defaults();
210
- $options['msg'] = "<div class=\"updated\"><p>".__('Google Analytics settings reset.')."</p></div>\n";
211
- } elseif ( isset($_POST['submit']) && isset($_POST['plugin']) && $_POST['plugin'] == 'google-analytics-for-wordpress') {
212
- if (!current_user_can('manage_options')) die(__('You cannot edit the Google Analytics for WordPress options.'));
213
- check_admin_referer('analyticspp-config');
214
-
215
- foreach (array('uastring', 'dlextensions', 'domainorurl','position','domain', 'customcode', 'ga_token', 'extraseurl', 'gajsurl', 'gfsubmiteventpv', 'trackprefix', 'ignore_userlevel', 'internallink', 'internallinklabel') as $option_name) {
216
- if (isset($_POST[$option_name]))
217
- $options[$option_name] = $_POST[$option_name];
218
- else
219
- $options[$option_name] = '';
220
- }
221
-
222
- foreach (array('extrase', 'trackoutbound', 'admintracking', 'trackadsense', 'allowanchor', 'allowlinker', 'allowhash', 'rsslinktagging', 'advancedsettings', 'trackregistration', 'theme_updated', 'cv_loggedin', 'cv_authorname', 'cv_category', 'cv_all_categories', 'cv_tags', 'cv_year', 'cv_post_type', 'outboundpageview', 'downloadspageview', 'gajslocalhosting', 'manual_uastring', 'taggfsubmit', 'wpec_tracking', 'shopp_tracking', 'anonymizeip', 'trackcommentform', 'debug','firebuglite', 'disable_pagespeed_tracking') as $option_name) {
223
- if (isset($_POST[$option_name]) && $_POST[$option_name] != 'off')
224
- $options[$option_name] = true;
225
- else
226
- $options[$option_name] = false;
227
- }
228
-
229
- if (isset($_POST['manual_uastring']) && isset($_POST['uastring_man'])) {
230
- $options['uastring'] = $_POST['uastring_man'];
231
- }
232
-
233
- $cache = '';
234
- if ( function_exists('w3tc_pgcache_flush') ) {
235
- w3tc_pgcache_flush();
236
- w3tc_dbcache_flush();
237
- w3tc_minify_flush();
238
- w3tc_objectcache_flush();
239
- $cache = ' and <strong>W3TC Caches cleared</strong>';
240
- } else if ( function_exists('wp_cache_clear_cache') ) {
241
- wp_cache_clear_cache();
242
- $cache = ' and <strong>WP Super Cache cleared</strong>';
243
- }
244
-
245
- $options['msg'] = "<div id=\"updatemessage\" class=\"updated fade\"><p>Google Analytics <strong>settings updated</strong>$cache.</p></div>\n";
246
- $options['msg'] .= "<script type=\"text/javascript\">setTimeout(function(){jQuery('#updatemessage').hide('slow');}, 3000);</script>";
247
- }
248
- update_option($this->optionname, $options);
249
- }
250
-
251
- function save_button() {
252
- return '<div class="alignright"><input type="submit" class="button-primary" name="submit" value="'.__('Update Google Analytics Settings &raquo;').'" /></div><br class="clear"/>';
253
- }
254
-
255
- function upgrade() {
256
- $options = get_option($this->optionname);
257
- if ( isset($options['version']) && $options['version'] < '4.04' ) {
258
- if ( !isset($options['ignore_userlevel']) || $options['ignore_userlevel'] == '')
259
- $options['ignore_userlevel'] = 11;
260
- }
261
- if ( !isset($options['version']) || $options['version'] != GAWP_VERSION ) {
262
- $options['version'] = GAWP_VERSION;
263
- }
264
- update_option($this->optionname, $options);
265
- }
266
-
267
- function config_page() {
268
- $options = get_option($this->optionname);
269
- if ( isset($options['msg']) )
270
- echo $options['msg'];
271
- $options['msg'] = '';
272
- update_option($this->optionname, $options);
273
-
274
- if ( !isset($options['uastring']) )
275
- $options = $this->set_defaults();
276
- $modules = array();
277
-
278
- ?>
279
- <div class="wrap">
280
- <a href="http://yoast.com/"><div id="yoast-icon" style="background: url(<?php echo $this->plugin_url; ?>images/ga-icon-32x32.png) no-repeat;" class="icon32"><br /></div></a>
281
- <h2><?php _e("Google Analytics for WordPress Configuration") ?></h2>
282
- <div class="postbox-container" style="width:65%;">
283
- <div class="metabox-holder">
284
- <div class="meta-box-sortables">
285
- <form action="<?php echo $this->plugin_options_url(); ?>" method="post" id="analytics-conf">
286
- <input type="hidden" name="plugin" value="google-analytics-for-wordpress"/>
287
- <?php
288
- wp_nonce_field('analyticspp-config');
289
- if ( empty($options['uastring']) && empty($options['ga_token']) && !isset($_GET['token']) ) {
290
- $url = $this->plugin_options_url();
291
- if (isset($_GET['switchua']))
292
- $url .= '&switchua=1';
293
- $query = 'https://www.google.com/accounts/AuthSubRequest?';
294
- $query .= http_build_query(
295
- array(
296
- 'next' => $url,
297
- 'scope' => 'https://www.google.com/analytics/feeds/',
298
- 'secure' => 0,
299
- 'session' => 1,
300
- 'hd' => 'default'
301
- )
302
- );
303
- $line = 'Please authenticate with Google Analytics to retrieve your tracking code:<br/><br/> <a class="button-primary" href="'.$query.'">Click here to authenticate with Google</a><br/><br/><strong>Note</strong>: if you have multiple Google accounts, you\'ll want to switch to the right account first, since Google doesn\'t let you switch accounts on the authentication screen.';
304
- } else if(isset($_GET['token']) || (isset($options['ga_token']) && !empty($options['ga_token']))) {
305
- if (isset($_GET['token']))
306
- $token = $_GET['token'];
307
- else
308
- $token = $options['ga_token'];
309
-
310
- require_once plugin_dir_path(__FILE__).'xmlparser.php';
311
- if (file_exists(ABSPATH.'wp-includes/class-http.php'))
312
- require_once(ABSPATH.'wp-includes/class-http.php');
313
-
314
- if (!isset($options['ga_api_responses'][$token])) {
315
- $options['ga_api_responses'] = array();
316
- $request = new WP_Http;
317
- $api_url = 'https://www.google.com/analytics/feeds/accounts/default';
318
- $headers = array(
319
- 'Content-Type' => 'application/x-www-form-urlencoded',
320
- 'Authorization' => 'AuthSub token="'.$token.'"',
321
- );
322
- $args = array(
323
- 'method' => 'GET',
324
- 'body' => '',
325
- 'headers' => $headers,
326
- 'timeout' => 20,
327
- );
328
- $result = $request->request( $api_url , $args );
329
- if (is_array($result) && $result['response']['code'] == 200) {
330
- $options['ga_api_responses'][$token] = $result;
331
- $options['ga_token'] = $token;
332
- update_option('Yoast_Google_Analytics', $options);
333
- }
334
- }
335
-
336
- if (is_array($options['ga_api_responses'][$token]) && $options['ga_api_responses'][$token]['response']['code'] == 200) {
337
- $arr = yoast_xml2array($options['ga_api_responses'][$token]['body']);
338
-
339
- $ga_accounts = array();
340
- if (isset($arr['feed']['entry'][0])) {
341
- foreach ($arr['feed']['entry'] as $site) {
342
- $ua = $site['dxp:property']['3_attr']['value'];
343
- $account = $site['dxp:property']['1_attr']['value'];
344
- if (!isset($ga_accounts[$account]) || !is_array($ga_accounts[$account]))
345
- $ga_accounts[$account] = array();
346
- $ga_accounts[$account][$site['title']] = $ua;
347
- }
348
- } else {
349
- $ua = $arr['feed']['entry']['dxp:property']['3_attr']['value'];
350
- $account = $arr['feed']['entry']['dxp:property']['1_attr']['value'];
351
- $title = $arr['feed']['entry']['title'];
352
- if (!isset($ga_accounts[$account]) || !is_array($ga_accounts[$account]))
353
- $ga_accounts[$account] = array();
354
- $ga_accounts[$account][$title] = $ua;
355
- }
356
-
357
- $select1 = '<select style="width:150px;" name="ga_account" id="ga_account">';
358
- $select1 .= "\t<option></option>\n";
359
- $select2 = '<select style="width:150px;" name="uastring" id="uastring_sel">';
360
- $i = 1;
361
- $currentua = '';
362
- if (!empty($options['uastring']))
363
- $currentua = $options['uastring'];
364
-
365
- foreach($ga_accounts as $account => $val) {
366
- $accountsel = false;
367
- foreach ($val as $title => $ua) {
368
- $sel = selected($ua, $currentua, false);
369
- if (!empty($sel)) {
370
- $accountsel = true;
371
- }
372
- $select2 .= "\t".'<option class="sub_'.$i.'" '.$sel.' value="'.$ua.'">'.$title.' - '.$ua.'</option>'."\n";
373
- }
374
- $select1 .= "\t".'<option '.selected($accountsel,true,false).' value="'.$i.'">'.$account.'</option>'."\n";
375
- $i++;
376
- }
377
- $select1 .= '</select>';
378
- $select2 .= '</select>';
379
-
380
- $line = '<input type="hidden" name="ga_token" value="'.$token.'"/>';
381
- $line .= 'Please select the correct Analytics profile to track:<br/>';
382
- $line .= '<table class="form_table">';
383
- $line .= '<tr><th width="15%">Account:</th><td width="85%">'.$select1.'</td></tr>';
384
- $line .= '<tr><th>Profile:</th><td>'.$select2.'</td></tr>';
385
- $line .= '</table>';
386
-
387
- $try = 1;
388
- if (isset($_GET['try']))
389
- $try = $_GET['try'] + 1;
390
-
391
- if ($i == 1 && $try < 4 && isset($_GET['token'])) {
392
- $line .= '<script type="text/javascript">
393
- window.location="'.$this->plugin_options_url().'&switchua=1&token='.$token.'&try='.$try.'";
394
- </script>';
395
- }
396
- $line .= 'Please note that if you have several profiles of the same website, it doesn\'t matter which profile you select, and in fact another profile might show as selected later. You can check whether they\'re profiles for the same site by checking if they have the same UA code. If that\'s true, tracking will be correct.<br/>';
397
- $line .= '<br/>Refresh this listing or switch to another account: ';
398
- } else {
399
- $line = 'Unfortunately, an error occurred while connecting to Google, please try again:';
400
- }
401
-
402
- $url = $this->plugin_options_url();
403
- if (isset($_GET['switchua']))
404
- $url .= '&switchua=1';
405
- $query = 'https://www.google.com/accounts/AuthSubRequest?';
406
- $query .= http_build_query(
407
- array(
408
- 'next' => $url,
409
- 'scope' => 'https://www.google.com/analytics/feeds/',
410
- 'secure' => 0,
411
- 'session' => 1,
412
- 'hd' => 'default'
413
- )
414
- );
415
- $line .= '<a class="button" href="'.$query.'">Re-authenticate with Google</a>';
416
- } else {
417
- $line = '<input id="uastring" name="uastring" type="text" size="20" maxlength="40" value="'.$options['uastring'].'"/><br/><a href="'.$this->plugin_options_url().'&amp;switchua=1">Select another Analytics Profile &raquo;</a>';
418
- }
419
- $line = '<div id="uastring_automatic">'.$line.'</div><div style="display:none;" id="uastring_manual">Manually enter your UA code: <input id="uastring" name="uastring_man" type="text" size="20" maxlength="40" value="'.$options['uastring'].'"/></div>';
420
- $rows = array();
421
- $content = '';
422
- $rows[] = array(
423
- 'id' => 'uastring',
424
- 'label' => 'Analytics Profile',
425
- 'desc' => '<input type="checkbox" name="manual_uastring" '.checked($options['manual_uastring'], true, false).' id="switchtomanual"/> <label for="switchtomanual">Manually enter your UA code</label>',
426
- 'content' => $line
427
- );
428
- $temp_content = $this->select('position', array('header' => 'In the header (default)', 'manual' => 'Insert manually'));
429
- if ($options['theme_updated'] && $options['position'] == 'manual') {
430
- $temp_content .= '<input type="hidden" name="theme_updated" value="off"/>';
431
- echo '<div id="message" class="updated" style="background-color:lightgreen;border-color:green;"><p><strong>Notice:</strong> You switched your theme, please make sure your Google Analytics tracking is still ok. Save your settings to make sure Google Analytics gets loaded properly.</p></div>';
432
- remove_action('admin_footer', array(&$this,'theme_switch_warning'));
433
- }
434
- $desc = '<div id="position_header">The header is by far the best spot to place the tracking code. If you\'d rather place the code manually, switch to manual placement. For more info <a href="http://yoast.com/wordpress/google-analytics/manual-placement/">read this page</a>.</div>';
435
- $desc .= '<div id="position_manual"><a href="http://yoast.com/wordpress/google-analytics/manual-placement/">Follow the instructions here</a> to choose the location for your tracking code manually.</div>';
436
-
437
- $rows[] = array(
438
- 'id' => 'position',
439
- 'label' => 'Where should the tracking code be placed',
440
- 'desc' => $desc,
441
- 'content' => $temp_content,
442
- );
443
- $rows[] = array(
444
- 'id' => 'trackoutbound',
445
- 'label' => 'Track outbound clicks &amp; downloads',
446
- 'desc' => 'Clicks &amp; downloads will be tracked as events, you can find these under Content &raquo; Event Tracking in your Google Analytics reports.',
447
- 'content' => $this->checkbox('trackoutbound'),
448
- );
449
- $rows[] = array(
450
- 'id' => 'advancedsettings',
451
- 'label' => 'Show advanced settings',
452
- 'desc' => 'Only adviced for advanced users who know their way around Google Analytics',
453
- 'content' => $this->checkbox('advancedsettings'),
454
- );
455
- $this->postbox('gasettings','Google Analytics Settings',$this->form_table($rows).$this->save_button());
456
-
457
- $rows = array();
458
- $pre_content = '<p>Google Analytics allows you to save up to 5 custom variables on each page, and this plugin helps you make the most use of these! Check which custom variables you\'d like the plugin to save for you below. Please note that these will only be saved when they are actually available.</p><p>If you want to start using these custom variables, go to Visitors &raquo; Custom Variables in your Analytics reports.</p>';
459
- $rows[] = array(
460
- 'id' => 'cv_loggedin',
461
- 'label' => 'Logged in Users',
462
- 'desc' => 'Allows you to easily remove logged in users from your reports, or to segment by different user roles. The users primary role will be logged.',
463
- 'content' => $this->checkbox('cv_loggedin'),
464
- );
465
- $rows[] = array(
466
- 'id' => 'cv_post_type',
467
- 'label' => 'Post type',
468
- 'desc' => 'Allows you to see pageviews per post type, especially useful if you use multiple custom post types.',
469
- 'content' => $this->checkbox('cv_post_type'),
470
- );
471
- $rows[] = array(
472
- 'id' => 'cv_authorname',
473
- 'label' => 'Author Name',
474
- 'desc' => 'Allows you to see pageviews per author.',
475
- 'content' => $this->checkbox('cv_authorname'),
476
- );
477
- $rows[] = array(
478
- 'id' => 'cv_tags',
479
- 'label' => 'Tags',
480
- 'desc' => 'Allows you to see pageviews per tags using advanced segments.',
481
- 'content' => $this->checkbox('cv_tags'),
482
- );
483
- $rows[] = array(
484
- 'id' => 'cv_year',
485
- 'label' => 'Publication year',
486
- 'desc' => 'Allows you to see pageviews per year of publication, showing you if your old posts still get traffic.',
487
- 'content' => $this->checkbox('cv_year'),
488
- );
489
- $rows[] = array(
490
- 'id' => 'cv_category',
491
- 'label' => 'Single Category',
492
- 'desc' => 'Allows you to see pageviews per category, works best when each post is in only one category.',
493
- 'content' => $this->checkbox('cv_category'),
494
- );
495
- $rows[] = array(
496
- 'id' => 'cv_all_categories',
497
- 'label' => 'All Categories',
498
- 'desc' => 'Allows you to see pageviews per category using advanced segments, should be used when you use multiple categories per post.',
499
- 'content' => $this->checkbox('cv_all_categories'),
500
- );
501
-
502
- $modules['Custom Variables'] = 'customvarsettings';
503
- $this->postbox('customvarsettings','Custom Variables Settings',$pre_content.$this->form_table($rows).$this->save_button());
504
-
505
- $rows = array();
506
- $rows[] = array(
507
- 'id' => 'ignore_userlevel',
508
- 'label' => 'Ignore users',
509
- 'desc' => 'Users of the role you select and higher will be ignored, so if you select Editor, all Editors and Administrators will be ignored.',
510
- 'content' => $this->select('ignore_userlevel', array(
511
- '11' => 'Ignore no-one',
512
- '8' => 'Administrator',
513
- '5' => 'Editor',
514
- '2' => 'Author',
515
- '1' => 'Contributor',
516
- '0' => 'Subscriber (ignores all logged in users)',
517
- )),
518
- );
519
- $rows[] = array(
520
- 'id' => 'outboundpageview',
521
- 'label' => 'Track outbound clicks as pageviews',
522
- 'desc' => 'You do not need to enable this to enable outbound click tracking, this changes the default behavior of tracking clicks as events to tracking them as pageviews. This is therefore not recommended, as this would skew your statistics, but <em>is</em> sometimes necessary when you need to set outbound clicks as goals.',
523
- 'content' => $this->checkbox('outboundpageview'),
524
- );
525
- $rows[] = array(
526
- 'id' => 'downloadspageview',
527
- 'label' => 'Track downloads as pageviews',
528
- 'desc' => 'Not recommended, as this would skew your statistics, but it does make it possible to track downloads as goals.',
529
- 'content' => $this->checkbox('downloadspageview'),
530
- );
531
- $rows[] = array(
532
- 'id' => 'dlextensions',
533
- 'label' => 'Extensions of files to track as downloads',
534
- 'content' => $this->textinput('dlextensions'),
535
- );
536
- if ( $options['outboundpageview'] ) {
537
- $rows[] = array(
538
- 'id' => 'trackprefix',
539
- 'label' => 'Prefix to use in Analytics before the tracked pageviews',
540
- 'desc' => 'This prefix is used before all pageviews, they are then segmented automatically after that. If nothing is entered here, <code>/yoast-ga/</code> is used.',
541
- 'content' => $this->textinput('trackprefix'),
542
- );
543
- }
544
- $rows[] = array(
545
- 'id' => 'domainorurl',
546
- 'label' => 'Track full URL of outbound clicks or just the domain',
547
- 'content' => $this->select('domainorurl', array(
548
- 'domain' => 'Just the domain',
549
- 'url' => 'Track the complete URL',
550
- )
551
- ),
552
- );
553
- $rows[] = array(
554
- 'id' => 'domain',
555
- 'label' => 'Domain Tracking',
556
- 'desc' => 'This allows you to set the domain that\'s set by <a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setDomainName"><code>setDomainName</code></a> for tracking subdomains, if empty this will not be set.',
557
- 'content' => $this->textinput('domain'),
558
- );
559
- $rows[] = array(
560
- 'id' => 'disable_pagespeed_tracking',
561
- 'label' => 'Disable Site Speed tracking',
562
- 'desc' => 'This disables the Site Speed tracking feature of Google Analytics that is enabled by default in this plugin.',
563
- 'content' => $this->checkbox('disable_pagespeed_tracking'),
564
- );
565
- $rows[] = array(
566
- 'id' => 'customcode',
567
- 'label' => 'Custom Code',
568
- 'desc' => 'Not for the average user: this allows you to add a line of code, to be added before the <code>trackPageview</code> call.',
569
- 'content' => $this->textinput('customcode'),
570
- );
571
- $rows[] = array(
572
- 'id' => 'trackadsense',
573
- 'label' => 'Track AdSense',
574
- 'desc' => 'This requires integration of your Analytics and AdSense account, for help, <a href="http://google.com/support/analytics/bin/answer.py?answer=92625">look here</a>.',
575
- 'content' => $this->checkbox('trackadsense'),
576
- );
577
- $rows[] = array(
578
- 'id' => 'gajslocalhosting',
579
- 'label' => 'Host ga.js locally',
580
- 'content' => $this->checkbox('gajslocalhosting').'<div id="localhostingbox">
581
- You have to provide a URL to your ga.js file:
582
- <input type="text" name="gajsurl" size="30" value="'.$options['gajsurl'].'"/>
583
- </div>',
584
- 'desc' => 'For some reasons you might want to use a locally hosted ga.js file, or another ga.js file, check the box and then please enter the full URL including http here.'
585
- );
586
- $rows[] = array(
587
- 'id' => 'extrase',
588
- 'label' => 'Track extra Search Engines',
589
- 'content' => $this->checkbox('extrase').'<div id="extrasebox">
590
- You can provide a custom URL to the extra search engines file if you want:
591
- <input type="text" name="extraseurl" size="30" value="'.$options['extraseurl'].'"/>
592
- </div>',
593
- );
594
- $rows[] = array(
595
- 'id' => 'rsslinktagging',
596
- 'label' => 'Tag links in RSS feed with campaign variables',
597
- 'desc' => 'Do not use this feature if you use FeedBurner, as FeedBurner can do this automatically, and better than this plugin can. Check <a href="http://www.google.com/support/feedburner/bin/answer.py?hl=en&amp;answer=165769">this help page</a> for info on how to enable this feature in FeedBurner.',
598
- 'content' => $this->checkbox('rsslinktagging'),
599
- );
600
- $rows[] = array(
601
- 'id' => 'trackregistration',
602
- 'label' => 'Add tracking to the login and registration forms',
603
- 'content' => $this->checkbox('trackregistration'),
604
- );
605
- $rows[] = array(
606
- 'id' => 'trackcommentform',
607
- 'label' => 'Add tracking to the comment forms',
608
- 'content' => $this->checkbox('trackcommentform'),
609
- );
610
- $rows[] = array(
611
- 'id' => 'allowanchor',
612
- 'label' => 'Use # instead of ? for Campaign tracking',
613
- 'desc' => 'This adds a <code><a href="http://code.google.com/apis/analytics/docs/gaJSApiCampaignTracking.html#_gat.GA_Tracker_._setAllowAnchor">_setAllowAnchor</a></code> call to your tracking code, and makes RSS link tagging use a # as well.',
614
- 'content' => $this->checkbox('allowanchor'),
615
- );
616
- $rows[] = array(
617
- 'id' => 'allowlinker',
618
- 'label' => 'Add <code>_setAllowLinker</code>',
619
- 'desc' => 'This adds a <code><a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setAllowLinker">_setAllowLinker</a></code> call to your tracking code, allowing you to use <code>_link</code> and related functions.',
620
- 'content' => $this->checkbox('allowlinker'),
621
- );
622
- $rows[] = array(
623
- 'id' => 'allowhash',
624
- 'label' => 'Set <code>_setAllowHash</code> to false',
625
- 'desc' => 'This sets <code><a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setAllowHash">_setAllowHash</a></code> to false, allowing you to track subdomains etc.',
626
- 'content' => $this->checkbox('allowhash'),
627
- );
628
- $rows[] = array(
629
- 'id' => 'anonymizeip',
630
- 'label' => 'Anonymize IP\'s',
631
- 'desc' => 'This adds <code><a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_gat._anonymizeIp">_anonymizeIp</a></code>, telling Google Analytics to anonymize the information sent by the tracker objects by removing the last octet of the IP address prior to its storage.',
632
- 'content' => $this->checkbox('anonymizeip'),
633
- );
634
- $modules['Advanced Settings'] = 'advancedgasettings';
635
- $this->postbox('advancedgasettings','Advanced Settings',$this->form_table($rows).$this->save_button());
636
-
637
- $rows = array();
638
- $rows[] = array(
639
- 'id' => 'internallink',
640
- 'label' => 'Internal links to track as outbound',
641
- 'desc' => 'If you want to track all internal links that begin with <code>/out/</code>, enter <code>/out/</code> in the box above. If you have multiple prefixes you can separate them with comma\'s: <code>/out/,/recommends/</code>',
642
- 'content' => $this->textinput('internallink'),
643
- );
644
- $rows[] = array(
645
- 'id' => 'internallinklabel',
646
- 'label' => 'Label to use',
647
- 'desc' => 'The label to use for these links, this will be added to where the click came from, so if the label is "aff", the label for a click from the content of an article becomes "outbound-article-aff".',
648
- 'content' => $this->textinput('internallinklabel'),
649
- );
650
- $modules['Internal Link Tracking'] = 'internallinktracking';
651
- $this->postbox('internallinktracking','Internal Links to Track as Outbound',$this->form_table($rows).$this->save_button());
652
-
653
- /* if (class_exists('RGForms') && GFCommon::$version >= '1.3.11') {
654
- $pre_content = 'This plugin can automatically tag your Gravity Forms to track form submissions as either events or pageviews';
655
- $rows = array();
656
- $rows[] = array(
657
- 'id' => 'taggfsubmit',
658
- 'label' => 'Tag Gravity Forms',
659
- 'content' => $this->checkbox('taggfsubmit'),
660
- );
661
- $rows[] = array(
662
- 'id' => 'gfsubmiteventpv',
663
- 'label' => 'Tag Gravity Forms as',
664
- 'content' => '<select name="gfsubmiteventpv">
665
- <option value="events" '.selected($options['gfsubmiteventpv'],'events',false).'>Events</option>
666
- <option value="pageviews" '.selected($options['gfsubmiteventpv'],'pageviews',false).'>Pageviews</option>
667
- </select>',
668
- );
669
- $this->postbox('gravityforms','Gravity Forms Settings',$pre_content.$this->form_table($rows).$this->save_button());
670
- $modules['Gravity Forms'] = 'gravityforms';
671
- }
672
- */
673
- if ( defined('WPSC_VERSION') ) {
674
- $pre_content = 'The WordPress e-Commerce plugin has been detected. This plugin can automatically add transaction tracking for you. To do that, <a href="http://yoast.com/wordpress/google-analytics/enable-ecommerce/">enable e-commerce for your reports in Google Analytics</a> and then check the box below.';
675
- $rows = array();
676
- $rows[] = array(
677
- 'id' => 'wpec_tracking',
678
- 'label' => 'Enable transaction tracking',
679
- 'content' => $this->checkbox('wpec_tracking'),
680
- );
681
- $this->postbox('wpecommerce','WordPress e-Commerce Settings',$pre_content.$this->form_table($rows).$this->save_button());
682
- $modules['WordPress e-Commerce'] = 'wpecommerce';
683
- }
684
-
685
- global $Shopp;
686
- if ( isset($Shopp) ) {
687
- $pre_content = 'The Shopp e-Commerce plugin has been detected. This plugin can automatically add transaction tracking for you. To do that, <a href="http://www.google.com/support/googleanalytics/bin/answer.py?hl=en&amp;answer=55528">enable e-commerce for your reports in Google Analytics</a> and then check the box below.';
688
- $rows = array();
689
- $rows[] = array(
690
- 'id' => 'shopp_tracking',
691
- 'label' => 'Enable transaction tracking',
692
- 'content' => $this->checkbox('shopp_tracking'),
693
- );
694
- $this->postbox('shoppecommerce','Shopp e-Commerce Settings',$pre_content.$this->form_table($rows).$this->save_button());
695
- $modules['Shopp'] = 'shoppecommerce';
696
- }
697
- $pre_content = '<p>If you want to confirm that tracking on your blog is working as it should, enable this option and check the console in <a href="http://getfirebug.com/">Firebug</a> (for Firefox), <a href="http://getfirebug.com/firebuglite">Firebug Lite</a> (for other browsers) or Chrome &amp; Safari\'s Web Inspector. Be absolutely sure to disable debugging afterwards, as it is slower than normal tracking.</p><p><strong>Note</strong>: the debugging and firebug scripts are only loaded for admins.</p>';
698
- $rows = array();
699
- $rows[] = array(
700
- 'id' => 'debug',
701
- 'label' => 'Enable debug mode',
702
- 'content' => $this->checkbox('debug'),
703
- );
704
- $rows[] = array(
705
- 'id' => 'firebuglite',
706
- 'label' => 'Enable Firebug Lite',
707
- 'content' => $this->checkbox('firebuglite'),
708
- );
709
- $this->postbox('debugmode','Debug Mode',$pre_content.$this->form_table($rows).$this->save_button());
710
- $modules['Debug Mode'] = 'debugmode';
711
- ?>
712
- </form>
713
- <form action="<?php echo $this->plugin_options_url(); ?>" method="post" onsubmit="javascript:return(confirm('Do you really want to reset all settings?'));">
714
- <input type="hidden" name="reset" value="true"/>
715
- <input type="hidden" name="plugin" value="google-analytics-for-wordpress"/>
716
- <div class="submit"><input type="submit" value="Reset All Settings &raquo;" /></div>
717
- </form>
718
- </div>
719
- </div>
720
- </div>
721
- <div class="postbox-container side" style="width:20%;">
722
- <div class="metabox-holder">
723
- <div class="meta-box-sortables">
724
- <?php
725
- if ( count($modules) > 0 )
726
- $this->postbox('toc','List of Available Modules',$this->toc($modules));
727
- $this->plugin_like();
728
- $this->postbox('donate','<strong class="red">Donate $10, $20 or $50!</strong>','<p>This plugin has cost me countless hours of work, if you use it, please donate a token of your appreciation!</p><br/><form style="margin-left:50px;" action="https://www.paypal.com/cgi-bin/webscr" method="post">
729
- <input type="hidden" name="cmd" value="_s-xclick">
730
- <input type="hidden" name="hosted_button_id" value="FW9FK4EBZ9FVJ">
731
- <input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
732
- <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
733
- </form>');
734
- $this->plugin_support();
735
- $this->news();
736
- ?>
737
- </div>
738
- <br/><br/><br/>
739
- </div>
740
- </div>
741
- </div>
742
- <?php
743
- }
744
-
745
- function set_defaults() {
746
- $options = array(
747
- 'advancedsettings' => false,
748
- 'allowanchor' => false,
749
- 'allowhash' => false,
750
- 'allowlinker' => false,
751
- 'anonymizeip' => false,
752
- 'customcode' => '',
753
- 'cv_loggedin' => false,
754
- 'cv_authorname' => false,
755
- 'cv_category' => false,
756
- 'cv_all_categories' => false,
757
- 'cv_tags' => false,
758
- 'cv_year' => false,
759
- 'cv_post_type' => false,
760
- 'debug' => false,
761
- 'dlextensions' => 'doc,exe,js,pdf,ppt,tgz,zip,xls',
762
- 'domain' => '',
763
- 'domainorurl' => 'domain',
764
- 'extrase' => false,
765
- 'extraseurl' => '',
766
- 'firebuglite' => false,
767
- 'ga_token' => '',
768
- 'ga_api_responses' => array(),
769
- 'gajslocalhosting' => false,
770
- 'gajsurl' => '',
771
- 'ignore_userlevel' => '11',
772
- 'internallink' => false,
773
- 'internallinklabel' => '',
774
- 'outboundpageview' => false,
775
- 'downloadspageview' => false,
776
- 'manual_uastring' => '',
777
- 'position' => 'footer',
778
- 'theme_updated' => false,
779
- 'trackcommentform' => true,
780
- 'trackadsense' => false,
781
- 'trackoutbound' => true,
782
- 'trackregistration' => false,
783
- 'rsslinktagging' => true,
784
- 'uastring' => '',
785
- 'version' => GAWP_VERSION,
786
- );
787
- update_option($this->optionname,$options);
788
- return $options;
789
- }
790
-
791
- function warning() {
792
- $options = get_option($this->optionname);
793
- if (!isset($options['uastring']) || empty($options['uastring'])) {
794
- echo "<div id='message' class='error'><p><strong>Google Analytics is not active.</strong> You must <a href='".$this->plugin_options_url()."'>select which Analytics Profile to track</a> before it can work.</p></div>";
795
- }
796
- } // end warning()
797
-
798
- } // end class GA_Admin
799
-
800
- $ga_admin = new GA_Admin();
801
- } //endif
802
-
803
-
804
- /**
805
- * Code that actually inserts stuff into pages.
806
- */
807
- if ( ! class_exists( 'GA_Filter' ) ) {
808
- class GA_Filter {
809
-
810
- /**
811
- * Cleans the variable to make it ready for storing in Google Analytics
812
- */
813
- function ga_str_clean($val) {
814
- return remove_accents(str_replace('---','-',str_replace(' ','-',strtolower(html_entity_decode($val)))));
815
- }
816
- /*
817
- * Insert the tracking code into the page
818
- */
819
- function spool_analytics() {
820
- global $wp_query;
821
- // echo '<!--'.print_r($wp_query,1).'-->';
822
-
823
- $options = get_option('Yoast_Google_Analytics');
824
-
825
- if ( !isset($options['uastring']) || $options['uastring'] == '' ) {
826
- if ( current_user_can('manage_options') )
827
- echo "<!-- Google Analytics tracking code not shown because yo haven't chosen a Google Analytics account yet. -->\n";
828
- return;
829
- }
830
-
831
- /**
832
- * The order of custom variables is very, very important: custom vars should always take up the same slot to make analysis easy.
833
- */
834
- $customvarslot = 1;
835
- if ( yoast_ga_do_tracking() && !is_preview() ) {
836
- $push = array();
837
-
838
- if ( $options['allowanchor'] )
839
- $push[] = "'_setAllowAnchor',true";
840
-
841
- if ( $options['allowlinker'] )
842
- $push[] = "'_setAllowLinker',true";
843
-
844
- if ( $options['anonymizeip'] )
845
- $push[] = "'_gat._anonymizeIp'";
846
-
847
- if ( isset($options['domain']) && $options['domain'] != "" ) {
848
- // should allow for a 'none' domain too!
849
- if (substr($options['domain'],0,1) != "." && $options['domain'] != 'none')
850
- $options['domain'] = ".".$options['domain'];
851
- $push[] = "'_setDomainName','".$options['domain']."'";
852
- }
853
-
854
- if ( $options['allowhash'] )
855
- $push[] = "'_setAllowHash',false";
856
-
857
- if ( $options['cv_loggedin'] ) {
858
- $current_user = wp_get_current_user();
859
- if ( $current_user && $current_user->ID != 0 )
860
- $push[] = "'_setCustomVar',$customvarslot,'logged-in','".$current_user->roles[0]."',1";
861
- // Customvar slot needs to be upped even when the user is not logged in, to make sure the variables below are always in the same slot.
862
- $customvarslot++;
863
- }
864
-
865
- if ( function_exists('is_post_type_archive') && is_post_type_archive() ) {
866
- if ( $options['cv_post_type'] ) {
867
- $post_type = get_post_type();
868
- if ( $post_type ) {
869
- $push[] = "'_setCustomVar',".$customvarslot.",'post_type','".$post_type."',3";
870
- $customvarslot++;
871
- }
872
- }
873
- } else if ( is_singular() && !is_home() ) {
874
- if ( $options['cv_post_type'] ) {
875
- $post_type = get_post_type();
876
- if ( $post_type ) {
877
- $push[] = "'_setCustomVar',".$customvarslot.",'post_type','".$post_type."',3";
878
- $customvarslot++;
879
- }
880
- }
881
- if ( $options['cv_authorname'] ) {
882
- $push[] = "'_setCustomVar',$customvarslot,'author','".GA_Filter::ga_str_clean(get_the_author_meta('display_name',$wp_query->post->post_author))."',3";
883
- $customvarslot++;
884
- }
885
- if ( $options['cv_tags'] ) {
886
- $i = 0;
887
- if ( get_the_tags() ) {
888
- $tagsstr = '';
889
- foreach ( get_the_tags() as $tag ) {
890
- if ($i > 0)
891
- $tagsstr .= ' ';
892
- $tagsstr .= $tag->slug;
893
- $i++;
894
- }
895
- // Max 64 chars for value and label combined, hence 64 - 4
896
- $tagsstr = substr($tagsstr, 0, 60);
897
- $push[] = "'_setCustomVar',$customvarslot,'tags','".$tagsstr."',3";
898
- }
899
- $customvarslot++;
900
- }
901
- if ( is_singular() ) {
902
- if ( $options['cv_year'] ) {
903
- $push[] = "'_setCustomVar',$customvarslot,'year','".get_the_time('Y')."',3";
904
- $customvarslot++;
905
- }
906
- if ( $options['cv_category'] && is_single() ) {
907
- $cats = get_the_category();
908
- if ( is_array( $cats ) && isset( $cats[0] ) )
909
- $push[] = "'_setCustomVar',$customvarslot,'category','".$cats[0]->slug."',3";
910
- $customvarslot++;
911
- }
912
- if ( $options['cv_all_categories'] && is_single() ) {
913
- $i = 0;
914
- $catsstr = '';
915
- foreach ( (array) get_the_category() as $cat ) {
916
- if ($i > 0)
917
- $catsstr .= ' ';
918
- $catsstr .= $cat->slug;
919
- $i++;
920
- }
921
- // Max 64 chars for value and label combined, hence 64 - 10
922
- $catsstr = substr($catsstr, 0, 54);
923
- $push[] = "'_setCustomVar',$customvarslot,'categories','".$catsstr."',3";
924
- $customvarslot++;
925
- }
926
- }
927
- }
928
-
929
- $push = apply_filters('yoast-ga-custom-vars',$push, $customvarslot);
930
-
931
- $push = apply_filters('yoast-ga-push-before-pageview',$push);
932
-
933
- if ( is_404() ) {
934
- $push[] = "'_trackPageview','/404.html?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer";
935
- } else if ($wp_query->is_search) {
936
- $pushstr = "'_trackPageview','".get_bloginfo('url')."/?s=";
937
- if ($wp_query->found_posts == 0) {
938
- $push[] = $pushstr."no-results:".rawurlencode($wp_query->query_vars['s'])."&cat=no-results'";
939
- } else if ($wp_query->found_posts == 1) {
940
- $push[] = $pushstr.rawurlencode($wp_query->query_vars['s'])."&cat=1-result'";
941
- } else if ($wp_query->found_posts > 1 && $wp_query->found_posts < 6) {
942
- $push[] = $pushstr.rawurlencode($wp_query->query_vars['s'])."&cat=2-5-results'";
943
- } else {
944
- $push[] = $pushstr.rawurlencode($wp_query->query_vars['s'])."&cat=plus-5-results'";
945
- }
946
- } else {
947
- $push[] = "'_trackPageview'";
948
- }
949
-
950
- if ( !isset( $options['disable_pagespeed_tracking'] ) || !$options['disable_pagespeed_tracking'] ) {
951
- $push[] = "'_trackPageLoadTime'";
952
- }
953
-
954
- $push = apply_filters('yoast-ga-push-after-pageview',$push);
955
-
956
- if ( defined('WPSC_VERSION') && $options['wpec_tracking'] )
957
- $push = GA_Filter::wpec_transaction_tracking($push);
958
-
959
- if ($options['shopp_tracking']) {
960
- global $Shopp;
961
- if ( isset($Shopp) )
962
- $push = GA_Filter::shopp_transaction_tracking($push);
963
- }
964
-
965
- $pushstr = "";
966
- foreach ($push as $key) {
967
- if (!empty($pushstr))
968
- $pushstr .= ",";
969
-
970
- $pushstr .= "[".$key."]";
971
- }
972
-
973
- if ( current_user_can('manage_options') && $options['firebuglite'] && $options['debug'] )
974
- echo '<script src="https://getfirebug.com/firebug-lite.js" type="text/javascript"></script>';
975
- ?>
976
-
977
- <script type="text/javascript">//<![CDATA[
978
- // Google Analytics for WordPress by Yoast v<?php echo GAWP_VERSION; ?> | http://yoast.com/wordpress/google-analytics/
979
- var _gaq = _gaq || [];
980
- _gaq.push(['_setAccount','<?php echo trim($options["uastring"]); ?>']);
981
- <?php
982
- if ( $options["extrase"] ) {
983
- if ( !empty($options["extraseurl"]) ) {
984
- $url = $options["extraseurl"];
985
- } else {
986
- $url = plugins_url( 'custom_se_async.js', __FILE__ );
987
- }
988
- echo '</script><script src="'.$url.'" type="text/javascript"></script>'."\n".'<script type="text/javascript">';
989
- }
990
-
991
- if ( $options['customcode'] && trim( $options['customcode'] ) != '' )
992
- echo "\t". stripslashes( $options['customcode'] ) ."\n";
993
- ?>
994
- _gaq.push(<?php echo $pushstr; ?>);
995
- (function() {
996
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
997
- ga.src = <?php
998
- if ( $options['gajslocalhosting'] && !empty($options['gajsurl']) ) {
999
- echo "'".$options['gajsurl']."';";
1000
- } else {
1001
- $script = 'ga.js';
1002
- if ( current_user_can('manage_options') && $options['debug'] )
1003
- $script = 'u/ga_debug.js';
1004
- echo "('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/".$script."';";
1005
- }
1006
- ?>
1007
-
1008
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
1009
- })();
1010
- //]]></script>
1011
- <?php
1012
- } else if ( $options["uastring"] != "" ) {
1013
- echo "<!-- Google Analytics tracking code not shown because users over level ".$options["ignore_userlevel"]." are ignored -->\n";
1014
- }
1015
- }
1016
-
1017
- /*
1018
- * Insert the AdSense parameter code into the page. This'll go into the header per Google's instructions.
1019
- */
1020
- function spool_adsense() {
1021
- $options = get_option('Yoast_Google_Analytics');
1022
- if ( $options["uastring"] != "" && yoast_ga_do_tracking() && !is_preview() ) {
1023
- echo '<script type="text/javascript">'."\n";
1024
- echo "\t".'window.google_analytics_uacct = "'.$options["uastring"].'";'."\n";
1025
- echo '</script>'."\n";
1026
- }
1027
- }
1028
-
1029
- function ga_get_tracking_prefix() {
1030
- $options = get_option('Yoast_Google_Analytics');
1031
- return (empty($options['trackprefix'])) ? '/yoast-ga/' : $options['trackprefix'];
1032
- }
1033
-
1034
- function ga_get_tracking_link($prefix, $target, $jsprefix = 'javascript:') {
1035
- $options = get_option('Yoast_Google_Analytics');
1036
- if (
1037
- ( $prefix != 'download' && $options['outboundpageview'] ) ||
1038
- ( $prefix == 'download' && $options['downloadspageview'] ) )
1039
- {
1040
- $prefix = GA_Filter::ga_get_tracking_prefix().$prefix;
1041
- $pushstr = "['_trackPageview','".$prefix."/". esc_js( esc_url( $target ) )."']";
1042
- } else {
1043
- $pushstr = "['_trackEvent','".$prefix."','".esc_js( esc_url( $target ) )."']";
1044
- }
1045
- return $jsprefix."_gaq.push(".$pushstr.");";
1046
- }
1047
-
1048
- function ga_get_domain($uri){
1049
- $hostPattern = "/^(http:\/\/)?([^\/]+)/i";
1050
- $domainPatternUS = "/[^\.\/]+\.[^\.\/]+$/";
1051
- $domainPatternUK = "/[^\.\/]+\.[^\.\/]+\.[^\.\/]+$/";
1052
-
1053
- preg_match($hostPattern, $uri, $matches);
1054
- $host = $matches[2];
1055
- if (preg_match("/.*\..*\..*\..*$/",$host))
1056
- preg_match($domainPatternUK, $host, $matches);
1057
- else
1058
- preg_match($domainPatternUS, $host, $matches);
1059
-
1060
- return array("domain"=>$matches[0],"host"=>$host);
1061
- }
1062
-
1063
- function ga_parse_link($category, $matches){
1064
- $origin = GA_Filter::ga_get_domain($_SERVER["HTTP_HOST"]);
1065
- $options = get_option('Yoast_Google_Analytics');
1066
-
1067
- // Break out immediately if the link is not an http or https link.
1068
- if (strpos($matches[2],"http") !== 0) {
1069
- $target = false;
1070
- } else if ((strpos($matches[2],"mailto") === 0)) {
1071
- $target = 'email';
1072
- } else {
1073
- $target = GA_Filter::ga_get_domain($matches[3]);
1074
- }
1075
- $trackBit = "";
1076
- $extension = substr(strrchr($matches[3], '.'), 1);
1077
- $dlextensions = explode(",",str_replace('.','',$options['dlextensions']));
1078
- if ( $target ) {
1079
- if ( $target == 'email' ) {
1080
- $trackBit = GA_Filter::ga_get_tracking_link('mailto', str_replace('mailto:','',$matches[3]),'');
1081
- } else if ( in_array($extension, $dlextensions) ) {
1082
- $trackBit = GA_Filter::ga_get_tracking_link('download', $matches[3],'');
1083
- } else if ( $target["domain"] != $origin["domain"] ){
1084
- if ($options['domainorurl'] == "domain") {
1085
- $url = $target["host"];
1086
- } else if ($options['domainorurl'] == "url") {
1087
- $url = $matches[3];
1088
- }
1089
- $trackBit = GA_Filter::ga_get_tracking_link($category, $url,'');
1090
- } else if ( $target["domain"] == $origin["domain"] && isset($options['internallink']) && $options['internallink'] != '') {
1091
- $url = preg_replace('|'.$origin["host"].'|','',$matches[3]);
1092
- $extintlinks = explode(',',$options['internallink']);
1093
- foreach ($extintlinks as $link) {
1094
- if (preg_match('|^'.trim($link).'|', $url, $match)) {
1095
- $label = $options['internallinklabel'];
1096
- if ($label == '')
1097
- $label = 'int';
1098
- $trackBit = GA_Filter::ga_get_tracking_link($category.'-'.$label, $url,'');
1099
- }
1100
- }
1101
- }
1102
- }
1103
- if ($trackBit != "") {
1104
- if (preg_match('/onclick=[\'\"](.*?)[\'\"]/i', $matches[4]) > 0) {
1105
- // Check for manually tagged outbound clicks, and replace them with the tracking of choice.
1106
- if (preg_match('/.*_track(Pageview|Event).*/i', $matches[4]) > 0) {
1107
- $matches[4] = preg_replace('/onclick=[\'\"](javascript:)?(.*;)?[a-zA-Z0-9]+\._track(Pageview|Event)\([^\)]+\)(;)?(.*)?[\'\"]/i', 'onclick="javascript:' . $trackBit .'$2$5"', $matches[4]);
1108
- } else {
1109
- $matches[4] = preg_replace('/onclick=[\'\"](javascript:)?(.*?)[\'\"]/i', 'onclick="javascript:' . $trackBit .'$2"', $matches[4]);
1110
- }
1111
- } else {
1112
- $matches[4] = 'onclick="javascript:' . $trackBit . '"' . $matches[4];
1113
- }
1114
- }
1115
- return '<a ' . $matches[1] . 'href="' . $matches[2] . '//' . $matches[3] . '"' . ' ' . $matches[4] . '>' . $matches[5] . '</a>';
1116
- }
1117
-
1118
- function ga_parse_article_link($matches){
1119
- return GA_Filter::ga_parse_link('outbound-article',$matches);
1120
- }
1121
-
1122
- function ga_parse_comment_link($matches){
1123
- return GA_Filter::ga_parse_link('outbound-comment',$matches);
1124
- }
1125
-
1126
- function ga_parse_widget_link($matches){
1127
- return GA_Filter::ga_parse_link('outbound-widget',$matches);
1128
- }
1129
-
1130
- function widget_content($text) {
1131
- if ( !yoast_ga_do_tracking() )
1132
- return $text;
1133
- static $anchorPattern = '/<a (.*?)href=[\'\"](.*?)\/\/([^\'\"]+?)[\'\"](.*?)>(.*?)<\/a>/i';
1134
- $text = preg_replace_callback($anchorPattern,array('GA_Filter','ga_parse_widget_link'),$text);
1135
- return $text;
1136
- }
1137
-
1138
- function the_content($text) {
1139
- if ( !yoast_ga_do_tracking() )
1140
- return $text;
1141
-
1142
- if (!is_feed()) {
1143
- static $anchorPattern = '/<a (.*?)href=[\'\"](.*?)\/\/([^\'\"]+?)[\'\"](.*?)>(.*?)<\/a>/i';
1144
- $text = preg_replace_callback($anchorPattern,array('GA_Filter','ga_parse_article_link'),$text);
1145
- }
1146
- return $text;
1147
- }
1148
-
1149
- function comment_text($text) {
1150
- if ( !yoast_ga_do_tracking() )
1151
- return $text;
1152
-
1153
- if (!is_feed()) {
1154
- static $anchorPattern = '/<a (.*?)href="(.*?)\/\/(.*?)"(.*?)>(.*?)<\/a>/i';
1155
- $text = preg_replace_callback($anchorPattern,array('GA_Filter','ga_parse_comment_link'),$text);
1156
- }
1157
- return $text;
1158
- }
1159
-
1160
- function comment_author_link($text) {
1161
- $options = get_option('Yoast_Google_Analytics');
1162
-
1163
- if ( !yoast_ga_do_tracking() )
1164
- return $text;
1165
-
1166
- static $anchorPattern = '/(.*\s+.*?href\s*=\s*)["\'](.*?)["\'](.*)/';
1167
- preg_match($anchorPattern, $text, $matches);
1168
- if ($matches[2] == "") return $text;
1169
-
1170
- $trackBit = '';
1171
- $target = GA_Filter::ga_get_domain($matches[2]);
1172
- $origin = GA_Filter::ga_get_domain($_SERVER["HTTP_HOST"]);
1173
- if ( $target["domain"] != $origin["domain"] ){
1174
- if ( isset( $options['domainorurl'] ) && $options['domainorurl'] == "domain" )
1175
- $url = $target["host"];
1176
- else
1177
- $url = $matches[2];
1178
- $trackBit = 'onclick="'.GA_Filter::ga_get_tracking_link('outbound-commentauthor', $url).'"';
1179
- }
1180
- return $matches[1] . "\"" . $matches[2] . "\" " . $trackBit ." ". $matches[3];
1181
- }
1182
-
1183
- function bookmarks($bookmarks) {
1184
- if ( !yoast_ga_do_tracking() )
1185
- return $bookmarks;
1186
-
1187
- $i = 0;
1188
- while ( $i < count($bookmarks) ) {
1189
- $target = GA_Filter::ga_get_domain($bookmarks[$i]->link_url);
1190
- $sitedomain = GA_Filter::ga_get_domain(get_bloginfo('url'));
1191
- if ($target['host'] == $sitedomain['host']) {
1192
- $i++;
1193
- continue;
1194
- }
1195
- if ( isset( $options['domainorurl'] ) && $options['domainorurl'] == "domain" )
1196
- $url = $target["host"];
1197
- else
1198
- $url = $bookmarks[$i]->link_url;
1199
- $trackBit = '" onclick="'.GA_Filter::ga_get_tracking_link('outbound-blogroll', $url);
1200
- $bookmarks[$i]->link_target .= $trackBit;
1201
- $i++;
1202
- }
1203
- return $bookmarks;
1204
- }
1205
-
1206
- function rsslinktagger($guid) {
1207
- $options = get_option('Yoast_Google_Analytics');
1208
- global $wp, $post;
1209
- if ( is_feed() ) {
1210
- if ( $options['allowanchor'] ) {
1211
- $delimiter = '#';
1212
- } else {
1213
- $delimiter = '?';
1214
- if (strpos ( $guid, $delimiter ) > 0)
1215
- $delimiter = '&amp;';
1216
- }
1217
- return $guid . $delimiter . 'utm_source=rss&amp;utm_medium=rss&amp;utm_campaign='.urlencode($post->post_name);
1218
- }
1219
- }
1220
-
1221
- function wpec_transaction_tracking( $push ) {
1222
- global $wpdb, $purchlogs, $cart_log_id;
1223
- if( !isset( $cart_log_id ) || empty($cart_log_id) )
1224
- return $push;
1225
-
1226
- $city = $wpdb->get_var ("SELECT tf.value
1227
- FROM ".WPSC_TABLE_SUBMITED_FORM_DATA." tf
1228
- LEFT JOIN ".WPSC_TABLE_CHECKOUT_FORMS." cf
1229
- ON cf.id = tf.form_id
1230
- WHERE cf.type = 'city'
1231
- AND log_id = ".$cart_log_id );
1232
-
1233
- $country = $wpdb->get_var ("SELECT tf.value
1234
- FROM ".WPSC_TABLE_SUBMITED_FORM_DATA." tf
1235
- LEFT JOIN ".WPSC_TABLE_CHECKOUT_FORMS." cf
1236
- ON cf.id = tf.form_id
1237
- WHERE cf.type = 'country'
1238
- AND log_id = ".$cart_log_id );
1239
-
1240
- $cart_items = $wpdb->get_results ("SELECT * FROM ".WPSC_TABLE_CART_CONTENTS." WHERE purchaseid = ".$cart_log_id, ARRAY_A);
1241
-
1242
- $total_shipping = $purchlogs->allpurchaselogs[0]->base_shipping;
1243
- $total_tax = 0;
1244
- foreach ( $cart_items as $item ) {
1245
- $total_shipping += $item['pnp'];
1246
- $total_tax += $item['tax_charged'];
1247
- }
1248
-
1249
- $push[] = "'_addTrans','".$cart_log_id."'," // Order ID
1250
- ."'".GA_Filter::ga_str_clean(get_bloginfo('name'))."'," // Store name
1251
- ."'".nzshpcrt_currency_display($purchlogs->allpurchaselogs[0]->totalprice,1,true,false,true)."'," // Total price
1252
- ."'".nzshpcrt_currency_display($total_tax,1,true,false,true)."'," // Tax
1253
- ."'".nzshpcrt_currency_display($total_shipping,1,true,false,true)."'," // Shipping
1254
- ."'".$city."'," // City
1255
- ."''," // State
1256
- ."'".$country."'"; // Country
1257
-
1258
- foreach( $cart_items as $item ) {
1259
- $item['sku'] = $wpdb->get_var( "SELECT meta_value FROM ".WPSC_TABLE_PRODUCTMETA." WHERE meta_key = 'sku' AND product_id = '".$item['prodid']."' LIMIT 1" );
1260
-
1261
- $item['category'] = $wpdb->get_var( "SELECT pc.name FROM ".WPSC_TABLE_PRODUCT_CATEGORIES." pc LEFT JOIN ".WPSC_TABLE_ITEM_CATEGORY_ASSOC." ca ON pc.id = ca.category_id WHERE pc.group_id = '1' AND ca.product_id = '".$item['prodid']."'" );
1262
- $push[] = "'_addItem',"
1263
- ."'".$cart_log_id."'," // Order ID
1264
- ."'".$item['sku']."'," // Item SKU
1265
- ."'". str_replace( "'", "", $item['name'] ) ."'," // Item Name
1266
- ."'".$item['category']."'," // Item Category
1267
- ."'".$item['price']."'," // Item Price
1268
- ."'".$item['quantity']."'"; // Item Quantity
1269
- }
1270
- $push[] = "'_trackTrans'";
1271
-
1272
- return $push;
1273
- }
1274
-
1275
- function shopp_transaction_tracking( $push ) {
1276
- global $Shopp;
1277
-
1278
- // Only process if we're in the checkout process (receipt page)
1279
- if (version_compare(substr(SHOPP_VERSION,0,3),'1.1') >= 0) {
1280
- // Only process if we're in the checkout process (receipt page)
1281
- if (function_exists('is_shopp_page') && !is_shopp_page('checkout')) return $push;
1282
- if (empty($Shopp->Order->purchase)) return $push;
1283
-
1284
- $Purchase = new Purchase($Shopp->Order->purchase);
1285
- $Purchase->load_purchased();
1286
- } else {
1287
- // For 1.0.x
1288
- // Only process if we're in the checkout process (receipt page)
1289
- if (function_exists('is_shopp_page') && !is_shopp_page('checkout')) return $push;
1290
- // Only process if we have valid order data
1291
- if (!isset($Shopp->Cart->data->Purchase)) return $push;
1292
- if (empty($Shopp->Cart->data->Purchase->id)) return $push;
1293
-
1294
- $Purchase = $Shopp->Cart->data->Purchase;
1295
- }
1296
-
1297
- $push[] = "'_addTrans',"
1298
- ."'".$Purchase->id."'," // Order ID
1299
- ."'".GA_Filter::ga_str_clean(get_bloginfo('name'))."'," // Store
1300
- ."'".number_format($Purchase->total,2)."'," // Total price
1301
- ."'".number_format($Purchase->tax,2)."'," // Tax
1302
- ."'".number_format($Purchase->shipping,2)."'," // Shipping
1303
- ."'".$Purchase->city."'," // City
1304
- ."'".$Purchase->state."'," // State
1305
- ."'.$Purchase->country.'"; // Country
1306
-
1307
- foreach ($Purchase->purchased as $item) {
1308
- $sku = empty($item->sku) ? 'PID-'.$item->product.str_pad($item->price,4,'0',STR_PAD_LEFT) : $item->sku;
1309
- $push[] = "'_addItem',"
1310
- ."'".$Purchase->id."',"
1311
- ."'".$sku."',"
1312
- ."'". str_replace( "'", "", $item->name ) ."',"
1313
- ."'".$item->optionlabel."',"
1314
- ."'".number_format($item->unitprice,2)."',"
1315
- ."'".$item->quantity."'";
1316
- }
1317
- $push[] = "'_trackTrans'";
1318
- return $push;
1319
- }
1320
-
1321
- } // class GA_Filter
1322
- } // endif
1323
-
1324
- /**
1325
- * If setAllowAnchor is set to true, GA ignores all links tagged "normally", so we redirect all "normally" tagged URL's
1326
- * to one tagged with a hash.
1327
- */
1328
- function ga_utm_hashtag_redirect() {
1329
- if (isset($_SERVER['REQUEST_URI'])) {
1330
- if (strpos($_SERVER['REQUEST_URI'], "utm_") !== false) {
1331
- $url = 'http://';
1332
- if ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != "") {
1333
- $url = 'https://';
1334
- }
1335
- $url .= $_SERVER['SERVER_NAME'];
1336
- if ( strpos($_SERVER['REQUEST_URI'], "?utm_") !== false ) {
1337
- $url .= str_replace("?utm_","#utm_",$_SERVER['REQUEST_URI']);
1338
- } else if ( strpos($_SERVER['REQUEST_URI'], "&utm_") !== false ) {
1339
- $url .= substr_replace($_SERVER['REQUEST_URI'], "#utm_", strpos($_SERVER['REQUEST_URI'], "&utm_"), 5);
1340
- }
1341
- wp_redirect($url, 301);
1342
- exit;
1343
- }
1344
- }
1345
- }
1346
-
1347
- function yoast_ga_do_tracking() {
1348
- $current_user = wp_get_current_user();
1349
-
1350
- if (0 == $current_user->ID)
1351
- return true;
1352
-
1353
- $yoast_ga_options = get_option('Yoast_Google_Analytics');
1354
-
1355
- if ( ($current_user->user_level >= $yoast_ga_options["ignore_userlevel"]) )
1356
- return false;
1357
- else
1358
- return true;
1359
- }
1360
-
1361
- function track_comment_form_head() {
1362
- if (is_singular()) {
1363
- global $post;
1364
- $yoast_ga_options = get_option('Yoast_Google_Analytics');
1365
- if ( yoast_ga_do_tracking()
1366
- && isset( $yoast_ga_options["trackcommentform"] )
1367
- && $yoast_ga_options["trackcommentform"]
1368
- && ( 'open' == $post->comment_status ) )
1369
- wp_enqueue_script('jquery');
1370
- }
1371
- }
1372
- add_action('wp_print_scripts','track_comment_form_head');
1373
-
1374
- $comment_form_id = '';
1375
- function yoast_get_comment_form_id($args) {
1376
- global $comment_form_id;
1377
- $comment_form_id = $args['id_form'];
1378
- return $args;
1379
- }
1380
- add_filter('comment_form_defaults', 'yoast_get_comment_form_id',99,1);
1381
-
1382
- function yoast_track_comment_form() {
1383
- global $comment_form_id, $post;
1384
- $yoast_ga_options = get_option('Yoast_Google_Analytics');
1385
- if ( yoast_ga_do_tracking() && $yoast_ga_options["trackcommentform"] ) {
1386
- ?>
1387
- <script type="text/javascript">
1388
- jQuery(document).ready(function() {
1389
- jQuery('#<?php echo $comment_form_id; ?>').submit(function() {
1390
- _gaq.push(
1391
- ['_setAccount','<?php echo $yoast_ga_options["uastring"]; ?>'],
1392
- ['_trackEvent','comment']
1393
- );
1394
- });
1395
- });
1396
- </script>
1397
- <?php
1398
- }
1399
- }
1400
- add_action('comment_form_after','yoast_track_comment_form');
1401
- /*
1402
- function gfform_tag() {
1403
- $options = get_option('Yoast_Google_Analytics');
1404
- if ( isset( $options['taggfsubmit'] ) && $options['taggfsubmit'] ) {
1405
- $title = GA_Filter::ga_str_clean( $form['title'] );
1406
- if ($options['gfsubmiteventpv'] == 'events') {
1407
- $pv = "['_trackEvent','gf_form_submit','".$title."']";
1408
- } else {
1409
- $pv = "['_trackPageview','".GA_Filter::ga_get_tracking_prefix()."gf-form-submit/".$title."']";
1410
- }
1411
- }
1412
- wp_enqueue_script('jquery');
1413
- ?>
1414
- <script type="text/javascript">
1415
- jQuery(document).ready(function() {
1416
- jQuery('.gform_wrapper form').submit(function() {
1417
- _gaq.push(<?php echo $pv; ?>);
1418
- });
1419
- });
1420
- </script>
1421
- <?php
1422
- }
1423
- add_action('wp_footer','gfform_tag',10);
1424
- */
1425
-
1426
- function yoast_sanitize_relative_links($content) {
1427
- preg_match("|^http(s)?://([^/]+)|i", get_bloginfo('url'), $match);
1428
- $content = preg_replace("/<a([^>]*) href=('|\")\/([^\"']*)('|\")/", "<a\${1} href=\"" .$match[0] ."/" ."\${3}\"", $content);
1429
-
1430
- if (is_singular()) {
1431
- $content = preg_replace("/<a([^>]*) href=('|\")#([^\"']*)('|\")/", "<a\${1} href=\"" .get_permalink()."#" ."\${3}\"", $content);
1432
- }
1433
- return $content;
1434
- }
1435
- add_filter('the_content', 'yoast_sanitize_relative_links', 98);
1436
- add_filter('widget_text', 'yoast_sanitize_relative_links', 98);
1437
-
1438
- function yoast_analytics() {
1439
- $options = get_option('Yoast_Google_Analytics');
1440
- if ($options['position'] == 'manual')
1441
- GA_Filter::spool_analytics();
1442
- else
1443
- echo '<!-- Please set Google Analytics position to "manual" in the settings, or remove this call to yoast_analytics(); -->';
1444
- }
1445
-
1446
- $gaf = new GA_Filter();
1447
- $options = get_option('Yoast_Google_Analytics');
1448
-
1449
- if (!is_array($options)) {
1450
- $options = get_option('GoogleAnalyticsPP');
1451
- if (!is_array($options)) {
1452
- $ga_admin->set_defaults();
1453
- } else {
1454
- delete_option('GoogleAnalyticsPP');
1455
- if ($options['admintracking']) {
1456
- $options["ignore_userlevel"] = '8';
1457
- unset($options['admintracking']);
1458
- } else {
1459
- $options["ignore_userlevel"] = '11';
1460
- }
1461
- update_option('Yoast_Google_Analytics', $options);
1462
- }
1463
- } else {
1464
- if ( isset( $options['allowanchor'] ) && $options['allowanchor'] ) {
1465
- add_action('init','ga_utm_hashtag_redirect',1);
1466
- }
1467
-
1468
- if ( isset( $options['trackoutbound'] ) && $options['trackoutbound'] ) {
1469
- // filters alter the existing content
1470
- add_filter('the_content', array('GA_Filter','the_content'), 99);
1471
- add_filter('widget_text', array('GA_Filter','widget_content'), 99);
1472
- add_filter('the_excerpt', array('GA_Filter','the_content'), 99);
1473
- add_filter('comment_text', array('GA_Filter','comment_text'), 99);
1474
- add_filter('get_bookmarks', array('GA_Filter','bookmarks'), 99);
1475
- add_filter('get_comment_author_link', array('GA_Filter','comment_author_link'), 99);
1476
- }
1477
-
1478
- if ( isset( $options['trackadsense'] ) && $options['trackadsense'] )
1479
- add_action('wp_head', array('GA_Filter','spool_adsense'),1);
1480
-
1481
- if ( !isset( $options['position'] ) )
1482
- $options['position'] = 'header';
1483
-
1484
- switch ($options['position']) {
1485
- case 'manual':
1486
- // No need to insert here, bail NOW.
1487
- break;
1488
- case 'header':
1489
- default:
1490
- add_action('wp_head', array('GA_Filter','spool_analytics'),2);
1491
- break;
1492
- }
1493
-
1494
- if ( isset( $options['trackregistration'] ) && $options['trackregistration'] )
1495
- add_action('login_head', array('GA_Filter','spool_analytics'),20);
1496
-
1497
- if ( isset( $options['rsslinktagging'] ) && $options['rsslinktagging'] )
1498
- add_filter ( 'the_permalink_rss', array('GA_Filter','rsslinktagger'), 99 );
1499
-
1500
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Google Analytics for WordPress
4
+ Plugin URI: http://yoast.com/wordpress/google-analytics/#utm_source=wordpress&utm_medium=plugin&utm_campaign=google-analytics-for-wordpress&utm_content=v420
5
+ Description: This plugin makes it simple to add Google Analytics to your WordPress blog, adding lots of features, eg. custom variables and automatic clickout and download tracking.
6
+ Author: Joost de Valk
7
+ Version: 4.2
8
+ Requires at least: 2.8
9
+ Author URI: http://yoast.com/
10
+ License: GPL
11
+ */
12
+
13
+ // This plugin was originally based on Rich Boakes' Analytics plugin: http://boakes.org/analytics
14
+
15
+ define('GAWP_VERSION', '4.2');
16
+
17
+ /*
18
+ * Admin User Interface
19
+ */
20
+
21
+ if ( is_admin() && ( !defined('DOING_AJAX') || !DOING_AJAX ) && !class_exists( 'GA_Admin' ) ) {
22
+
23
+ require_once plugin_dir_path( __FILE__ ) . 'yst_plugin_tools.php';
24
+ require_once plugin_dir_path( __FILE__ ) . '/wp-gdata/wp-gdata.php';
25
+
26
+ class GA_Admin extends Yoast_GA_Plugin_Admin {
27
+
28
+ var $hook = 'google-analytics-for-wordpress';
29
+ var $filename = 'google-analytics-for-wordpress/googleanalytics.php';
30
+ var $longname = 'Google Analytics Configuration';
31
+ var $shortname = 'Google Analytics';
32
+ var $ozhicon = 'images/chart_curve.png';
33
+ var $optionname = 'Yoast_Google_Analytics';
34
+ var $homepage = 'http://yoast.com/wordpress/google-analytics/';
35
+ var $toc = '';
36
+
37
+ /**
38
+ * PHP4 Constructor
39
+ */
40
+ function GA_Admin() {
41
+ $this->__construct();
42
+ }
43
+
44
+ /**
45
+ * Constructur, load all required stuff.
46
+ */
47
+ function __construct() {
48
+ $this->upgrade();
49
+
50
+ $this->plugin_url = plugins_url( '', __FILE__ ).'/';
51
+
52
+ // Register the settings page
53
+ add_action( 'admin_menu', array(&$this, 'register_settings_page') );
54
+
55
+ // Register the contextual help for the settings page
56
+ add_action( 'contextual_help', array(&$this, 'plugin_help'), 10, 3 );
57
+
58
+ // Give the settings page a nice icon in Ozh's menu
59
+ add_filter( 'ozh_adminmenu_icon', array(&$this, 'add_ozh_adminmenu_icon' ) );
60
+
61
+ // Give the plugin a settings link in the plugin overview
62
+ add_filter( 'plugin_action_links', array(&$this, 'add_action_link'), 10, 2 );
63
+
64
+ // Print Scripts and Styles
65
+ add_action('admin_print_scripts', array(&$this, 'config_page_scripts') );
66
+ add_action('admin_print_styles', array(&$this, 'config_page_styles') );
67
+
68
+ // Setup the dashboard news widget
69
+ add_action('wp_dashboard_setup', array(&$this, 'widget_setup') );
70
+
71
+ // Print stuff in the settings page's head
72
+ add_action('admin_head', array(&$this, 'config_page_head') );
73
+
74
+ // Drop a warning on each page of the admin when Google Analytics hasn't been configured
75
+ add_action('admin_footer', array(&$this, 'warning') );
76
+
77
+ // Save settings
78
+ // TODO: replace with Options API
79
+ add_action('admin_init', array(&$this, 'save_settings') );
80
+
81
+ // Authenticate
82
+ add_action('admin_init', array(&$this, 'authenticate') );
83
+ }
84
+
85
+ function config_page_head() {
86
+ global $current_screen;
87
+ if ( 'settings_page_'.$this->hook == $current_screen->id ) {
88
+ $options = get_option( $this->optionname );
89
+ if (!empty($options['uastring'])) {
90
+ $uastring = $options['uastring'];
91
+ } else {
92
+ $uastring = '';
93
+ }
94
+
95
+ ?>
96
+ <script type="text/javascript">
97
+ function makeSublist(parent,child,childVal) {
98
+ jQuery("body").append("<select style='display:none' id='"+parent+child+"'></select>");
99
+ jQuery('#'+parent+child).html(jQuery("#"+child+" option"));
100
+
101
+ var parentValue = jQuery('#'+parent).val();
102
+ jQuery('#'+child).html(jQuery("#"+parent+child+" .sub_"+parentValue).clone());
103
+
104
+ childVal = (typeof childVal == "undefined")? "" : childVal ;
105
+ jQuery("#"+child).val(childVal).attr('selected','selected');
106
+
107
+ jQuery('#'+parent).change(function(){
108
+ var parentValue = jQuery('#'+parent).val();
109
+ jQuery('#'+child).html(jQuery("#"+parent+child+" .sub_"+parentValue).clone());
110
+ jQuery('#'+child).trigger("change");
111
+ jQuery('#'+child).focus();
112
+ });
113
+ }
114
+ jQuery(document).ready(function(){
115
+ makeSublist('ga_account', 'uastring_sel', '<?php echo $uastring; ?>');
116
+ jQuery('#position').change(function(){
117
+ if (jQuery('#position').val() == 'header') {
118
+ jQuery('#position_header').css("display","block");
119
+ jQuery('#position_manual').css("display","none");
120
+ } else {
121
+ jQuery('#position_header').css("display","none");
122
+ jQuery('#position_manual').css("display","block");
123
+ }
124
+ }).change();
125
+ jQuery('#switchtomanual').change(function() {
126
+ if ( jQuery('#switchtomanual').is(':checked') ) {
127
+ jQuery('#uastring_manual').css('display','block');
128
+ jQuery('#uastring_automatic').css('display','none');
129
+ } else {
130
+ jQuery('#uastring_manual').css('display','none');
131
+ jQuery('#uastring_automatic').css('display','block');
132
+ }
133
+ }).change();
134
+ jQuery('#trackoutbound').change(function(){
135
+ if ( jQuery('#trackoutbound').is(':checked') ) {
136
+ jQuery('#internallinktracking').css("display","block");
137
+ jQuery('.internallinktracking').css("display","list-item");
138
+ } else {
139
+ jQuery('#internallinktracking').css("display","none");
140
+ jQuery('.internallinktracking').css("display","none");
141
+ }
142
+ }).change();
143
+ jQuery('#advancedsettings').change(function(){
144
+ if ( jQuery('#advancedsettings').is(':checked') ) {
145
+ jQuery('#advancedgasettings').css("display","block");
146
+ jQuery('#customvarsettings').css("display","block");
147
+ jQuery('.advancedgasettings').css("display","list-item");
148
+ jQuery('.customvarsettings').css("display","list-item");
149
+ } else {
150
+ jQuery('#advancedgasettings').css("display","none");
151
+ jQuery('#customvarsettings').css("display","none");
152
+ jQuery('.advancedgasettings').css("display","none");
153
+ jQuery('.customvarsettings').css("display","none");
154
+ }
155
+ }).change();
156
+ jQuery('#extrase').change(function(){
157
+ if ( jQuery('#extrase').is(':checked') ) {
158
+ jQuery('#extrasebox').css("display","block");
159
+ } else {
160
+ jQuery('#extrasebox').css("display","none");
161
+ }
162
+ }).change();
163
+ jQuery('#gajslocalhosting').change(function(){
164
+ if ( jQuery('#gajslocalhosting').is(':checked') ) {
165
+ jQuery('#localhostingbox').css("display","block");
166
+ } else {
167
+ jQuery('#localhostingbox').css("display","none");
168
+ }
169
+ }).change();
170
+ jQuery('#customvarsettings :input').change(function() {
171
+ if (jQuery("#customvarsettings :input:checked").size() > 5) {
172
+ alert("<?php _e('The maximum number of allowed custom variables in Google Analytics is 5, please unselect one of the other custom variables before selecting this one.'); ?>");
173
+ jQuery(this).attr('checked', false);
174
+ };
175
+ });
176
+ jQuery('#uastring').change(function(){
177
+ if ( jQuery('#switchtomanual').is(':checked') ) {
178
+ if (!jQuery(this).val().match(/^UA-[\d-]+$/)) {
179
+ alert("<?php _e('That\'s not a valid UA ID, please make sure it matches the expected pattern of: UA-XXXXXX-X, and that there are no spaces or other characters in the input field.'); ?>");
180
+ jQuery(this).focus();
181
+ }
182
+ }
183
+ });
184
+ });
185
+ </script>
186
+ <link rel="shortcut icon" href="<?php echo $this->plugin_url; ?>images/favicon.ico" />
187
+ <?php
188
+ }
189
+ }
190
+
191
+ function plugin_help($contextual_help, $screen_id, $screen) {
192
+ if ( $screen_id == 'settings_page_'.$this->hook ) {
193
+
194
+ $contextual_help = '<h2>'.__('Having problems?').'</h2>'.
195
+ '<p>'.sprintf( __("If you're having problems with this plugin, please refer to its <a href='%s'>FAQ page</a>."), 'http://yoast.com/wordpress/google-analytics/ga-wp-faq/' ).'</p>';
196
+ }
197
+ return $contextual_help;
198
+ }
199
+
200
+ function toc( $modules ) {
201
+ $output = '<ul>';
202
+ foreach ($modules as $module => $key) {
203
+ $output .= '<li class="'.$key.'"><a href="#'.$key.'">'.$module.'</a></li>';
204
+ }
205
+ $output .= '</ul>';
206
+ return $output;
207
+ }
208
+
209
+ function save_settings() {
210
+ $options = get_option( $this->optionname );
211
+
212
+ if ( isset($_REQUEST['reset']) && $_REQUEST['reset'] == "true" && isset($_REQUEST['plugin']) && $_REQUEST['plugin'] == 'google-analytics-for-wordpress') {
213
+ $options = $this->set_defaults();
214
+ $options['msg'] = "<div class=\"updated\"><p>".__('Google Analytics settings reset.')."</p></div>\n";
215
+ } elseif ( isset($_POST['submit']) && isset($_POST['plugin']) && $_POST['plugin'] == 'google-analytics-for-wordpress') {
216
+ if (!current_user_can('manage_options')) die(__('You cannot edit the Google Analytics for WordPress options.'));
217
+ check_admin_referer('analyticspp-config');
218
+
219
+ foreach (array('uastring', 'dlextensions', 'domainorurl','position','domain', 'customcode', 'ga_token', 'extraseurl', 'gajsurl', 'gfsubmiteventpv', 'trackprefix', 'ignore_userlevel', 'internallink', 'internallinklabel', 'primarycrossdomain', 'othercrossdomains') as $option_name) {
220
+ if (isset($_POST[$option_name]))
221
+ $options[$option_name] = $_POST[$option_name];
222
+ else
223
+ $options[$option_name] = '';
224
+ }
225
+
226
+ foreach (array('extrase', 'trackoutbound', 'admintracking', 'trackadsense', 'allowanchor', 'allowlinker', 'allowhash', 'rsslinktagging', 'advancedsettings', 'trackregistration', 'theme_updated', 'cv_loggedin', 'cv_authorname', 'cv_category', 'cv_all_categories', 'cv_tags', 'cv_year', 'cv_post_type', 'outboundpageview', 'downloadspageview', 'trackcrossdomain','gajslocalhosting', 'manual_uastring', 'taggfsubmit', 'wpec_tracking', 'shopp_tracking', 'anonymizeip', 'trackcommentform', 'debug','firebuglite', 'disable_pagespeed_tracking') as $option_name) {
227
+ if (isset($_POST[$option_name]) && $_POST[$option_name] != 'off')
228
+ $options[$option_name] = true;
229
+ else
230
+ $options[$option_name] = false;
231
+ }
232
+
233
+ if (isset($_POST['manual_uastring']) && isset($_POST['uastring_man'])) {
234
+ $options['uastring'] = $_POST['uastring_man'];
235
+ }
236
+
237
+ if ( $options['trackcrossdomain'] ) {
238
+ if ( !$options['allowlinker'] )
239
+ $options['allowlinker'] = true;
240
+
241
+ if ( empty($options['primarycrossdomain']) ) {
242
+ $origin = GA_Filter::ga_get_domain($_SERVER["HTTP_HOST"]);
243
+ $options['primarycrossdomain'] = $origin["domain"];
244
+ }
245
+ }
246
+
247
+ $cache = '';
248
+ if ( function_exists('w3tc_pgcache_flush') ) {
249
+ w3tc_pgcache_flush();
250
+ w3tc_dbcache_flush();
251
+ w3tc_minify_flush();
252
+ w3tc_objectcache_flush();
253
+ $cache = ' and <strong>W3TC Caches cleared</strong>';
254
+ } else if ( function_exists('wp_cache_clear_cache') ) {
255
+ wp_cache_clear_cache();
256
+ $cache = ' and <strong>WP Super Cache cleared</strong>';
257
+ }
258
+
259
+ $options['msg'] = "<div id=\"updatemessage\" class=\"updated fade\"><p>Google Analytics <strong>settings updated</strong>$cache.</p></div>\n";
260
+ $options['msg'] .= "<script type=\"text/javascript\">setTimeout(function(){jQuery('#updatemessage').hide('slow');}, 3000);</script>";
261
+ }
262
+ update_option($this->optionname, $options);
263
+ }
264
+
265
+ function save_button() {
266
+ return '<div class="alignright"><input type="submit" class="button-primary" name="submit" value="'.__('Update Google Analytics Settings &raquo;').'" /></div><br class="clear"/>';
267
+ }
268
+
269
+ function upgrade() {
270
+ $options = get_option($this->optionname);
271
+ if ( isset($options['version']) && $options['version'] < '4.04' ) {
272
+ if ( !isset($options['ignore_userlevel']) || $options['ignore_userlevel'] == '')
273
+ $options['ignore_userlevel'] = 11;
274
+ }
275
+ if ( !isset($options['version']) || $options['version'] != GAWP_VERSION ) {
276
+ $options['version'] = GAWP_VERSION;
277
+ }
278
+ update_option($this->optionname, $options);
279
+ }
280
+
281
+ function config_page() {
282
+ $options = get_option($this->optionname);
283
+ if ( isset($options['msg']) )
284
+ echo $options['msg'];
285
+ $options['msg'] = '';
286
+ update_option($this->optionname, $options);
287
+
288
+ if ( !isset($options['uastring']) )
289
+ $options = $this->set_defaults();
290
+ $modules = array();
291
+
292
+ ?>
293
+ <div class="wrap">
294
+ <a href="http://yoast.com/"><div id="yoast-icon" style="background: url(<?php echo $this->plugin_url; ?>images/ga-icon-32x32.png) no-repeat;" class="icon32"><br /></div></a>
295
+ <h2><?php _e("Google Analytics for WordPress Configuration") ?></h2>
296
+ <div class="postbox-container" style="width:65%;">
297
+ <div class="metabox-holder">
298
+ <div class="meta-box-sortables">
299
+ <form action="<?php echo $this->plugin_options_url(); ?>" method="post" id="analytics-conf">
300
+ <input type="hidden" name="plugin" value="google-analytics-for-wordpress"/>
301
+ <?php
302
+ wp_nonce_field('analyticspp-config');
303
+
304
+ if ( empty($options['uastring']) && empty($options['ga_token']) ) {
305
+ $query = $this->plugin_options_url().'&reauth=true';
306
+ $line = 'Please authenticate with Google Analytics to retrieve your tracking code:<br/><br/> <a class="button-primary" href="'.$query.'">Click here to authenticate with Google</a><br/><br/><strong>Note</strong>: if you have multiple Google accounts, you\'ll want to switch to the right account first, since Google doesn\'t let you switch accounts on the authentication screen.';
307
+ } else if(isset($options['ga_token']) && !empty($options['ga_token'])) {
308
+ $token = $options['ga_token'];
309
+
310
+ require_once plugin_dir_path(__FILE__).'xmlparser.php';
311
+ if (file_exists(ABSPATH.'wp-includes/class-http.php'))
312
+ require_once(ABSPATH.'wp-includes/class-http.php');
313
+
314
+ if (!isset($options['ga_api_responses'][$token])) {
315
+ $options['ga_api_responses'] = array();
316
+
317
+ if ( $oauth = $options['gawp_oauth'] ) {
318
+ if ( isset( $oauth['params']['oauth_token'], $oauth['params']['oauth_token_secret'] ) ) {
319
+ $options['gawp_oauth']['access_token'] = array(
320
+ 'oauth_token' => base64_decode( $oauth['params']['oauth_token'] ),
321
+ 'oauth_token_secret' => base64_decode( $oauth['params']['oauth_token_secret'] )
322
+ );
323
+ unset( $options['gawp_oauth']['params'] );
324
+ update_option( $this->optionname, $options );
325
+ }
326
+ }
327
+
328
+ $args = array(
329
+ 'scope' => 'https://www.google.com/analytics/feeds/',
330
+ 'xoauth_displayname' => 'Google Analytics for WordPress by Yoast'
331
+ );
332
+ $access_token = $options['gawp_oauth']['access_token'];
333
+ $gdata = new WP_Gdata( $args, $access_token['oauth_token'], $access_token['oauth_token_secret'] );
334
+
335
+
336
+ $response = $gdata->get( 'https://www.google.com/analytics/feeds/accounts/default' );
337
+ $http_code = wp_remote_retrieve_response_code( $response );
338
+ $response = wp_remote_retrieve_body( $response );
339
+
340
+
341
+ if($http_code==200)
342
+ {
343
+ $options['ga_api_responses'][$token] = array(
344
+ 'response'=>array('code'=>$http_code),
345
+ 'body'=>$response
346
+ );
347
+ $options['ga_token'] = $token;
348
+ update_option('Yoast_Google_Analytics', $options);
349
+ }
350
+ }
351
+
352
+ if (is_array($options['ga_api_responses'][$token]) && $options['ga_api_responses'][$token]['response']['code'] == 200) {
353
+ $arr = yoast_xml2array($options['ga_api_responses'][$token]['body']);
354
+
355
+ $ga_accounts = array();
356
+ if (isset($arr['feed']['entry'][0])) {
357
+ foreach ($arr['feed']['entry'] as $site) {
358
+ $ua = $site['dxp:property']['3_attr']['value'];
359
+ $account = $site['dxp:property']['1_attr']['value'];
360
+ if (!isset($ga_accounts[$account]) || !is_array($ga_accounts[$account]))
361
+ $ga_accounts[$account] = array();
362
+ $ga_accounts[$account][$site['title']] = $ua;
363
+ }
364
+ } else {
365
+ $ua = $arr['feed']['entry']['dxp:property']['3_attr']['value'];
366
+ $account = $arr['feed']['entry']['dxp:property']['1_attr']['value'];
367
+ $title = $arr['feed']['entry']['title'];
368
+ if (!isset($ga_accounts[$account]) || !is_array($ga_accounts[$account]))
369
+ $ga_accounts[$account] = array();
370
+ $ga_accounts[$account][$title] = $ua;
371
+ }
372
+
373
+ $select1 = '<select style="width:150px;" name="ga_account" id="ga_account">';
374
+ $select1 .= "\t<option></option>\n";
375
+ $select2 = '<select style="width:150px;" name="uastring" id="uastring_sel">';
376
+ $i = 1;
377
+ $currentua = '';
378
+ if (!empty($options['uastring']))
379
+ $currentua = $options['uastring'];
380
+
381
+ foreach($ga_accounts as $account => $val) {
382
+ $accountsel = false;
383
+ foreach ($val as $title => $ua) {
384
+ $sel = selected($ua, $currentua, false);
385
+ if (!empty($sel)) {
386
+ $accountsel = true;
387
+ }
388
+ $select2 .= "\t".'<option class="sub_'.$i.'" '.$sel.' value="'.$ua.'">'.$title.' - '.$ua.'</option>'."\n";
389
+ }
390
+ $select1 .= "\t".'<option '.selected($accountsel,true,false).' value="'.$i.'">'.$account.'</option>'."\n";
391
+ $i++;
392
+ }
393
+ $select1 .= '</select>';
394
+ $select2 .= '</select>';
395
+
396
+ $line = '<input type="hidden" name="ga_token" value="'.$token.'"/>';
397
+ $line .= 'Please select the correct Analytics profile to track:<br/>';
398
+ $line .= '<table class="form_table">';
399
+ $line .= '<tr><th width="15%">Account:</th><td width="85%">'.$select1.'</td></tr>';
400
+ $line .= '<tr><th>Profile:</th><td>'.$select2.'</td></tr>';
401
+ $line .= '</table>';
402
+
403
+ $try = 1;
404
+ if (isset($_GET['try']))
405
+ $try = $_GET['try'] + 1;
406
+
407
+ if ($i == 1 && $try < 4 && isset($_GET['token'])) {
408
+ $line .= '<script type="text/javascript">
409
+ window.location="'.$this->plugin_options_url().'&switchua=1&token='.$token.'&try='.$try.'";
410
+ </script>';
411
+ }
412
+ $line .= 'Please note that if you have several profiles of the same website, it doesn\'t matter which profile you select, and in fact another profile might show as selected later. You can check whether they\'re profiles for the same site by checking if they have the same UA code. If that\'s true, tracking will be correct.<br/>';
413
+ $line .= '<br/>Refresh this listing or switch to another account: ';
414
+ } else {
415
+ $line = 'Unfortunately, an error occurred while connecting to Google, please try again:';
416
+ }
417
+
418
+ $query = $this->plugin_options_url().'&reauth=true';
419
+ $line .= '<a class="button" href="'.$query.'">Re-authenticate with Google</a>';
420
+ } else {
421
+ $line = '<input id="uastring" name="uastring" type="text" size="20" maxlength="40" value="'.$options['uastring'].'"/><br/><a href="'.$this->plugin_options_url().'&amp;switchua=1">Select another Analytics Profile &raquo;</a>';
422
+ }
423
+ $line = '<div id="uastring_automatic">'.$line.'</div><div style="display:none;" id="uastring_manual">Manually enter your UA code: <input id="uastring" name="uastring_man" type="text" size="20" maxlength="40" value="'.$options['uastring'].'"/></div>';
424
+ $rows = array();
425
+ $content = '';
426
+ $rows[] = array(
427
+ 'id' => 'uastring',
428
+ 'label' => 'Analytics Profile',
429
+ 'desc' => '<input type="checkbox" name="manual_uastring" '.checked($options['manual_uastring'], true, false).' id="switchtomanual"/> <label for="switchtomanual">Manually enter your UA code</label>',
430
+ 'content' => $line
431
+ );
432
+ $temp_content = $this->select('position', array('header' => 'In the header (default)', 'manual' => 'Insert manually'));
433
+ if ($options['theme_updated'] && $options['position'] == 'manual') {
434
+ $temp_content .= '<input type="hidden" name="theme_updated" value="off"/>';
435
+ echo '<div id="message" class="updated" style="background-color:lightgreen;border-color:green;"><p><strong>Notice:</strong> You switched your theme, please make sure your Google Analytics tracking is still ok. Save your settings to make sure Google Analytics gets loaded properly.</p></div>';
436
+ remove_action('admin_footer', array(&$this,'theme_switch_warning'));
437
+ }
438
+ $desc = '<div id="position_header">The header is by far the best spot to place the tracking code. If you\'d rather place the code manually, switch to manual placement. For more info <a href="http://yoast.com/wordpress/google-analytics/manual-placement/">read this page</a>.</div>';
439
+ $desc .= '<div id="position_manual"><a href="http://yoast.com/wordpress/google-analytics/manual-placement/">Follow the instructions here</a> to choose the location for your tracking code manually.</div>';
440
+
441
+ $rows[] = array(
442
+ 'id' => 'position',
443
+ 'label' => 'Where should the tracking code be placed',
444
+ 'desc' => $desc,
445
+ 'content' => $temp_content,
446
+ );
447
+ $rows[] = array(
448
+ 'id' => 'trackoutbound',
449
+ 'label' => 'Track outbound clicks &amp; downloads',
450
+ 'desc' => 'Clicks &amp; downloads will be tracked as events, you can find these under Content &raquo; Event Tracking in your Google Analytics reports.',
451
+ 'content' => $this->checkbox('trackoutbound'),
452
+ );
453
+ $rows[] = array(
454
+ 'id' => 'advancedsettings',
455
+ 'label' => 'Show advanced settings',
456
+ 'desc' => 'Only adviced for advanced users who know their way around Google Analytics',
457
+ 'content' => $this->checkbox('advancedsettings'),
458
+ );
459
+ $this->postbox('gasettings','Google Analytics Settings',$this->form_table($rows).$this->save_button());
460
+
461
+ $rows = array();
462
+ $pre_content = '<p>Google Analytics allows you to save up to 5 custom variables on each page, and this plugin helps you make the most use of these! Check which custom variables you\'d like the plugin to save for you below. Please note that these will only be saved when they are actually available.</p><p>If you want to start using these custom variables, go to Visitors &raquo; Custom Variables in your Analytics reports.</p>';
463
+ $rows[] = array(
464
+ 'id' => 'cv_loggedin',
465
+ 'label' => 'Logged in Users',
466
+ 'desc' => 'Allows you to easily remove logged in users from your reports, or to segment by different user roles. The users primary role will be logged.',
467
+ 'content' => $this->checkbox('cv_loggedin'),
468
+ );
469
+ $rows[] = array(
470
+ 'id' => 'cv_post_type',
471
+ 'label' => 'Post type',
472
+ 'desc' => 'Allows you to see pageviews per post type, especially useful if you use multiple custom post types.',
473
+ 'content' => $this->checkbox('cv_post_type'),
474
+ );
475
+ $rows[] = array(
476
+ 'id' => 'cv_authorname',
477
+ 'label' => 'Author Name',
478
+ 'desc' => 'Allows you to see pageviews per author.',
479
+ 'content' => $this->checkbox('cv_authorname'),
480
+ );
481
+ $rows[] = array(
482
+ 'id' => 'cv_tags',
483
+ 'label' => 'Tags',
484
+ 'desc' => 'Allows you to see pageviews per tags using advanced segments.',
485
+ 'content' => $this->checkbox('cv_tags'),
486
+ );
487
+ $rows[] = array(
488
+ 'id' => 'cv_year',
489
+ 'label' => 'Publication year',
490
+ 'desc' => 'Allows you to see pageviews per year of publication, showing you if your old posts still get traffic.',
491
+ 'content' => $this->checkbox('cv_year'),
492
+ );
493
+ $rows[] = array(
494
+ 'id' => 'cv_category',
495
+ 'label' => 'Single Category',
496
+ 'desc' => 'Allows you to see pageviews per category, works best when each post is in only one category.',
497
+ 'content' => $this->checkbox('cv_category'),
498
+ );
499
+ $rows[] = array(
500
+ 'id' => 'cv_all_categories',
501
+ 'label' => 'All Categories',
502
+ 'desc' => 'Allows you to see pageviews per category using advanced segments, should be used when you use multiple categories per post.',
503
+ 'content' => $this->checkbox('cv_all_categories'),
504
+ );
505
+
506
+ $modules['Custom Variables'] = 'customvarsettings';
507
+ $this->postbox('customvarsettings','Custom Variables Settings',$pre_content.$this->form_table($rows).$this->save_button());
508
+
509
+ $rows = array();
510
+ $rows[] = array(
511
+ 'id' => 'ignore_userlevel',
512
+ 'label' => 'Ignore users',
513
+ 'desc' => 'Users of the role you select and higher will be ignored, so if you select Editor, all Editors and Administrators will be ignored.',
514
+ 'content' => $this->select('ignore_userlevel', array(
515
+ '11' => 'Ignore no-one',
516
+ '8' => 'Administrator',
517
+ '5' => 'Editor',
518
+ '2' => 'Author',
519
+ '1' => 'Contributor',
520
+ '0' => 'Subscriber (ignores all logged in users)',
521
+ )),
522
+ );
523
+ $rows[] = array(
524
+ 'id' => 'outboundpageview',
525
+ 'label' => 'Track outbound clicks as pageviews',
526
+ 'desc' => 'You do not need to enable this to enable outbound click tracking, this changes the default behavior of tracking clicks as events to tracking them as pageviews. This is therefore not recommended, as this would skew your statistics, but <em>is</em> sometimes necessary when you need to set outbound clicks as goals.',
527
+ 'content' => $this->checkbox('outboundpageview'),
528
+ );
529
+ $rows[] = array(
530
+ 'id' => 'downloadspageview',
531
+ 'label' => 'Track downloads as pageviews',
532
+ 'desc' => 'Not recommended, as this would skew your statistics, but it does make it possible to track downloads as goals.',
533
+ 'content' => $this->checkbox('downloadspageview'),
534
+ );
535
+ $rows[] = array(
536
+ 'id' => 'dlextensions',
537
+ 'label' => 'Extensions of files to track as downloads',
538
+ 'content' => $this->textinput('dlextensions'),
539
+ );
540
+ if ( $options['outboundpageview'] ) {
541
+ $rows[] = array(
542
+ 'id' => 'trackprefix',
543
+ 'label' => 'Prefix to use in Analytics before the tracked pageviews',
544
+ 'desc' => 'This prefix is used before all pageviews, they are then segmented automatically after that. If nothing is entered here, <code>/yoast-ga/</code> is used.',
545
+ 'content' => $this->textinput('trackprefix'),
546
+ );
547
+ }
548
+ $rows[] = array(
549
+ 'id' => 'domainorurl',
550
+ 'label' => 'Track full URL of outbound clicks or just the domain',
551
+ 'content' => $this->select('domainorurl', array(
552
+ 'domain' => 'Just the domain',
553
+ 'url' => 'Track the complete URL',
554
+ )
555
+ ),
556
+ );
557
+ $rows[] = array(
558
+ 'id' => 'domain',
559
+ 'label' => 'Subdomain Tracking',
560
+ 'desc' => 'This allows you to set the domain that\'s set by <a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setDomainName"><code>setDomainName</code></a> for tracking subdomains, if empty this will not be set.',
561
+ 'content' => $this->textinput('domain'),
562
+ );
563
+ $rows[] = array(
564
+ 'id' => 'trackcrossdomain',
565
+ 'label' => 'Enable Cross Domain Tracking',
566
+ 'desc' => 'This allows you to enable <a href="http://code.google.com/apis/analytics/docs/tracking/gaTrackingSite.html">Cross-Domain Tracking</a> for this site. When endabled <code>_setAllowLinker:</code> will be enabled if it is not already.',
567
+ 'content' => $this->checkbox('trackcrossdomain'),
568
+ );
569
+ $rows[] = array(
570
+ 'id' => 'primarycrossdomain',
571
+ 'label' => 'Cross-Domain Tracking, Primary Domain',
572
+ 'desc' => 'Set the primary domain used in <a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setDomainName"><code>setDomainName</code></a> for cross domain tracking (eg. <code>example-petstore.com</code> ), if empty this will default to your configured Home URL.',
573
+ 'content' => $this->textinput('primarycrossdomain'),
574
+ );
575
+ $rows[] = array(
576
+ 'id' => 'othercrossdomains',
577
+ 'label' => 'Cross-Domain Tracking, Other Domains',
578
+ 'desc' => 'All links to these domains will have the <a href="http://code.google.com/apis/analytics/docs/tracking/gaTrackingSite.html#multipleDomains"><code>_link</code></a> code automatically attached. Separate domains/sub-domains with commas (eg. <code>dogs.example-petstore.com, cats.example-petstore.com</code>)',
579
+ 'content' => $this->textinput('othercrossdomains'),
580
+ );
581
+ $rows[] = array(
582
+ 'id' => 'disable_pagespeed_tracking',
583
+ 'label' => 'Disable Site Speed tracking',
584
+ 'desc' => 'This disables the Site Speed tracking feature of Google Analytics that is enabled by default in this plugin.',
585
+ 'content' => $this->checkbox('disable_pagespeed_tracking'),
586
+ );
587
+ $rows[] = array(
588
+ 'id' => 'customcode',
589
+ 'label' => 'Custom Code',
590
+ 'desc' => 'Not for the average user: this allows you to add a line of code, to be added before the <code>trackPageview</code> call.',
591
+ 'content' => $this->textinput('customcode'),
592
+ );
593
+ $rows[] = array(
594
+ 'id' => 'trackadsense',
595
+ 'label' => 'Track AdSense',
596
+ 'desc' => 'This requires integration of your Analytics and AdSense account, for help, <a href="http://google.com/support/analytics/bin/answer.py?answer=92625">look here</a>.',
597
+ 'content' => $this->checkbox('trackadsense'),
598
+ );
599
+ $rows[] = array(
600
+ 'id' => 'gajslocalhosting',
601
+ 'label' => 'Host ga.js locally',
602
+ 'content' => $this->checkbox('gajslocalhosting').'<div id="localhostingbox">
603
+ You have to provide a URL to your ga.js file:
604
+ <input type="text" name="gajsurl" size="30" value="'.$options['gajsurl'].'"/>
605
+ </div>',
606
+ 'desc' => 'For some reasons you might want to use a locally hosted ga.js file, or another ga.js file, check the box and then please enter the full URL including http here.'
607
+ );
608
+ $rows[] = array(
609
+ 'id' => 'extrase',
610
+ 'label' => 'Track extra Search Engines',
611
+ 'content' => $this->checkbox('extrase').'<div id="extrasebox">
612
+ You can provide a custom URL to the extra search engines file if you want:
613
+ <input type="text" name="extraseurl" size="30" value="'.$options['extraseurl'].'"/>
614
+ </div>',
615
+ );
616
+ $rows[] = array(
617
+ 'id' => 'rsslinktagging',
618
+ 'label' => 'Tag links in RSS feed with campaign variables',
619
+ 'desc' => 'Do not use this feature if you use FeedBurner, as FeedBurner can do this automatically, and better than this plugin can. Check <a href="http://www.google.com/support/feedburner/bin/answer.py?hl=en&amp;answer=165769">this help page</a> for info on how to enable this feature in FeedBurner.',
620
+ 'content' => $this->checkbox('rsslinktagging'),
621
+ );
622
+ $rows[] = array(
623
+ 'id' => 'trackregistration',
624
+ 'label' => 'Add tracking to the login and registration forms',
625
+ 'content' => $this->checkbox('trackregistration'),
626
+ );
627
+ $rows[] = array(
628
+ 'id' => 'trackcommentform',
629
+ 'label' => 'Add tracking to the comment forms',
630
+ 'content' => $this->checkbox('trackcommentform'),
631
+ );
632
+ $rows[] = array(
633
+ 'id' => 'allowanchor',
634
+ 'label' => 'Use # instead of ? for Campaign tracking',
635
+ 'desc' => 'This adds a <code><a href="http://code.google.com/apis/analytics/docs/gaJSApiCampaignTracking.html#_gat.GA_Tracker_._setAllowAnchor">_setAllowAnchor</a></code> call to your tracking code, and makes RSS link tagging use a # as well.',
636
+ 'content' => $this->checkbox('allowanchor'),
637
+ );
638
+ $rows[] = array(
639
+ 'id' => 'allowlinker',
640
+ 'label' => 'Add <code>_setAllowLinker</code>',
641
+ 'desc' => 'This adds a <code><a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setAllowLinker">_setAllowLinker</a></code> call to your tracking code, allowing you to use <code>_link</code> and related functions.',
642
+ 'content' => $this->checkbox('allowlinker'),
643
+ );
644
+ $rows[] = array(
645
+ 'id' => 'allowhash',
646
+ 'label' => 'Set <code>_setAllowHash</code> to false',
647
+ 'desc' => 'This sets <code><a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setAllowHash">_setAllowHash</a></code> to false, allowing you to track subdomains etc.',
648
+ 'content' => $this->checkbox('allowhash'),
649
+ );
650
+ $rows[] = array(
651
+ 'id' => 'anonymizeip',
652
+ 'label' => 'Anonymize IP\'s',
653
+ 'desc' => 'This adds <code><a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_gat._anonymizeIp">_anonymizeIp</a></code>, telling Google Analytics to anonymize the information sent by the tracker objects by removing the last octet of the IP address prior to its storage.',
654
+ 'content' => $this->checkbox('anonymizeip'),
655
+ );
656
+ $modules['Advanced Settings'] = 'advancedgasettings';
657
+ $this->postbox('advancedgasettings','Advanced Settings',$this->form_table($rows).$this->save_button());
658
+
659
+ $rows = array();
660
+ $rows[] = array(
661
+ 'id' => 'internallink',
662
+ 'label' => 'Internal links to track as outbound',
663
+ 'desc' => 'If you want to track all internal links that begin with <code>/out/</code>, enter <code>/out/</code> in the box above. If you have multiple prefixes you can separate them with comma\'s: <code>/out/,/recommends/</code>',
664
+ 'content' => $this->textinput('internallink'),
665
+ );
666
+ $rows[] = array(
667
+ 'id' => 'internallinklabel',
668
+ 'label' => 'Label to use',
669
+ 'desc' => 'The label to use for these links, this will be added to where the click came from, so if the label is "aff", the label for a click from the content of an article becomes "outbound-article-aff".',
670
+ 'content' => $this->textinput('internallinklabel'),
671
+ );
672
+ $modules['Internal Link Tracking'] = 'internallinktracking';
673
+ $this->postbox('internallinktracking','Internal Links to Track as Outbound',$this->form_table($rows).$this->save_button());
674
+
675
+ /* if (class_exists('RGForms') && GFCommon::$version >= '1.3.11') {
676
+ $pre_content = 'This plugin can automatically tag your Gravity Forms to track form submissions as either events or pageviews';
677
+ $rows = array();
678
+ $rows[] = array(
679
+ 'id' => 'taggfsubmit',
680
+ 'label' => 'Tag Gravity Forms',
681
+ 'content' => $this->checkbox('taggfsubmit'),
682
+ );
683
+ $rows[] = array(
684
+ 'id' => 'gfsubmiteventpv',
685
+ 'label' => 'Tag Gravity Forms as',
686
+ 'content' => '<select name="gfsubmiteventpv">
687
+ <option value="events" '.selected($options['gfsubmiteventpv'],'events',false).'>Events</option>
688
+ <option value="pageviews" '.selected($options['gfsubmiteventpv'],'pageviews',false).'>Pageviews</option>
689
+ </select>',
690
+ );
691
+ $this->postbox('gravityforms','Gravity Forms Settings',$pre_content.$this->form_table($rows).$this->save_button());
692
+ $modules['Gravity Forms'] = 'gravityforms';
693
+ }
694
+ */
695
+ if ( defined('WPSC_VERSION') ) {
696
+ $pre_content = 'The WordPress e-Commerce plugin has been detected. This plugin can automatically add transaction tracking for you. To do that, <a href="http://yoast.com/wordpress/google-analytics/enable-ecommerce/">enable e-commerce for your reports in Google Analytics</a> and then check the box below.';
697
+ $rows = array();
698
+ $rows[] = array(
699
+ 'id' => 'wpec_tracking',
700
+ 'label' => 'Enable transaction tracking',
701
+ 'content' => $this->checkbox('wpec_tracking'),
702
+ );
703
+ $this->postbox('wpecommerce','WordPress e-Commerce Settings',$pre_content.$this->form_table($rows).$this->save_button());
704
+ $modules['WordPress e-Commerce'] = 'wpecommerce';
705
+ }
706
+
707
+ global $Shopp;
708
+ if ( isset($Shopp) ) {
709
+ $pre_content = 'The Shopp e-Commerce plugin has been detected. This plugin can automatically add transaction tracking for you. To do that, <a href="http://www.google.com/support/googleanalytics/bin/answer.py?hl=en&amp;answer=55528">enable e-commerce for your reports in Google Analytics</a> and then check the box below.';
710
+ $rows = array();
711
+ $rows[] = array(
712
+ 'id' => 'shopp_tracking',
713
+ 'label' => 'Enable transaction tracking',
714
+ 'content' => $this->checkbox('shopp_tracking'),
715
+ );
716
+ $this->postbox('shoppecommerce','Shopp e-Commerce Settings',$pre_content.$this->form_table($rows).$this->save_button());
717
+ $modules['Shopp'] = 'shoppecommerce';
718
+ }
719
+ $pre_content = '<p>If you want to confirm that tracking on your blog is working as it should, enable this option and check the console in <a href="http://getfirebug.com/">Firebug</a> (for Firefox), <a href="http://getfirebug.com/firebuglite">Firebug Lite</a> (for other browsers) or Chrome &amp; Safari\'s Web Inspector. Be absolutely sure to disable debugging afterwards, as it is slower than normal tracking.</p><p><strong>Note</strong>: the debugging and firebug scripts are only loaded for admins.</p>';
720
+ $rows = array();
721
+ $rows[] = array(
722
+ 'id' => 'debug',
723
+ 'label' => 'Enable debug mode',
724
+ 'content' => $this->checkbox('debug'),
725
+ );
726
+ $rows[] = array(
727
+ 'id' => 'firebuglite',
728
+ 'label' => 'Enable Firebug Lite',
729
+ 'content' => $this->checkbox('firebuglite'),
730
+ );
731
+ $this->postbox('debugmode','Debug Mode',$pre_content.$this->form_table($rows).$this->save_button());
732
+ $modules['Debug Mode'] = 'debugmode';
733
+ ?>
734
+ </form>
735
+ <form action="<?php echo $this->plugin_options_url(); ?>" method="post" onsubmit="javascript:return(confirm('Do you really want to reset all settings?'));">
736
+ <input type="hidden" name="reset" value="true"/>
737
+ <input type="hidden" name="plugin" value="google-analytics-for-wordpress"/>
738
+ <div class="submit"><input type="submit" value="Reset All Settings &raquo;" /></div>
739
+ </form>
740
+ </div>
741
+ </div>
742
+ </div>
743
+ <div class="postbox-container side" style="width:20%;">
744
+ <div class="metabox-holder">
745
+ <div class="meta-box-sortables">
746
+ <?php
747
+ if ( count($modules) > 0 )
748
+ $this->postbox('toc','List of Available Modules',$this->toc($modules));
749
+ $this->plugin_like();
750
+ $this->postbox('donate','<strong class="red">Donate $10, $20 or $50!</strong>','<p>This plugin has cost me countless hours of work, if you use it, please donate a token of your appreciation!</p><br/><form style="margin-left:50px;" action="https://www.paypal.com/cgi-bin/webscr" method="post">
751
+ <input type="hidden" name="cmd" value="_s-xclick">
752
+ <input type="hidden" name="hosted_button_id" value="FW9FK4EBZ9FVJ">
753
+ <input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
754
+ <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
755
+ </form>');
756
+ $this->plugin_support();
757
+ $this->news();
758
+ ?>
759
+ </div>
760
+ <br/><br/><br/>
761
+ </div>
762
+ </div>
763
+ </div>
764
+ <?php
765
+ }
766
+
767
+ function set_defaults() {
768
+ $options = array(
769
+ 'advancedsettings' => false,
770
+ 'allowanchor' => false,
771
+ 'allowhash' => false,
772
+ 'allowlinker' => false,
773
+ 'anonymizeip' => false,
774
+ 'customcode' => '',
775
+ 'cv_loggedin' => false,
776
+ 'cv_authorname' => false,
777
+ 'cv_category' => false,
778
+ 'cv_all_categories' => false,
779
+ 'cv_tags' => false,
780
+ 'cv_year' => false,
781
+ 'cv_post_type' => false,
782
+ 'debug' => false,
783
+ 'dlextensions' => 'doc,exe,js,pdf,ppt,tgz,zip,xls',
784
+ 'domain' => '',
785
+ 'domainorurl' => 'domain',
786
+ 'extrase' => false,
787
+ 'extraseurl' => '',
788
+ 'firebuglite' => false,
789
+ 'ga_token' => '',
790
+ 'ga_api_responses' => array(),
791
+ 'gajslocalhosting' => false,
792
+ 'gajsurl' => '',
793
+ 'ignore_userlevel' => '11',
794
+ 'internallink' => false,
795
+ 'internallinklabel' => '',
796
+ 'outboundpageview' => false,
797
+ 'downloadspageview' => false,
798
+ 'othercrossdomains' => '',
799
+ 'position' => 'footer',
800
+ 'primarycrossdomain' => '',
801
+ 'theme_updated' => false,
802
+ 'trackcommentform' => true,
803
+ 'trackcrossdomain' => false,
804
+ 'trackadsense' => false,
805
+ 'trackoutbound' => true,
806
+ 'trackregistration' => false,
807
+ 'rsslinktagging' => true,
808
+ 'uastring' => '',
809
+ 'version' => GAWP_VERSION,
810
+ );
811
+ update_option($this->optionname,$options);
812
+ return $options;
813
+ }
814
+
815
+ function warning() {
816
+ $options = get_option($this->optionname);
817
+ if (!isset($options['uastring']) || empty($options['uastring'])) {
818
+ echo "<div id='message' class='error'><p><strong>Google Analytics is not active.</strong> You must <a href='".$this->plugin_options_url()."'>select which Analytics Profile to track</a> before it can work.</p></div>";
819
+ }
820
+ } // end warning()
821
+
822
+
823
+ function authenticate() {
824
+ if ( isset( $_REQUEST['oauth_token'] ) ) {
825
+ $o = get_option( $this->optionname );
826
+ if ( isset( $o['gawp_oauth']['oauth_token'] ) && $o['gawp_oauth']['oauth_token'] !== $_REQUEST['oauth_token'] ) {
827
+ $o['gawp_oauth']['oauth_token'] = '';
828
+ } else {
829
+ $gdata = new WP_GData(
830
+ array(
831
+ 'scope' => 'https://www.google.com/analytics/feeds/',
832
+ 'xoauth_displayname' => 'Google Analytics for WordPress by Yoast'
833
+ ),
834
+ $o['gawp_oauth']['oauth_token'],
835
+ $o['gawp_oauth']['oauth_token_secret']
836
+ );
837
+
838
+ $o['gawp_oauth']['access_token'] = $gdata->get_access_token( $_REQUEST['oauth_verifier'] );
839
+ unset( $o['gawp_oauth']['oauth_token'] );
840
+ unset( $o['gawp_oauth']['oauth_token_secret'] );
841
+ $o['ga_token'] = $o['gawp_oauth']['access_token']['oauth_token'];
842
+ }
843
+
844
+ update_option( $this->optionname, $o );
845
+
846
+ wp_redirect( menu_page_url( $this->hook, false ) );
847
+ exit;
848
+ }
849
+
850
+ if ( ! empty( $_GET['reauth'] ) ) {
851
+ $gdata = new WP_GData(
852
+ array(
853
+ 'scope' => 'https://www.google.com/analytics/feeds/',
854
+ 'xoauth_displayname' => 'Google Analytics for WordPress by Yoast'
855
+ )
856
+ );
857
+
858
+ $request_token = $gdata->get_request_token( menu_page_url( 'google-analytics-for-wordpress', false ) );
859
+
860
+ $options = get_option( $this->optionname );
861
+ unset( $options['ga_token'] );
862
+ unset( $options['gawp_oauth']['access_token'] );
863
+ $options['gawp_oauth']['oauth_token'] = $request_token['oauth_token'];
864
+ $options['gawp_oauth']['oauth_token_secret'] = $request_token['oauth_token_secret'];
865
+ update_option( $this->optionname, $options );
866
+
867
+ wp_redirect( $gdata->get_authorize_url( $request_token ) );
868
+ exit;
869
+ }
870
+
871
+ } //end reauthenticate()
872
+ } // end class GA_Admin
873
+
874
+ $ga_admin = new GA_Admin();
875
+ } //endif
876
+
877
+
878
+ /**
879
+ * Code that actually inserts stuff into pages.
880
+ */
881
+ if ( ! class_exists( 'GA_Filter' ) ) {
882
+ class GA_Filter {
883
+
884
+ /**
885
+ * Cleans the variable to make it ready for storing in Google Analytics
886
+ */
887
+ function ga_str_clean($val) {
888
+ return remove_accents(str_replace('---','-',str_replace(' ','-',strtolower(html_entity_decode($val)))));
889
+ }
890
+ /*
891
+ * Insert the tracking code into the page
892
+ */
893
+ function spool_analytics() {
894
+ global $wp_query;
895
+ // echo '<!--'.print_r($wp_query,1).'-->';
896
+
897
+ $options = get_option('Yoast_Google_Analytics');
898
+
899
+ if ( !isset($options['uastring']) || $options['uastring'] == '' ) {
900
+ if ( current_user_can('manage_options') )
901
+ echo "<!-- Google Analytics tracking code not shown because yo haven't chosen a Google Analytics account yet. -->\n";
902
+ return;
903
+ }
904
+
905
+ /**
906
+ * The order of custom variables is very, very important: custom vars should always take up the same slot to make analysis easy.
907
+ */
908
+ $customvarslot = 1;
909
+ if ( yoast_ga_do_tracking() && !is_preview() ) {
910
+ $push = array();
911
+
912
+ if ( $options['allowanchor'] )
913
+ $push[] = "'_setAllowAnchor',true";
914
+
915
+ if ( $options['allowlinker'] )
916
+ $push[] = "'_setAllowLinker',true";
917
+
918
+ if ( $options['anonymizeip'] )
919
+ $push[] = "'_gat._anonymizeIp'";
920
+
921
+ if ( isset($options['domain']) && $options['domain'] != "" )
922
+ $push[] = "'_setDomainName','".$options['domain']."'";
923
+
924
+ if ( $options['trackcrossdomain'] )
925
+ $push[] = "'_setDomainName','".$options['primarycrossdomain']."'";
926
+
927
+ if ( $options['allowhash'] )
928
+ $push[] = "'_setAllowHash',false";
929
+
930
+ if ( $options['cv_loggedin'] ) {
931
+ $current_user = wp_get_current_user();
932
+ if ( $current_user && $current_user->ID != 0 )
933
+ $push[] = "'_setCustomVar',$customvarslot,'logged-in','".$current_user->roles[0]."',1";
934
+ // Customvar slot needs to be upped even when the user is not logged in, to make sure the variables below are always in the same slot.
935
+ $customvarslot++;
936
+ }
937
+
938
+ if ( function_exists('is_post_type_archive') && is_post_type_archive() ) {
939
+ if ( $options['cv_post_type'] ) {
940
+ $post_type = get_post_type();
941
+ if ( $post_type ) {
942
+ $push[] = "'_setCustomVar',".$customvarslot.",'post_type','".$post_type."',3";
943
+ $customvarslot++;
944
+ }
945
+ }
946
+ } else if ( is_singular() && !is_home() ) {
947
+ if ( $options['cv_post_type'] ) {
948
+ $post_type = get_post_type();
949
+ if ( $post_type ) {
950
+ $push[] = "'_setCustomVar',".$customvarslot.",'post_type','".$post_type."',3";
951
+ $customvarslot++;
952
+ }
953
+ }
954
+ if ( $options['cv_authorname'] ) {
955
+ $push[] = "'_setCustomVar',$customvarslot,'author','".GA_Filter::ga_str_clean(get_the_author_meta('display_name',$wp_query->post->post_author))."',3";
956
+ $customvarslot++;
957
+ }
958
+ if ( $options['cv_tags'] ) {
959
+ $i = 0;
960
+ if ( get_the_tags() ) {
961
+ $tagsstr = '';
962
+ foreach ( get_the_tags() as $tag ) {
963
+ if ($i > 0)
964
+ $tagsstr .= ' ';
965
+ $tagsstr .= $tag->slug;
966
+ $i++;
967
+ }
968
+ // Max 64 chars for value and label combined, hence 64 - 4
969
+ $tagsstr = substr($tagsstr, 0, 60);
970
+ $push[] = "'_setCustomVar',$customvarslot,'tags','".$tagsstr."',3";
971
+ }
972
+ $customvarslot++;
973
+ }
974
+ if ( is_singular() ) {
975
+ if ( $options['cv_year'] ) {
976
+ $push[] = "'_setCustomVar',$customvarslot,'year','".get_the_time('Y')."',3";
977
+ $customvarslot++;
978
+ }
979
+ if ( $options['cv_category'] && is_single() ) {
980
+ $cats = get_the_category();
981
+ if ( is_array( $cats ) && isset( $cats[0] ) )
982
+ $push[] = "'_setCustomVar',$customvarslot,'category','".$cats[0]->slug."',3";
983
+ $customvarslot++;
984
+ }
985
+ if ( $options['cv_all_categories'] && is_single() ) {
986
+ $i = 0;
987
+ $catsstr = '';
988
+ foreach ( (array) get_the_category() as $cat ) {
989
+ if ($i > 0)
990
+ $catsstr .= ' ';
991
+ $catsstr .= $cat->slug;
992
+ $i++;
993
+ }
994
+ // Max 64 chars for value and label combined, hence 64 - 10
995
+ $catsstr = substr($catsstr, 0, 54);
996
+ $push[] = "'_setCustomVar',$customvarslot,'categories','".$catsstr."',3";
997
+ $customvarslot++;
998
+ }
999
+ }
1000
+ }
1001
+
1002
+ $push = apply_filters('yoast-ga-custom-vars',$push, $customvarslot);
1003
+
1004
+ $push = apply_filters('yoast-ga-push-before-pageview',$push);
1005
+
1006
+ if ( is_404() ) {
1007
+ $push[] = "'_trackPageview','/404.html?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer";
1008
+ } else if ($wp_query->is_search) {
1009
+ $pushstr = "'_trackPageview','".get_bloginfo('url')."/?s=";
1010
+ if ($wp_query->found_posts == 0) {
1011
+ $push[] = $pushstr."no-results:".rawurlencode($wp_query->query_vars['s'])."&cat=no-results'";
1012
+ } else if ($wp_query->found_posts == 1) {
1013
+ $push[] = $pushstr.rawurlencode($wp_query->query_vars['s'])."&cat=1-result'";
1014
+ } else if ($wp_query->found_posts > 1 && $wp_query->found_posts < 6) {
1015
+ $push[] = $pushstr.rawurlencode($wp_query->query_vars['s'])."&cat=2-5-results'";
1016
+ } else {
1017
+ $push[] = $pushstr.rawurlencode($wp_query->query_vars['s'])."&cat=plus-5-results'";
1018
+ }
1019
+ } else {
1020
+ $push[] = "'_trackPageview'";
1021
+ }
1022
+
1023
+ if ( !isset( $options['disable_pagespeed_tracking'] ) || !$options['disable_pagespeed_tracking'] ) {
1024
+ $push[] = "'_trackPageLoadTime'";
1025
+ }
1026
+
1027
+ $push = apply_filters('yoast-ga-push-after-pageview',$push);
1028
+
1029
+ if ( defined('WPSC_VERSION') && $options['wpec_tracking'] )
1030
+ $push = GA_Filter::wpec_transaction_tracking($push);
1031
+
1032
+ if ($options['shopp_tracking']) {
1033
+ global $Shopp;
1034
+ if ( isset($Shopp) )
1035
+ $push = GA_Filter::shopp_transaction_tracking($push);
1036
+ }
1037
+
1038
+ $pushstr = "";
1039
+ foreach ($push as $key) {
1040
+ if (!empty($pushstr))
1041
+ $pushstr .= ",";
1042
+
1043
+ $pushstr .= "[".$key."]";
1044
+ }
1045
+
1046
+ if ( current_user_can('manage_options') && $options['firebuglite'] && $options['debug'] )
1047
+ echo '<script src="https://getfirebug.com/firebug-lite.js" type="text/javascript"></script>';
1048
+ ?>
1049
+
1050
+ <script type="text/javascript">//<![CDATA[
1051
+ // Google Analytics for WordPress by Yoast v<?php echo GAWP_VERSION; ?> | http://yoast.com/wordpress/google-analytics/
1052
+ var _gaq = _gaq || [];
1053
+ _gaq.push(['_setAccount','<?php echo trim($options["uastring"]); ?>']);
1054
+ <?php
1055
+ if ( $options["extrase"] ) {
1056
+ if ( !empty($options["extraseurl"]) ) {
1057
+ $url = $options["extraseurl"];
1058
+ } else {
1059
+ $url = plugins_url( 'custom_se_async.js', __FILE__ );
1060
+ }
1061
+ echo '</script><script src="'.$url.'" type="text/javascript"></script>'."\n".'<script type="text/javascript">';
1062
+ }
1063
+
1064
+ if ( $options['customcode'] && trim( $options['customcode'] ) != '' )
1065
+ echo "\t". stripslashes( $options['customcode'] ) ."\n";
1066
+ ?>
1067
+ _gaq.push(<?php echo $pushstr; ?>);
1068
+ (function() {
1069
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
1070
+ ga.src = <?php
1071
+ if ( $options['gajslocalhosting'] && !empty($options['gajsurl']) ) {
1072
+ echo "'".$options['gajsurl']."';";
1073
+ } else {
1074
+ $script = 'ga.js';
1075
+ if ( current_user_can('manage_options') && $options['debug'] )
1076
+ $script = 'u/ga_debug.js';
1077
+ echo "('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/".$script."';";
1078
+ }
1079
+ ?>
1080
+
1081
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
1082
+ })();
1083
+ //]]></script>
1084
+ <?php
1085
+ } else if ( $options["uastring"] != "" ) {
1086
+ echo "<!-- Google Analytics tracking code not shown because users over level ".$options["ignore_userlevel"]." are ignored -->\n";
1087
+ }
1088
+ }
1089
+
1090
+ /*
1091
+ * Insert the AdSense parameter code into the page. This'll go into the header per Google's instructions.
1092
+ */
1093
+ function spool_adsense() {
1094
+ $options = get_option('Yoast_Google_Analytics');
1095
+ if ( $options["uastring"] != "" && yoast_ga_do_tracking() && !is_preview() ) {
1096
+ echo '<script type="text/javascript">'."\n";
1097
+ echo "\t".'window.google_analytics_uacct = "'.$options["uastring"].'";'."\n";
1098
+ echo '</script>'."\n";
1099
+ }
1100
+ }
1101
+
1102
+ function ga_get_tracking_prefix() {
1103
+ $options = get_option('Yoast_Google_Analytics');
1104
+ return (empty($options['trackprefix'])) ? '/yoast-ga/' : $options['trackprefix'];
1105
+ }
1106
+
1107
+ function ga_get_tracking_link($prefix, $target, $jsprefix = 'javascript:') {
1108
+ $options = get_option('Yoast_Google_Analytics');
1109
+ if (
1110
+ ( $prefix != 'download' && $options['outboundpageview'] ) ||
1111
+ ( $prefix == 'download' && $options['downloadspageview'] ) )
1112
+ {
1113
+ $prefix = GA_Filter::ga_get_tracking_prefix().$prefix;
1114
+ $pushstr = "['_trackPageview','".$prefix."/". esc_js( esc_url( $target ) )."']";
1115
+ } else {
1116
+ $pushstr = "['_trackEvent','".$prefix."','".esc_js( esc_url( $target ) )."']";
1117
+ }
1118
+ return $jsprefix."_gaq.push(".$pushstr.");";
1119
+ }
1120
+
1121
+ function ga_get_domain($uri){
1122
+ $hostPattern = "/^(http:\/\/)?([^\/]+)/i";
1123
+ $domainPatternUS = "/[^\.\/]+\.[^\.\/]+$/";
1124
+ $domainPatternUK = "/[^\.\/]+\.[^\.\/]+\.[^\.\/]+$/";
1125
+
1126
+ preg_match($hostPattern, $uri, $matches);
1127
+ $host = $matches[2];
1128
+ if (preg_match("/.*\..*\..*\..*$/",$host))
1129
+ preg_match($domainPatternUK, $host, $matches);
1130
+ else
1131
+ preg_match($domainPatternUS, $host, $matches);
1132
+
1133
+ return array("domain"=>$matches[0],"host"=>$host);
1134
+ }
1135
+
1136
+ function ga_parse_link($category, $matches){
1137
+ $origin = GA_Filter::ga_get_domain($_SERVER["HTTP_HOST"]);
1138
+ $options = get_option('Yoast_Google_Analytics');
1139
+
1140
+ // Break out immediately if the link is not an http or https link.
1141
+ if (strpos($matches[2],"http") !== 0) {
1142
+ $target = false;
1143
+ } else if ((strpos($matches[2],"mailto") === 0)) {
1144
+ $target = 'email';
1145
+ } else {
1146
+ $target = GA_Filter::ga_get_domain($matches[3]);
1147
+ }
1148
+ $trackBit = "";
1149
+ $extension = substr(strrchr($matches[3], '.'), 1);
1150
+ $dlextensions = explode(",",str_replace('.','',$options['dlextensions']));
1151
+ if ( $target ) {
1152
+ if ( $target == 'email' ) {
1153
+ $trackBit = GA_Filter::ga_get_tracking_link('mailto', str_replace('mailto:','',$matches[3]),'');
1154
+ } else if ( in_array($extension, $dlextensions) ) {
1155
+ $trackBit = GA_Filter::ga_get_tracking_link('download', $matches[3],'');
1156
+ } else if ( $target["domain"] != $origin["domain"] ){
1157
+ $crossdomains = explode(',',str_replace(' ','',$options['othercrossdomains']));
1158
+ if ( $options['trackcrossdomain'] && in_array($target["host"],$crossdomains) ) {
1159
+ $trackBit = '_gaq.push([\'_link\', \'' . $matches[2] . '//' . $matches[3] . '\']); return false;"';
1160
+ } else if ( $options['trackoutbound'] && in_array($options['domainorurl'], array('domain','url')) ) {
1161
+ $url = $options['domainorurl'] == 'domain' ? $target["host"] : $matches[3];
1162
+ $trackBit = GA_Filter::ga_get_tracking_link($category, $url,'');
1163
+ }
1164
+ $trackBit = GA_Filter::ga_get_tracking_link($category, $url,'');
1165
+ } else if ( $target["domain"] == $origin["domain"] && isset($options['internallink']) && $options['internallink'] != '') {
1166
+ $url = preg_replace('|'.$origin["host"].'|','',$matches[3]);
1167
+ $extintlinks = explode(',',$options['internallink']);
1168
+ foreach ($extintlinks as $link) {
1169
+ if (preg_match('|^'.trim($link).'|', $url, $match)) {
1170
+ $label = $options['internallinklabel'];
1171
+ if ($label == '')
1172
+ $label = 'int';
1173
+ $trackBit = GA_Filter::ga_get_tracking_link($category.'-'.$label, $url,'');
1174
+ }
1175
+ }
1176
+ }
1177
+ }
1178
+ if ($trackBit != "") {
1179
+ if (preg_match('/onclick=[\'\"](.*?)[\'\"]/i', $matches[4]) > 0) {
1180
+ // Check for manually tagged outbound clicks, and replace them with the tracking of choice.
1181
+ if (preg_match('/.*_track(Pageview|Event).*/i', $matches[4]) > 0) {
1182
+ $matches[4] = preg_replace('/onclick=[\'\"](javascript:)?(.*;)?[a-zA-Z0-9]+\._track(Pageview|Event)\([^\)]+\)(;)?(.*)?[\'\"]/i', 'onclick="javascript:' . $trackBit .'$2$5"', $matches[4]);
1183
+ } else {
1184
+ $matches[4] = preg_replace('/onclick=[\'\"](javascript:)?(.*?)[\'\"]/i', 'onclick="javascript:' . $trackBit .'$2"', $matches[4]);
1185
+ }
1186
+ } else {
1187
+ $matches[4] = 'onclick="javascript:' . $trackBit . '"' . $matches[4];
1188
+ }
1189
+ }
1190
+ return '<a ' . $matches[1] . 'href="' . $matches[2] . '//' . $matches[3] . '"' . ' ' . $matches[4] . '>' . $matches[5] . '</a>';
1191
+ }
1192
+
1193
+ function ga_parse_article_link($matches){
1194
+ return GA_Filter::ga_parse_link('outbound-article',$matches);
1195
+ }
1196
+
1197
+ function ga_parse_comment_link($matches){
1198
+ return GA_Filter::ga_parse_link('outbound-comment',$matches);
1199
+ }
1200
+
1201
+ function ga_parse_widget_link($matches){
1202
+ return GA_Filter::ga_parse_link('outbound-widget',$matches);
1203
+ }
1204
+
1205
+ function ga_parse_nav_menu($matches){
1206
+ return GA_Filter::ga_parse_link('outbound-menu',$matches);
1207
+ }
1208
+
1209
+ function widget_content($text) {
1210
+ if ( !yoast_ga_do_tracking() )
1211
+ return $text;
1212
+ static $anchorPattern = '/<a (.*?)href=[\'\"](.*?)\/\/([^\'\"]+?)[\'\"](.*?)>(.*?)<\/a>/i';
1213
+ $text = preg_replace_callback($anchorPattern,array('GA_Filter','ga_parse_widget_link'),$text);
1214
+ return $text;
1215
+ }
1216
+
1217
+ function the_content($text) {
1218
+ if ( !yoast_ga_do_tracking() )
1219
+ return $text;
1220
+
1221
+ if (!is_feed()) {
1222
+ static $anchorPattern = '/<a (.*?)href=[\'\"](.*?)\/\/([^\'\"]+?)[\'\"](.*?)>(.*?)<\/a>/i';
1223
+ $text = preg_replace_callback($anchorPattern,array('GA_Filter','ga_parse_article_link'),$text);
1224
+ }
1225
+ return $text;
1226
+ }
1227
+
1228
+ function nav_menu($text) {
1229
+ if ( !yoast_ga_do_tracking() )
1230
+ return $text;
1231
+
1232
+ if (!is_feed()) {
1233
+ static $anchorPattern = '/<a (.*?)href=[\'\"](.*?)\/\/([^\'\"]+?)[\'\"](.*?)>(.*?)<\/a>/i';
1234
+ $text = preg_replace_callback($anchorPattern,array('GA_Filter','ga_parse_nav_menu'),$text);
1235
+ }
1236
+ return $text;
1237
+ }
1238
+
1239
+ function comment_text($text) {
1240
+ if ( !yoast_ga_do_tracking() )
1241
+ return $text;
1242
+
1243
+ if (!is_feed()) {
1244
+ static $anchorPattern = '/<a (.*?)href="(.*?)\/\/(.*?)"(.*?)>(.*?)<\/a>/i';
1245
+ $text = preg_replace_callback($anchorPattern,array('GA_Filter','ga_parse_comment_link'),$text);
1246
+ }
1247
+ return $text;
1248
+ }
1249
+
1250
+ function comment_author_link($text) {
1251
+ $options = get_option('Yoast_Google_Analytics');
1252
+
1253
+ if ( !yoast_ga_do_tracking() )
1254
+ return $text;
1255
+
1256
+ static $anchorPattern = '/(.*\s+.*?href\s*=\s*)["\'](.*?)["\'](.*)/';
1257
+ preg_match($anchorPattern, $text, $matches);
1258
+ if ($matches[2] == "") return $text;
1259
+
1260
+ $trackBit = '';
1261
+ $target = GA_Filter::ga_get_domain($matches[2]);
1262
+ $origin = GA_Filter::ga_get_domain($_SERVER["HTTP_HOST"]);
1263
+ if ( $target["domain"] != $origin["domain"] ){
1264
+ if ( isset( $options['domainorurl'] ) && $options['domainorurl'] == "domain" )
1265
+ $url = $target["host"];
1266
+ else
1267
+ $url = $matches[2];
1268
+ $trackBit = 'onclick="'.GA_Filter::ga_get_tracking_link('outbound-commentauthor', $url).'"';
1269
+ }
1270
+ return $matches[1] . "\"" . $matches[2] . "\" " . $trackBit ." ". $matches[3];
1271
+ }
1272
+
1273
+ function bookmarks($bookmarks) {
1274
+ if ( !yoast_ga_do_tracking() )
1275
+ return $bookmarks;
1276
+
1277
+ $i = 0;
1278
+ while ( $i < count($bookmarks) ) {
1279
+ $target = GA_Filter::ga_get_domain($bookmarks[$i]->link_url);
1280
+ $sitedomain = GA_Filter::ga_get_domain(get_bloginfo('url'));
1281
+ if ($target['host'] == $sitedomain['host']) {
1282
+ $i++;
1283
+ continue;
1284
+ }
1285
+ if ( isset( $options['domainorurl'] ) && $options['domainorurl'] == "domain" )
1286
+ $url = $target["host"];
1287
+ else
1288
+ $url = $bookmarks[$i]->link_url;
1289
+ $trackBit = '" onclick="'.GA_Filter::ga_get_tracking_link('outbound-blogroll', $url);
1290
+ $bookmarks[$i]->link_target .= $trackBit;
1291
+ $i++;
1292
+ }
1293
+ return $bookmarks;
1294
+ }
1295
+
1296
+ function rsslinktagger($guid) {
1297
+ $options = get_option('Yoast_Google_Analytics');
1298
+ global $wp, $post;
1299
+ if ( is_feed() ) {
1300
+ if ( $options['allowanchor'] ) {
1301
+ $delimiter = '#';
1302
+ } else {
1303
+ $delimiter = '?';
1304
+ if (strpos ( $guid, $delimiter ) > 0)
1305
+ $delimiter = '&amp;';
1306
+ }
1307
+ return $guid . $delimiter . 'utm_source=rss&amp;utm_medium=rss&amp;utm_campaign='.urlencode($post->post_name);
1308
+ }
1309
+ return $guid;
1310
+ }
1311
+
1312
+ function wpec_transaction_tracking( $push ) {
1313
+ global $wpdb, $purchlogs, $cart_log_id;
1314
+ if( !isset( $cart_log_id ) || empty($cart_log_id) )
1315
+ return $push;
1316
+
1317
+ $city = $wpdb->get_var ("SELECT tf.value
1318
+ FROM ".WPSC_TABLE_SUBMITED_FORM_DATA." tf
1319
+ LEFT JOIN ".WPSC_TABLE_CHECKOUT_FORMS." cf
1320
+ ON cf.id = tf.form_id
1321
+ WHERE cf.type = 'city'
1322
+ AND log_id = ".$cart_log_id );
1323
+
1324
+ $country = $wpdb->get_var ("SELECT tf.value
1325
+ FROM ".WPSC_TABLE_SUBMITED_FORM_DATA." tf
1326
+ LEFT JOIN ".WPSC_TABLE_CHECKOUT_FORMS." cf
1327
+ ON cf.id = tf.form_id
1328
+ WHERE cf.type = 'country'
1329
+ AND log_id = ".$cart_log_id );
1330
+
1331
+ $cart_items = $wpdb->get_results ("SELECT * FROM ".WPSC_TABLE_CART_CONTENTS." WHERE purchaseid = ".$cart_log_id, ARRAY_A);
1332
+
1333
+ $total_shipping = $purchlogs->allpurchaselogs[0]->base_shipping;
1334
+ $total_tax = 0;
1335
+ foreach ( $cart_items as $item ) {
1336
+ $total_shipping += $item['pnp'];
1337
+ $total_tax += $item['tax_charged'];
1338
+ }
1339
+
1340
+ $push[] = "'_addTrans','".$cart_log_id."'," // Order ID
1341
+ ."'".GA_Filter::ga_str_clean(get_bloginfo('name'))."'," // Store name
1342
+ ."'".nzshpcrt_currency_display($purchlogs->allpurchaselogs[0]->totalprice,1,true,false,true)."'," // Total price
1343
+ ."'".nzshpcrt_currency_display($total_tax,1,true,false,true)."'," // Tax
1344
+ ."'".nzshpcrt_currency_display($total_shipping,1,true,false,true)."'," // Shipping
1345
+ ."'".$city."'," // City
1346
+ ."''," // State
1347
+ ."'".$country."'"; // Country
1348
+
1349
+ foreach( $cart_items as $item ) {
1350
+ $item['sku'] = $wpdb->get_var( "SELECT meta_value FROM ".WPSC_TABLE_PRODUCTMETA." WHERE meta_key = 'sku' AND product_id = '".$item['prodid']."' LIMIT 1" );
1351
+
1352
+ $item['category'] = $wpdb->get_var( "SELECT pc.name FROM ".WPSC_TABLE_PRODUCT_CATEGORIES." pc LEFT JOIN ".WPSC_TABLE_ITEM_CATEGORY_ASSOC." ca ON pc.id = ca.category_id WHERE pc.group_id = '1' AND ca.product_id = '".$item['prodid']."'" );
1353
+ $push[] = "'_addItem',"
1354
+ ."'".$cart_log_id."'," // Order ID
1355
+ ."'".$item['sku']."'," // Item SKU
1356
+ ."'". str_replace( "'", "", $item['name'] ) ."'," // Item Name
1357
+ ."'".$item['category']."'," // Item Category
1358
+ ."'".$item['price']."'," // Item Price
1359
+ ."'".$item['quantity']."'"; // Item Quantity
1360
+ }
1361
+ $push[] = "'_trackTrans'";
1362
+
1363
+ return $push;
1364
+ }
1365
+
1366
+ function shopp_transaction_tracking( $push ) {
1367
+ global $Shopp;
1368
+
1369
+ // Only process if we're in the checkout process (receipt page)
1370
+ if (version_compare(substr(SHOPP_VERSION,0,3),'1.1') >= 0) {
1371
+ // Only process if we're in the checkout process (receipt page)
1372
+ if (function_exists('is_shopp_page') && !is_shopp_page('checkout')) return $push;
1373
+ if (empty($Shopp->Order->purchase)) return $push;
1374
+
1375
+ $Purchase = new Purchase($Shopp->Order->purchase);
1376
+ $Purchase->load_purchased();
1377
+ } else {
1378
+ // For 1.0.x
1379
+ // Only process if we're in the checkout process (receipt page)
1380
+ if (function_exists('is_shopp_page') && !is_shopp_page('checkout')) return $push;
1381
+ // Only process if we have valid order data
1382
+ if (!isset($Shopp->Cart->data->Purchase)) return $push;
1383
+ if (empty($Shopp->Cart->data->Purchase->id)) return $push;
1384
+
1385
+ $Purchase = $Shopp->Cart->data->Purchase;
1386
+ }
1387
+
1388
+ $push[] = "'_addTrans',"
1389
+ ."'".$Purchase->id."'," // Order ID
1390
+ ."'".GA_Filter::ga_str_clean(get_bloginfo('name'))."'," // Store
1391
+ ."'".number_format($Purchase->total,2)."'," // Total price
1392
+ ."'".number_format($Purchase->tax,2)."'," // Tax
1393
+ ."'".number_format($Purchase->shipping,2)."'," // Shipping
1394
+ ."'".$Purchase->city."'," // City
1395
+ ."'".$Purchase->state."'," // State
1396
+ ."'.$Purchase->country.'"; // Country
1397
+
1398
+ foreach ($Purchase->purchased as $item) {
1399
+ $sku = empty($item->sku) ? 'PID-'.$item->product.str_pad($item->price,4,'0',STR_PAD_LEFT) : $item->sku;
1400
+ $push[] = "'_addItem',"
1401
+ ."'".$Purchase->id."',"
1402
+ ."'".$sku."',"
1403
+ ."'". str_replace( "'", "", $item->name ) ."',"
1404
+ ."'".$item->optionlabel."',"
1405
+ ."'".number_format($item->unitprice,2)."',"
1406
+ ."'".$item->quantity."'";
1407
+ }
1408
+ $push[] = "'_trackTrans'";
1409
+ return $push;
1410
+ }
1411
+
1412
+ } // class GA_Filter
1413
+ } // endif
1414
+
1415
+ /**
1416
+ * If setAllowAnchor is set to true, GA ignores all links tagged "normally", so we redirect all "normally" tagged URL's
1417
+ * to one tagged with a hash.
1418
+ */
1419
+ function ga_utm_hashtag_redirect() {
1420
+ if (isset($_SERVER['REQUEST_URI'])) {
1421
+ if (strpos($_SERVER['REQUEST_URI'], "utm_") !== false) {
1422
+ $url = 'http://';
1423
+ if ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != "") {
1424
+ $url = 'https://';
1425
+ }
1426
+ $url .= $_SERVER['SERVER_NAME'];
1427
+ if ( strpos($_SERVER['REQUEST_URI'], "?utm_") !== false ) {
1428
+ $url .= str_replace("?utm_","#utm_",$_SERVER['REQUEST_URI']);
1429
+ } else if ( strpos($_SERVER['REQUEST_URI'], "&utm_") !== false ) {
1430
+ $url .= substr_replace($_SERVER['REQUEST_URI'], "#utm_", strpos($_SERVER['REQUEST_URI'], "&utm_"), 5);
1431
+ }
1432
+ wp_redirect($url, 301);
1433
+ exit;
1434
+ }
1435
+ }
1436
+ }
1437
+
1438
+ function yoast_ga_do_tracking() {
1439
+ $current_user = wp_get_current_user();
1440
+
1441
+ if (0 == $current_user->ID)
1442
+ return true;
1443
+
1444
+ $yoast_ga_options = get_option('Yoast_Google_Analytics');
1445
+
1446
+ if ( ($current_user->user_level >= $yoast_ga_options["ignore_userlevel"]) )
1447
+ return false;
1448
+ else
1449
+ return true;
1450
+ }
1451
+
1452
+ function track_comment_form_head() {
1453
+ if (is_singular()) {
1454
+ global $post;
1455
+ $yoast_ga_options = get_option('Yoast_Google_Analytics');
1456
+ if ( yoast_ga_do_tracking()
1457
+ && isset( $yoast_ga_options["trackcommentform"] )
1458
+ && $yoast_ga_options["trackcommentform"]
1459
+ && ( 'open' == $post->comment_status ) )
1460
+ wp_enqueue_script('jquery');
1461
+ }
1462
+ }
1463
+ add_action('wp_print_scripts','track_comment_form_head');
1464
+
1465
+ $comment_form_id = '';
1466
+ function yoast_get_comment_form_id($args) {
1467
+ global $comment_form_id;
1468
+ $comment_form_id = $args['id_form'];
1469
+ return $args;
1470
+ }
1471
+ add_filter('comment_form_defaults', 'yoast_get_comment_form_id',99,1);
1472
+
1473
+ function yoast_track_comment_form() {
1474
+ global $comment_form_id, $post;
1475
+ $yoast_ga_options = get_option('Yoast_Google_Analytics');
1476
+ if ( yoast_ga_do_tracking() && $yoast_ga_options["trackcommentform"] ) {
1477
+ ?>
1478
+ <script type="text/javascript">
1479
+ jQuery(document).ready(function() {
1480
+ jQuery('#<?php echo $comment_form_id; ?>').submit(function() {
1481
+ _gaq.push(
1482
+ ['_setAccount','<?php echo $yoast_ga_options["uastring"]; ?>'],
1483
+ ['_trackEvent','comment']
1484
+ );
1485
+ });
1486
+ });
1487
+ </script>
1488
+ <?php
1489
+ }
1490
+ }
1491
+ add_action('comment_form_after','yoast_track_comment_form');
1492
+
1493
+ function yoast_sanitize_relative_links($content) {
1494
+ preg_match("|^http(s)?://([^/]+)|i", get_bloginfo('url'), $match);
1495
+ $content = preg_replace("/<a([^>]*) href=('|\")\/([^\"']*)('|\")/", "<a\${1} href=\"" .$match[0] ."/" ."\${3}\"", $content);
1496
+
1497
+ if (is_singular()) {
1498
+ $content = preg_replace("/<a([^>]*) href=('|\")#([^\"']*)('|\")/", "<a\${1} href=\"" .get_permalink()."#" ."\${3}\"", $content);
1499
+ }
1500
+ return $content;
1501
+ }
1502
+ add_filter('the_content', 'yoast_sanitize_relative_links', 98);
1503
+ add_filter('widget_text', 'yoast_sanitize_relative_links', 98);
1504
+
1505
+ function yoast_analytics() {
1506
+ $options = get_option('Yoast_Google_Analytics');
1507
+ if ($options['position'] == 'manual')
1508
+ GA_Filter::spool_analytics();
1509
+ else
1510
+ echo '<!-- Please set Google Analytics position to "manual" in the settings, or remove this call to yoast_analytics(); -->';
1511
+ }
1512
+
1513
+ $gaf = new GA_Filter();
1514
+ $options = get_option('Yoast_Google_Analytics');
1515
+
1516
+ if (!is_array($options)) {
1517
+ $options = get_option('GoogleAnalyticsPP');
1518
+ if (!is_array($options)) {
1519
+ $ga_admin->set_defaults();
1520
+ } else {
1521
+ delete_option('GoogleAnalyticsPP');
1522
+ if ($options['admintracking']) {
1523
+ $options["ignore_userlevel"] = '8';
1524
+ unset($options['admintracking']);
1525
+ } else {
1526
+ $options["ignore_userlevel"] = '11';
1527
+ }
1528
+ update_option('Yoast_Google_Analytics', $options);
1529
+ }
1530
+ } else {
1531
+ if ( isset( $options['allowanchor'] ) && $options['allowanchor'] ) {
1532
+ add_action('init','ga_utm_hashtag_redirect',1);
1533
+ }
1534
+
1535
+ if ( (isset( $options['trackoutbound'] ) && $options['trackoutbound'] ) ||
1536
+ (isset( $options['trackcrossdomain'] ) && $options['trackcrossdomain'] ) ) {
1537
+ // filters alter the existing content
1538
+ add_filter('the_content', array('GA_Filter','the_content'), 99);
1539
+ add_filter('widget_text', array('GA_Filter','widget_content'), 99);
1540
+ add_filter('the_excerpt', array('GA_Filter','the_content'), 99);
1541
+ add_filter('comment_text', array('GA_Filter','comment_text'), 99);
1542
+ add_filter('get_bookmarks', array('GA_Filter','bookmarks'), 99);
1543
+ add_filter('get_comment_author_link', array('GA_Filter','comment_author_link'), 99);
1544
+ add_filter('wp_nav_menu', array('GA_Filter','nav_menu'), 99);
1545
+ }
1546
+
1547
+ if ( isset( $options['trackadsense'] ) && $options['trackadsense'] )
1548
+ add_action('wp_head', array('GA_Filter','spool_adsense'),1);
1549
+
1550
+ if ( !isset( $options['position'] ) )
1551
+ $options['position'] = 'header';
1552
+
1553
+ switch ($options['position']) {
1554
+ case 'manual':
1555
+ // No need to insert here, bail NOW.
1556
+ break;
1557
+ case 'header':
1558
+ default:
1559
+ add_action('wp_head', array('GA_Filter','spool_analytics'),2);
1560
+ break;
1561
+ }
1562
+
1563
+ if ( isset( $options['trackregistration'] ) && $options['trackregistration'] )
1564
+ add_action('login_head', array('GA_Filter','spool_analytics'),20);
1565
+
1566
+ if ( isset( $options['rsslinktagging'] ) && $options['rsslinktagging'] )
1567
+ add_filter ( 'the_permalink_rss', array('GA_Filter','rsslinktagger'), 99 );
1568
+
1569
+ }
images/facebook-icon.png ADDED
Binary file
images/google-plus-icon.png ADDED
Binary file
images/twitter-icon.png ADDED
Binary file
readme.txt CHANGED
@@ -1,329 +1,335 @@
1
- === Google Analytics for WordPress ===
2
- Contributors: joostdevalk
3
- Donate link: http://yoast.com/donate/
4
- Tags: analytics, google analytics, statistics, tracking, stats, google
5
- Requires at least: 2.8
6
- Tested up to: 3.2
7
- Stable tag: 4.1.3
8
-
9
- Track your WordPress site easily and with lots of metadata: views per author & category, automatic tracking of outbound clicks and pageviews.
10
-
11
- == Description ==
12
-
13
- The Google Analytics for WordPress plugin allows you to track your blog easily and with lots of metadata.
14
-
15
- Check out the [Google Analytics for WordPress video](http://www.youtube.com/watch?v=tnUXzbvXxSQ):
16
-
17
- http://www.youtube.com/watch?v=tnUXzbvXxSQ&hd=1
18
-
19
- Full list of features:
20
-
21
- * Simple installation through integration with Google Analytics API: authenticate, select the site you want to track and you're done.
22
- * This plugin uses the asynchronous Google Analytics tracking code, the fastest and most reliable tracking code Google Analytics offers.
23
- * Option to manually place the tracking code in another location.
24
- * Automatic Google Analytics site speed tracking.
25
- * Outbound link & downloads tracking.
26
- * Configurable options to track outbound links either as pageviews.
27
- * Option to track just downloads as pageviews in Google Analytics.
28
- * Allows usage of custom variables in Google Analytics to track meta data on pages. Support for the following custom variables:
29
- * Author
30
- * Single category and / or multiple categories
31
- * Post type (especially useful if you use custom post types)
32
- * Logged in users
33
- * Publication Year
34
- * Tags
35
- * Possibility to ignore any user level and up, so all editors and higher for instance.
36
- * Easily connect your Google AdSense and Google Analytics accounts.
37
- * Option to tag links with Google Analytics campaign tracking, with the option to use hashes (#).
38
- * Option anonymize IP's, for use in countries like Germany.
39
- * Full [debug mode](http://yoast.com/google-analytics-debug-mode/), including Firebug lite and ga_debug.js for debugging Google Analytics issues.
40
- * Allow local hosting of ga.js file.
41
- * Tracking of search engines not included in Google Analytics default tracking.
42
- * Tracking of login and registration forms.
43
-
44
- Other interesting stuff:
45
-
46
- * Check out the other [Wordpress plugins](http://yoast.com/wordpress/) by the same author.
47
- * Want to increase traffic to your WordPress blog? Check out the [WordPress SEO](http://yoast.com/articles/wordpress-seo/) Guide!
48
- * Check out the authors [WordPress Hosting](http://yoast.com/articles/wordpress-hosting/) experience. Good hosting is hard to come by, but it doesn't have to be expensive, Joost tells you why!
49
- * If you've still not seen enough, or you'd rather listen than read, check out the [WordPress Podcast](http://wp-community.org/), hosted by the author of this plugin and Frederick Townes, the creator of [W3 Total Cache](http://wordpress.org/extend/plugins/w3-total-cache/).
50
-
51
- == Installation ==
52
-
53
- This section describes how to install the plugin and get it working.
54
-
55
- 1. Delete any existing `gapp` or `google-analytics-for-wordpress` folder from the `/wp-content/plugins/` directory
56
- 1. Upload `google-analytics-for-wordpress` folder to the `/wp-content/plugins/` directory
57
- 1. Activate the plugin through the 'Plugins' menu in WordPress
58
- 1. Go to the options panel under the 'Settings' menu and add your Analytics account number and set the settings you want.
59
-
60
- == Changelog ==
61
-
62
- = 4.1.3 =
63
-
64
- * Security fix: badly crafted comments could lead to insertion of "weird" links into comments. They'd have to pass your moderation, but still... Immediate update advised. Props to [David Whitehouse](http://www.david-whitehouse.org/) and [James Slater](http://james.slaterspage.com/) for finding it.
65
-
66
- = 4.1.2 =
67
-
68
- * Fixed bug with custom SE tracking introduced in 4.1.1.
69
-
70
- = 4.1.1 =
71
-
72
- * Made plugin admin work with jQuery 1.6 and jQuery 1.4.
73
- * Added contextual help.
74
- * Improved cache flushing when using W3TC.
75
- * Fixed various minor other notices.
76
- * First stab at getting ready for full i18n compatibility.
77
-
78
- = 4.1 =
79
-
80
- * Added:
81
- * Google Site Speed tracking, turned it on by default.
82
-
83
- * Fixed:
84
- * Custom code now properly removes slashes.
85
-
86
- = 4.0.12 =
87
-
88
- * Fixed:
89
- * Tons of notices in backend and front end when no settings were saved yet.
90
- * Set proper defaults for all variables.
91
- * Notice for unset categories array on custom post types.
92
- * Notice for unset variable.
93
- * Error when user is not logged in in certain corner cases.
94
- * Bug where $options was used but never loaded for blogroll links.
95
-
96
- = 4.0.11 =
97
-
98
- * Bugs fixed:
99
- * You can now disable comment form tracking properly.
100
- * Removed charset property from script tags to allow validation with HTML5 doctype.
101
-
102
- = 4.0.10 =
103
-
104
- * Known issues:
105
- * Authentication with Google gives errors in quite a few cases. Please use the manual option to add your UA code until we find a way to reliably fix it.
106
-
107
- * Added functionality:
108
- * Option to set `_setAllowHash` to false, for proper subdomain tracking and some other uses.
109
- * Option to add a custom string of code to the tracking, before the push string is sent out.
110
-
111
- * Documentation fixes:
112
- * Fixed link for `_setDomainName()`.
113
- * Fixed some grammatical errors (keep emailing me about those, please!)
114
- * Removed second comment in source output.
115
- * Fixed version number output in source.
116
-
117
- = 4.0.9 =
118
-
119
- * Code enhancements:
120
- * Updated Shopp integration to also work with the upcoming Shopp 1.1 and higher.
121
- * Switched from [split](http://php.net/split) to [explode](http://php.net/explode), as split has been deprecated in PHP 5.3+.
122
- * New features:
123
- * A new debug mode has been added, using the new [ga_debug.js](http://analytics.blogspot.com/2010/08/new-tools-to-debug-your-tracking-code.html). Along with this you can now enable Firebug Lite, so you can easily see the output from the debug script in each browser. Admins only, of course.
124
- * A list of modules has been added to the right sidebar, to allow easy navigation within the settings page.
125
-
126
- = 4.0.8 =
127
- * Reverted double quote change from 4.0.7 because it was causing bigger issues.
128
-
129
- = 4.0.7 =
130
- * Bugs fixed in this release:
131
- * Changed access level from "edit_users" to "manage_options" so super-admins in an multi site environment would be able to access.
132
- * Not a real bug but a fix nonetheless: UA ID is now trimmed on output, so spaces accidently entered in the settings screen won't prevent tracking.
133
- * Changed double quotes in link tracking output to single quotes to resolve incompatibilities with several plugins.
134
-
135
- = 4.0.6 =
136
- * Bugs fixed in this release:
137
- * Sanitizing relative URL's could go wrong on some blogs installed in subdirectories.
138
- * Comment form tracking only worked for posts, not for pages, and would sometimes cause other issues. Patch by [Milan Dinić](http://blog.milandinic.com/).
139
- * Settings page: now correctly hiding internal links to track as outbound block when outbound link tracking is disabled.
140
- * Code sanitization:
141
- * Hardcoded the [scope for custom variables](http://code.google.com/apis/analytics/docs/gaJS/gaJSApiBasicConfiguration.html#_gat.GA_Tracker_._setCustomVar) to prevent that from possibly going wrong.
142
- * Improved method of determining whether current user should be tracked or not.
143
- * Added plugin version number in script branding comment, and moved branding comment to within CDATA section to assist in debugging, even when people use W3TC or another form of code minification.
144
- * Documentation fixes:
145
- * Updated custom variable order in settings panel to reflect order of tracking. You can now determine their index key by counting down, first checked box is index 1, second 2, etc.
146
- * Ignored users dropdown now correctly reflects that ignoring subcribers and up means ignoring ALL logged in users.
147
-
148
- = 4.0.5 =
149
- * New features in this release:
150
- * Added a simple check to see if the UA code, when entered manually, matches a basic pattern of UA-1234567-12.
151
- * Added integration with [W3 Total Cache](http://wordpress.org/extend/plugins/w3-total-cache/) and [WP Super Cache](http://wordpress.org/extend/plugins/wp-super-cache/). The page cache is now automatically cleared after updating settings. Caching is recommended for all WordPress users, as faster page loads improve tracking reliability and W3 Total Cache is our recommended caching plugin.
152
- * Added the option to enter a manual location for ga.js, allowing you to host it locally should you wish to.
153
- * Bugs fixed:
154
- * Fixed implementation of _anonymizeIp, it now correctly anonymizes IP's by setting [_gat._anonymizeIp](http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_gat._anonymizeIp).
155
- * Increased request timeout time for Google Analytics authentication from 10 to 20 seconds, for slow hosts (if this fixes it for you, your hosting is probably not really good, consider another WordPress host).
156
- * Documentation fixes:
157
- * Added a note about profiles with the same UA code to the Analytics Profile selection.
158
- * The profile selection dropdown now shows the UA code after the profile name too.
159
- * Updated the [screenshots](http://wordpress.org/extend/plugins/google-analytics-for-wordpress/screenshots/) and the [FAQ](http://wordpress.org/extend/plugins/google-analytics-for-wordpress/faq/) for this plugin.
160
-
161
- = 4.0.4 =
162
- * Fix for stupid boolean mistake in 4.0.3.
163
-
164
- = 4.0.3 =
165
- * New features in this release:
166
- * Added versioning to the options array, to allow for easy addition of options.
167
- * Added an option to enable comment form tracking (as this loads jQuery), defaults to on.
168
- * Bugs fixed:
169
- * If you upgraded from before 4.0 to 4.0.2 you might have an empty value for ignore_userlevel in some edge cases, this is now fixed.
170
- * Custom search engines were loaded after trackPageview, this was wrong as shown [by these docs](http://code.google.com/intl/sr/apis/analytics/docs/tracking/asyncMigrationExamples.html#SearchEngines), now fixed.
171
-
172
- = 4.0.2 =
173
- * Old settings from versions below 4.0 are now properly sanitized and inherited (slaps forehead about simplicity of fix).
174
- * New features in this release:
175
- * Link sanitization added: relative links will be rewritten to absolute, so /out/ becomes http://example.com/out/ and is tracked properly.
176
- * Added a feature to track and label internal links as outbound clicks, for instance /out/ links.
177
- * Added tracking for mailto: links.
178
- * Added a filter for text-widgets, all links in those widgets are now tagged too.
179
- * Added support for [_anonymizeIp](http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_gat._anonymizeIp).
180
- * Bugs fixed in this release:
181
- * Made sure all content filters don't run when the current user is ignored because of his user level.
182
-
183
- = 4.0.1 =
184
- * Fix for when you have only 1 site in a specific Analytics profile.
185
-
186
- = 4.0 =
187
- * NOTE WHEN UPGRADING: you'll have to reconfigure the plugin so it can fully support all the new features!
188
- * Complete rewrite of the codebase
189
- * Switched to the new asynchronous event tracking model
190
- * Switched link tracking to an event tracking model, because of this change removed 5 settings from the settings panel that were no longer needed
191
- * Implemented custom variable tracking to track:
192
- * On the session level: whether the user is logged in or not.
193
- * On the page level: the current posts's author, category, tags, year of publication and post type.
194
- * Added Google Analytics API integration, so you can easily select a site to track.
195
- * E-Commerce integration, tracking transactions, support for WP E-Commerce and Shopp.
196
- * Much much more: check out [the release post](http://yoast.com/google-analytics-wordpress-v4/).
197
-
198
- = 3.2.3 =
199
- * Added 0 result search tracking inspired by [Justin Cutroni's post](http://www.epikone.com/blog/2009/09/08/tracking-ero-result-searches-in-google-analytics/).
200
-
201
- = 3.2.2 =
202
- * Fix to the hashtag redirect so it actually works in all cases.
203
-
204
- = 3.2.1 =
205
- * Slight change to RSS URL tagging, now setting campaign to post name, and behaving better when not using rewritten URL's.
206
- * Two patches by [Lee Willis](http://www.leewillis.co.uk):
207
- * Made some changes so the entire plugin works fine with .co.uk, .co.za etc domains.
208
- * Made sure internal blogroll links aren't tagged as external clicks.
209
-
210
- = 3.2 =
211
- * Added option to add tracking to add tracking to login / register pages, so you can track new signups (under Advanced settings).
212
- * Added beta option to track Google image search as a search engine, needs more testing to make sure it works.
213
- * Fixed a bug in the extra search engine tracking implementation.
214
- * Removed redundant "More Info" section from readme.txt.
215
-
216
- = 3.1.1 =
217
- * Stupid typo that caused warnings.
218
-
219
- = 3.1 =
220
- * Added 404 tracking as described [here](http://www.google.com/support/googleanalytics/bin/answer.py?hl=en&answer=86927).
221
- * Optimized the tracking script, if extra search engine tracking is disabled it'll be a lot smaller now.
222
- * Various code optimizations to prevent PHP notices and removal of redundant code.
223
-
224
- = 3.0.1 =
225
- * Removed no longer needed code to add config page that caused PHP warnings.
226
-
227
- = 3.0 =
228
- * Major backend overhaul, using new Yoast backend class.
229
- * Added ability to automatically redirect non hashtagged campaign URLs to hashtagged campaign URL's when setAllowAnchor is set to true (if you don't get it, forget about it, you might need it but don't need to worry)
230
-
231
- = 2.9.5 =
232
- * Fixed a bug with the included RSS, which came up when multiple Yoast plugins were installed.
233
-
234
- = 2.9.4 =
235
- * Changed to the new Changelog design.
236
- * Removed pre 2.6 compatibility code, plugin now requires WP 2.6 or higher.
237
- * Small changes to the admin screen.
238
-
239
- = 2.9.3 =
240
- * Added a new option for RSS link tagging, which allows you to tag your RSS feed links with RSS campaign variables. When you've set campaign variables to use # instead of ?, this will adhere to that setting too. Thanks to [Timan Rebel](http://rebelic.nl/) for the idea and code.
241
-
242
- = 2.9.2: =
243
- * Added a check to see whether the wp_footer() call is in footer.php.
244
- * Added a message to the source when tracking code is left out because user is logged in as admin.
245
- * Added option to segment logged in users.
246
- * Added try - catch to script lines like in new Google Analytics scripts.
247
- * Fixed bug in warning when no UA code is entered.
248
- * Prevent link tracking when admin is logged in and admin tracking is disabled.
249
- * Now prevents parsing of non http and https link.
250
-
251
- = 2.9 =
252
- * Re arranged admin panel to have "standard" and "advanced" settings.
253
- * Added domain tracking.
254
- * Added fix for double onclick parameter, as suggested [here](http://wordpress.org/support/topic/241757).
255
-
256
- = 2.8 =
257
- * Added the option to add setAllowAnchor to the tracking code, allowing you to track campaigns with # instead of ?.
258
-
259
- = 2.7 =
260
- * Added option to select either header of footer position.
261
- * Added new AdSense integration options.
262
- * Removed now unneeded adsense tracking script.
263
-
264
- = 2.6.6=
265
- * Fixed settings link.
266
-
267
- = 2.6.5 =
268
- * added Ozh admin menu icon and settings link.
269
-
270
- = 2.6.4 =
271
- * Fixes for 2.7.
272
-
273
- = 2.6.3 =
274
- * Fixed bug that didn't allow saving of outbound clicks from comments string.
275
-
276
- = 2.6 =
277
- * Fixed incompatibility with WP 2.6.
278
-
279
- = 2.5.4 =
280
- * Fixed an issue with pluginpath being used globally.
281
- * Changed links to [new domain](http://yoast.com/).
282
-
283
- = 2.2 =
284
- * Switched to the new tracking code.
285
-
286
- = 2.1 =
287
- * Made sure tracking was disabled on preview pages.
288
-
289
- = 2.0 =
290
- * Added AdSense tracking.
291
-
292
- = 1.5 =
293
- * Added option to enable admin tracking, off by default.
294
-
295
- == Frequently Asked Questions ==
296
-
297
- = Can I run this plugin together with another Google Analytics plugin? =
298
-
299
- No. You can not. It will break tracking.
300
-
301
- = Another profile than the one I selected is showing as selected? =
302
-
303
- You probably have multiple profiles for the same website, that share the same UA-code. If so, it doesn't matter which of the profiles is shown as selected, tracking will be correct.
304
-
305
- = I've just installed the new tracking and Google Analytics says it's not receiving data yet? =
306
-
307
- Give it a couple of hours, usually it'll be fixed. It can take up to 24 hours to appear though.
308
-
309
- = Google Analytics says it's receiving data, but I don't see any stats yet? =
310
-
311
- This can take up to 24 hours after the installation of the new tracking code.
312
-
313
- = Why is the tracking code loaded in the head section of the site? =
314
-
315
- Because that's where it belongs. It makes the page load faster (yes, faster, due to the asynchronous method of loading the script) and tracking more reliable. If you must place it in the footer anyway, switch to manual mode and check out the docs for [manual placement of the Google Analytics code](http://yoast.com/wordpress/google-analytics/manual-placement/).
316
-
317
- == Screenshots ==
318
-
319
- 1. Screenshot of the basic settings panel for this plugin.
320
- 2. Screenshot of the custom variable settings panel.
321
- 3. Screenshot of the link tracking panel.
322
- 4. Screenshot of the advanced settings panel.
323
- 5. Screenshot of the debugging mode in action.
324
-
325
- == Upgrade Notice ==
326
-
327
- = 4.1.3 =
328
-
329
- Security fix, please update ASAP. Old version is susceptible to link insertion.
 
 
 
 
 
 
1
+ === Google Analytics for WordPress ===
2
+ Contributors: joostdevalk
3
+ Donate link: http://yoast.com/donate/
4
+ Tags: analytics, google analytics, statistics, tracking, stats, google
5
+ Requires at least: 2.8
6
+ Tested up to: 3.2.1
7
+ Stable tag: 4.2
8
+
9
+ Track your WordPress site easily and with lots of metadata: views per author & category, automatic tracking of outbound clicks and pageviews.
10
+
11
+ == Description ==
12
+
13
+ The Google Analytics for WordPress plugin allows you to track your blog easily and with lots of metadata.
14
+
15
+ Check out the [Google Analytics for WordPress video](http://www.youtube.com/watch?v=tnUXzbvXxSQ):
16
+
17
+ http://www.youtube.com/watch?v=tnUXzbvXxSQ&hd=1
18
+
19
+ Full list of features:
20
+
21
+ * Simple installation through integration with Google Analytics API: authenticate, select the site you want to track and you're done.
22
+ * This plugin uses the asynchronous Google Analytics tracking code, the fastest and most reliable tracking code Google Analytics offers.
23
+ * Option to manually place the tracking code in another location.
24
+ * Automatic Google Analytics site speed tracking.
25
+ * Outbound link & downloads tracking.
26
+ * Configurable options to track outbound links either as pageviews.
27
+ * Option to track just downloads as pageviews in Google Analytics.
28
+ * Allows usage of custom variables in Google Analytics to track meta data on pages. Support for the following custom variables:
29
+ * Author
30
+ * Single category and / or multiple categories
31
+ * Post type (especially useful if you use custom post types)
32
+ * Logged in users
33
+ * Publication Year
34
+ * Tags
35
+ * Possibility to ignore any user level and up, so all editors and higher for instance.
36
+ * Easily connect your Google AdSense and Google Analytics accounts.
37
+ * Option to tag links with Google Analytics campaign tracking, with the option to use hashes (#).
38
+ * Option anonymize IP's, for use in countries like Germany.
39
+ * Full [debug mode](http://yoast.com/google-analytics-debug-mode/), including Firebug lite and ga_debug.js for debugging Google Analytics issues.
40
+ * Allow local hosting of ga.js file.
41
+ * Tracking of search engines not included in Google Analytics default tracking.
42
+ * Tracking of login and registration forms.
43
+
44
+ Other interesting stuff:
45
+
46
+ * Check out the other [Wordpress plugins](http://yoast.com/wordpress/) by the same author.
47
+ * Want to increase traffic to your WordPress blog? Check out the [WordPress SEO](http://yoast.com/articles/wordpress-seo/) Guide!
48
+ * Check out the authors [WordPress Hosting](http://yoast.com/articles/wordpress-hosting/) experience. Good hosting is hard to come by, but it doesn't have to be expensive, Joost tells you why!
49
+ * If you've still not seen enough, or you'd rather listen than read, check out the [WordPress Podcast](http://wp-community.org/), hosted by the author of this plugin and Frederick Townes, the creator of [W3 Total Cache](http://wordpress.org/extend/plugins/w3-total-cache/).
50
+
51
+ == Installation ==
52
+
53
+ This section describes how to install the plugin and get it working.
54
+
55
+ 1. Delete any existing `gapp` or `google-analytics-for-wordpress` folder from the `/wp-content/plugins/` directory
56
+ 1. Upload `google-analytics-for-wordpress` folder to the `/wp-content/plugins/` directory
57
+ 1. Activate the plugin through the 'Plugins' menu in WordPress
58
+ 1. Go to the options panel under the 'Settings' menu and add your Analytics account number and set the settings you want.
59
+
60
+ == Changelog ==
61
+
62
+ = 4.2 =
63
+
64
+ * Google Authentication now happens using OAuth. The requests have become signed as an extra security measure and tokens have become more stable, as opposed to the prior tokens used with AuthSub.
65
+ * Added support for cross-domain tracking.
66
+ * Fixed various small bugs.
67
+
68
+ = 4.1.3 =
69
+
70
+ * Security fix: badly crafted comments could lead to insertion of "weird" links into comments. They'd have to pass your moderation, but still... Immediate update advised. Props to David Whitehouse and James Slater for finding it.
71
+
72
+ = 4.1.2 =
73
+
74
+ * Fixed bug with custom SE tracking introduced in 4.1.1.
75
+
76
+ = 4.1.1 =
77
+
78
+ * Made plugin admin work with jQuery 1.6 and jQuery 1.4.
79
+ * Added contextual help.
80
+ * Improved cache flushing when using W3TC.
81
+ * Fixed various minor other notices.
82
+ * First stab at getting ready for full i18n compatibility.
83
+
84
+ = 4.1 =
85
+
86
+ * Added:
87
+ * Google Site Speed tracking, turned it on by default.
88
+
89
+ * Fixed:
90
+ * Custom code now properly removes slashes.
91
+
92
+ = 4.0.12 =
93
+
94
+ * Fixed:
95
+ * Tons of notices in backend and front end when no settings were saved yet.
96
+ * Set proper defaults for all variables.
97
+ * Notice for unset categories array on custom post types.
98
+ * Notice for unset variable.
99
+ * Error when user is not logged in in certain corner cases.
100
+ * Bug where $options was used but never loaded for blogroll links.
101
+
102
+ = 4.0.11 =
103
+
104
+ * Bugs fixed:
105
+ * You can now disable comment form tracking properly.
106
+ * Removed charset property from script tags to allow validation with HTML5 doctype.
107
+
108
+ = 4.0.10 =
109
+
110
+ * Known issues:
111
+ * Authentication with Google gives errors in quite a few cases. Please use the manual option to add your UA code until we find a way to reliably fix it.
112
+
113
+ * Added functionality:
114
+ * Option to set `_setAllowHash` to false, for proper subdomain tracking and some other uses.
115
+ * Option to add a custom string of code to the tracking, before the push string is sent out.
116
+
117
+ * Documentation fixes:
118
+ * Fixed link for `_setDomainName()`.
119
+ * Fixed some grammatical errors (keep emailing me about those, please!)
120
+ * Removed second comment in source output.
121
+ * Fixed version number output in source.
122
+
123
+ = 4.0.9 =
124
+
125
+ * Code enhancements:
126
+ * Updated Shopp integration to also work with the upcoming Shopp 1.1 and higher.
127
+ * Switched from [split](http://php.net/split) to [explode](http://php.net/explode), as split has been deprecated in PHP 5.3+.
128
+ * New features:
129
+ * A new debug mode has been added, using the new [ga_debug.js](http://analytics.blogspot.com/2010/08/new-tools-to-debug-your-tracking-code.html). Along with this you can now enable Firebug Lite, so you can easily see the output from the debug script in each browser. Admins only, of course.
130
+ * A list of modules has been added to the right sidebar, to allow easy navigation within the settings page.
131
+
132
+ = 4.0.8 =
133
+ * Reverted double quote change from 4.0.7 because it was causing bigger issues.
134
+
135
+ = 4.0.7 =
136
+ * Bugs fixed in this release:
137
+ * Changed access level from "edit_users" to "manage_options" so super-admins in an multi site environment would be able to access.
138
+ * Not a real bug but a fix nonetheless: UA ID is now trimmed on output, so spaces accidently entered in the settings screen won't prevent tracking.
139
+ * Changed double quotes in link tracking output to single quotes to resolve incompatibilities with several plugins.
140
+
141
+ = 4.0.6 =
142
+ * Bugs fixed in this release:
143
+ * Sanitizing relative URL's could go wrong on some blogs installed in subdirectories.
144
+ * Comment form tracking only worked for posts, not for pages, and would sometimes cause other issues. Patch by [Milan Dinić](http://blog.milandinic.com/).
145
+ * Settings page: now correctly hiding internal links to track as outbound block when outbound link tracking is disabled.
146
+ * Code sanitization:
147
+ * Hardcoded the [scope for custom variables](http://code.google.com/apis/analytics/docs/gaJS/gaJSApiBasicConfiguration.html#_gat.GA_Tracker_._setCustomVar) to prevent that from possibly going wrong.
148
+ * Improved method of determining whether current user should be tracked or not.
149
+ * Added plugin version number in script branding comment, and moved branding comment to within CDATA section to assist in debugging, even when people use W3TC or another form of code minification.
150
+ * Documentation fixes:
151
+ * Updated custom variable order in settings panel to reflect order of tracking. You can now determine their index key by counting down, first checked box is index 1, second 2, etc.
152
+ * Ignored users dropdown now correctly reflects that ignoring subcribers and up means ignoring ALL logged in users.
153
+
154
+ = 4.0.5 =
155
+ * New features in this release:
156
+ * Added a simple check to see if the UA code, when entered manually, matches a basic pattern of UA-1234567-12.
157
+ * Added integration with [W3 Total Cache](http://wordpress.org/extend/plugins/w3-total-cache/) and [WP Super Cache](http://wordpress.org/extend/plugins/wp-super-cache/). The page cache is now automatically cleared after updating settings. Caching is recommended for all WordPress users, as faster page loads improve tracking reliability and W3 Total Cache is our recommended caching plugin.
158
+ * Added the option to enter a manual location for ga.js, allowing you to host it locally should you wish to.
159
+ * Bugs fixed:
160
+ * Fixed implementation of _anonymizeIp, it now correctly anonymizes IP's by setting [_gat._anonymizeIp](http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_gat._anonymizeIp).
161
+ * Increased request timeout time for Google Analytics authentication from 10 to 20 seconds, for slow hosts (if this fixes it for you, your hosting is probably not really good, consider another WordPress host).
162
+ * Documentation fixes:
163
+ * Added a note about profiles with the same UA code to the Analytics Profile selection.
164
+ * The profile selection dropdown now shows the UA code after the profile name too.
165
+ * Updated the [screenshots](http://wordpress.org/extend/plugins/google-analytics-for-wordpress/screenshots/) and the [FAQ](http://wordpress.org/extend/plugins/google-analytics-for-wordpress/faq/) for this plugin.
166
+
167
+ = 4.0.4 =
168
+ * Fix for stupid boolean mistake in 4.0.3.
169
+
170
+ = 4.0.3 =
171
+ * New features in this release:
172
+ * Added versioning to the options array, to allow for easy addition of options.
173
+ * Added an option to enable comment form tracking (as this loads jQuery), defaults to on.
174
+ * Bugs fixed:
175
+ * If you upgraded from before 4.0 to 4.0.2 you might have an empty value for ignore_userlevel in some edge cases, this is now fixed.
176
+ * Custom search engines were loaded after trackPageview, this was wrong as shown [by these docs](http://code.google.com/intl/sr/apis/analytics/docs/tracking/asyncMigrationExamples.html#SearchEngines), now fixed.
177
+
178
+ = 4.0.2 =
179
+ * Old settings from versions below 4.0 are now properly sanitized and inherited (slaps forehead about simplicity of fix).
180
+ * New features in this release:
181
+ * Link sanitization added: relative links will be rewritten to absolute, so /out/ becomes http://example.com/out/ and is tracked properly.
182
+ * Added a feature to track and label internal links as outbound clicks, for instance /out/ links.
183
+ * Added tracking for mailto: links.
184
+ * Added a filter for text-widgets, all links in those widgets are now tagged too.
185
+ * Added support for [_anonymizeIp](http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_gat._anonymizeIp).
186
+ * Bugs fixed in this release:
187
+ * Made sure all content filters don't run when the current user is ignored because of his user level.
188
+
189
+ = 4.0.1 =
190
+ * Fix for when you have only 1 site in a specific Analytics profile.
191
+
192
+ = 4.0 =
193
+ * NOTE WHEN UPGRADING: you'll have to reconfigure the plugin so it can fully support all the new features!
194
+ * Complete rewrite of the codebase
195
+ * Switched to the new asynchronous event tracking model
196
+ * Switched link tracking to an event tracking model, because of this change removed 5 settings from the settings panel that were no longer needed
197
+ * Implemented custom variable tracking to track:
198
+ * On the session level: whether the user is logged in or not.
199
+ * On the page level: the current posts's author, category, tags, year of publication and post type.
200
+ * Added Google Analytics API integration, so you can easily select a site to track.
201
+ * E-Commerce integration, tracking transactions, support for WP E-Commerce and Shopp.
202
+ * Much much more: check out [the release post](http://yoast.com/google-analytics-wordpress-v4/).
203
+
204
+ = 3.2.3 =
205
+ * Added 0 result search tracking inspired by [Justin Cutroni's post](http://www.epikone.com/blog/2009/09/08/tracking-ero-result-searches-in-google-analytics/).
206
+
207
+ = 3.2.2 =
208
+ * Fix to the hashtag redirect so it actually works in all cases.
209
+
210
+ = 3.2.1 =
211
+ * Slight change to RSS URL tagging, now setting campaign to post name, and behaving better when not using rewritten URL's.
212
+ * Two patches by [Lee Willis](http://www.leewillis.co.uk):
213
+ * Made some changes so the entire plugin works fine with .co.uk, .co.za etc domains.
214
+ * Made sure internal blogroll links aren't tagged as external clicks.
215
+
216
+ = 3.2 =
217
+ * Added option to add tracking to add tracking to login / register pages, so you can track new signups (under Advanced settings).
218
+ * Added beta option to track Google image search as a search engine, needs more testing to make sure it works.
219
+ * Fixed a bug in the extra search engine tracking implementation.
220
+ * Removed redundant "More Info" section from readme.txt.
221
+
222
+ = 3.1.1 =
223
+ * Stupid typo that caused warnings.
224
+
225
+ = 3.1 =
226
+ * Added 404 tracking as described [here](http://www.google.com/support/googleanalytics/bin/answer.py?hl=en&answer=86927).
227
+ * Optimized the tracking script, if extra search engine tracking is disabled it'll be a lot smaller now.
228
+ * Various code optimizations to prevent PHP notices and removal of redundant code.
229
+
230
+ = 3.0.1 =
231
+ * Removed no longer needed code to add config page that caused PHP warnings.
232
+
233
+ = 3.0 =
234
+ * Major backend overhaul, using new Yoast backend class.
235
+ * Added ability to automatically redirect non hashtagged campaign URLs to hashtagged campaign URL's when setAllowAnchor is set to true (if you don't get it, forget about it, you might need it but don't need to worry)
236
+
237
+ = 2.9.5 =
238
+ * Fixed a bug with the included RSS, which came up when multiple Yoast plugins were installed.
239
+
240
+ = 2.9.4 =
241
+ * Changed to the new Changelog design.
242
+ * Removed pre 2.6 compatibility code, plugin now requires WP 2.6 or higher.
243
+ * Small changes to the admin screen.
244
+
245
+ = 2.9.3 =
246
+ * Added a new option for RSS link tagging, which allows you to tag your RSS feed links with RSS campaign variables. When you've set campaign variables to use # instead of ?, this will adhere to that setting too. Thanks to [Timan Rebel](http://rebelic.nl/) for the idea and code.
247
+
248
+ = 2.9.2: =
249
+ * Added a check to see whether the wp_footer() call is in footer.php.
250
+ * Added a message to the source when tracking code is left out because user is logged in as admin.
251
+ * Added option to segment logged in users.
252
+ * Added try - catch to script lines like in new Google Analytics scripts.
253
+ * Fixed bug in warning when no UA code is entered.
254
+ * Prevent link tracking when admin is logged in and admin tracking is disabled.
255
+ * Now prevents parsing of non http and https link.
256
+
257
+ = 2.9 =
258
+ * Re arranged admin panel to have "standard" and "advanced" settings.
259
+ * Added domain tracking.
260
+ * Added fix for double onclick parameter, as suggested [here](http://wordpress.org/support/topic/241757).
261
+
262
+ = 2.8 =
263
+ * Added the option to add setAllowAnchor to the tracking code, allowing you to track campaigns with # instead of ?.
264
+
265
+ = 2.7 =
266
+ * Added option to select either header of footer position.
267
+ * Added new AdSense integration options.
268
+ * Removed now unneeded adsense tracking script.
269
+
270
+ = 2.6.6=
271
+ * Fixed settings link.
272
+
273
+ = 2.6.5 =
274
+ * added Ozh admin menu icon and settings link.
275
+
276
+ = 2.6.4 =
277
+ * Fixes for 2.7.
278
+
279
+ = 2.6.3 =
280
+ * Fixed bug that didn't allow saving of outbound clicks from comments string.
281
+
282
+ = 2.6 =
283
+ * Fixed incompatibility with WP 2.6.
284
+
285
+ = 2.5.4 =
286
+ * Fixed an issue with pluginpath being used globally.
287
+ * Changed links to [new domain](http://yoast.com/).
288
+
289
+ = 2.2 =
290
+ * Switched to the new tracking code.
291
+
292
+ = 2.1 =
293
+ * Made sure tracking was disabled on preview pages.
294
+
295
+ = 2.0 =
296
+ * Added AdSense tracking.
297
+
298
+ = 1.5 =
299
+ * Added option to enable admin tracking, off by default.
300
+
301
+ == Frequently Asked Questions ==
302
+
303
+ = Can I run this plugin together with another Google Analytics plugin? =
304
+
305
+ No. You can not. It will break tracking.
306
+
307
+ = Another profile than the one I selected is showing as selected? =
308
+
309
+ You probably have multiple profiles for the same website, that share the same UA-code. If so, it doesn't matter which of the profiles is shown as selected, tracking will be correct.
310
+
311
+ = I've just installed the new tracking and Google Analytics says it's not receiving data yet? =
312
+
313
+ Give it a couple of hours, usually it'll be fixed. It can take up to 24 hours to appear though.
314
+
315
+ = Google Analytics says it's receiving data, but I don't see any stats yet? =
316
+
317
+ This can take up to 24 hours after the installation of the new tracking code.
318
+
319
+ = Why is the tracking code loaded in the head section of the site? =
320
+
321
+ Because that's where it belongs. It makes the page load faster (yes, faster, due to the asynchronous method of loading the script) and tracking more reliable. If you must place it in the footer anyway, switch to manual mode and check out the docs for [manual placement of the Google Analytics code](http://yoast.com/wordpress/google-analytics/manual-placement/).
322
+
323
+ == Screenshots ==
324
+
325
+ 1. Screenshot of the basic settings panel for this plugin.
326
+ 2. Screenshot of the custom variable settings panel.
327
+ 3. Screenshot of the link tracking panel.
328
+ 4. Screenshot of the advanced settings panel.
329
+ 5. Screenshot of the debugging mode in action.
330
+
331
+ == Upgrade Notice ==
332
+
333
+ = 4.0.11 =
334
+
335
+ You can now properly disable the comment form tracking, and the charset attribute on script tags is gone so you can validate as HTML5 too.
wp-gdata/OAuth.php ADDED
@@ -0,0 +1,895 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // vim: foldmethod=marker
3
+
4
+ /* Generic exception class
5
+ */
6
+ class OAuthException extends Exception {
7
+ // pass
8
+ }
9
+
10
+ class OAuthConsumer {
11
+ public $key;
12
+ public $secret;
13
+
14
+ function __construct($key, $secret, $callback_url=NULL) {
15
+ $this->key = $key;
16
+ $this->secret = $secret;
17
+ $this->callback_url = $callback_url;
18
+ }
19
+
20
+ function __toString() {
21
+ return "OAuthConsumer[key=$this->key,secret=$this->secret]";
22
+ }
23
+ }
24
+
25
+ class OAuthToken {
26
+ // access tokens and request tokens
27
+ public $key;
28
+ public $secret;
29
+
30
+ /**
31
+ * key = the token
32
+ * secret = the token secret
33
+ */
34
+ function __construct($key, $secret) {
35
+ $this->key = $key;
36
+ $this->secret = $secret;
37
+ }
38
+
39
+ /**
40
+ * generates the basic string serialization of a token that a server
41
+ * would respond to request_token and access_token calls with
42
+ */
43
+ function to_string() {
44
+ return "oauth_token=" .
45
+ OAuthUtil::urlencode_rfc3986($this->key) .
46
+ "&oauth_token_secret=" .
47
+ OAuthUtil::urlencode_rfc3986($this->secret);
48
+ }
49
+
50
+ function __toString() {
51
+ return $this->to_string();
52
+ }
53
+ }
54
+
55
+ /**
56
+ * A class for implementing a Signature Method
57
+ * See section 9 ("Signing Requests") in the spec
58
+ */
59
+ abstract class OAuthSignatureMethod {
60
+ /**
61
+ * Needs to return the name of the Signature Method (ie HMAC-SHA1)
62
+ * @return string
63
+ */
64
+ abstract public function get_name();
65
+
66
+ /**
67
+ * Build up the signature
68
+ * NOTE: The output of this function MUST NOT be urlencoded.
69
+ * the encoding is handled in OAuthRequest when the final
70
+ * request is serialized
71
+ * @param OAuthRequest $request
72
+ * @param OAuthConsumer $consumer
73
+ * @param OAuthToken $token
74
+ * @return string
75
+ */
76
+ abstract public function build_signature($request, $consumer, $token);
77
+
78
+ /**
79
+ * Verifies that a given signature is correct
80
+ * @param OAuthRequest $request
81
+ * @param OAuthConsumer $consumer
82
+ * @param OAuthToken $token
83
+ * @param string $signature
84
+ * @return bool
85
+ */
86
+ public function check_signature($request, $consumer, $token, $signature) {
87
+ $built = $this->build_signature($request, $consumer, $token);
88
+
89
+ // Check for zero length, although unlikely here
90
+ if (strlen($built) == 0 || strlen($signature) == 0) {
91
+ return false;
92
+ }
93
+
94
+ if (strlen($built) != strlen($signature)) {
95
+ return false;
96
+ }
97
+
98
+ // Avoid a timing leak with a (hopefully) time insensitive compare
99
+ $result = 0;
100
+ for ($i = 0; $i < strlen($signature); $i++) {
101
+ $result |= ord($built{$i}) ^ ord($signature{$i});
102
+ }
103
+
104
+ return $result == 0;
105
+ }
106
+ }
107
+
108
+ /**
109
+ * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104]
110
+ * where the Signature Base String is the text and the key is the concatenated values (each first
111
+ * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&'
112
+ * character (ASCII code 38) even if empty.
113
+ * - Chapter 9.2 ("HMAC-SHA1")
114
+ */
115
+ class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {
116
+ function get_name() {
117
+ return "HMAC-SHA1";
118
+ }
119
+
120
+ public function build_signature($request, $consumer, $token) {
121
+ $base_string = $request->get_signature_base_string();
122
+ $request->base_string = $base_string;
123
+
124
+ $key_parts = array(
125
+ $consumer->secret,
126
+ ($token) ? $token->secret : ""
127
+ );
128
+
129
+ $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
130
+ $key = implode('&', $key_parts);
131
+
132
+ return base64_encode(hash_hmac('sha1', $base_string, $key, true));
133
+ }
134
+ }
135
+
136
+ /**
137
+ * The PLAINTEXT method does not provide any security protection and SHOULD only be used
138
+ * over a secure channel such as HTTPS. It does not use the Signature Base String.
139
+ * - Chapter 9.4 ("PLAINTEXT")
140
+ */
141
+ class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod {
142
+ public function get_name() {
143
+ return "PLAINTEXT";
144
+ }
145
+
146
+ /**
147
+ * oauth_signature is set to the concatenated encoded values of the Consumer Secret and
148
+ * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is
149
+ * empty. The result MUST be encoded again.
150
+ * - Chapter 9.4.1 ("Generating Signatures")
151
+ *
152
+ * Please note that the second encoding MUST NOT happen in the SignatureMethod, as
153
+ * OAuthRequest handles this!
154
+ */
155
+ public function build_signature($request, $consumer, $token) {
156
+ $key_parts = array(
157
+ $consumer->secret,
158
+ ($token) ? $token->secret : ""
159
+ );
160
+
161
+ $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
162
+ $key = implode('&', $key_parts);
163
+ $request->base_string = $key;
164
+
165
+ return $key;
166
+ }
167
+ }
168
+
169
+ /**
170
+ * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in
171
+ * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for
172
+ * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a
173
+ * verified way to the Service Provider, in a manner which is beyond the scope of this
174
+ * specification.
175
+ * - Chapter 9.3 ("RSA-SHA1")
176
+ */
177
+ abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod {
178
+ public function get_name() {
179
+ return "RSA-SHA1";
180
+ }
181
+
182
+ // Up to the SP to implement this lookup of keys. Possible ideas are:
183
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
184
+ // (2) fetch via http using a url provided by the requester
185
+ // (3) some sort of specific discovery code based on request
186
+ //
187
+ // Either way should return a string representation of the certificate
188
+ protected abstract function fetch_public_cert(&$request);
189
+
190
+ // Up to the SP to implement this lookup of keys. Possible ideas are:
191
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
192
+ //
193
+ // Either way should return a string representation of the certificate
194
+ protected abstract function fetch_private_cert(&$request);
195
+
196
+ public function build_signature($request, $consumer, $token) {
197
+ $base_string = $request->get_signature_base_string();
198
+ $request->base_string = $base_string;
199
+
200
+ // Fetch the private key cert based on the request
201
+ $cert = $this->fetch_private_cert($request);
202
+
203
+ // Pull the private key ID from the certificate
204
+ $privatekeyid = openssl_get_privatekey($cert);
205
+
206
+ // Sign using the key
207
+ $ok = openssl_sign($base_string, $signature, $privatekeyid);
208
+
209
+ // Release the key resource
210
+ openssl_free_key($privatekeyid);
211
+
212
+ return base64_encode($signature);
213
+ }
214
+
215
+ public function check_signature($request, $consumer, $token, $signature) {
216
+ $decoded_sig = base64_decode($signature);
217
+
218
+ $base_string = $request->get_signature_base_string();
219
+
220
+ // Fetch the public key cert based on the request
221
+ $cert = $this->fetch_public_cert($request);
222
+
223
+ // Pull the public key ID from the certificate
224
+ $publickeyid = openssl_get_publickey($cert);
225
+
226
+ // Check the computed signature against the one passed in the query
227
+ $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
228
+
229
+ // Release the key resource
230
+ openssl_free_key($publickeyid);
231
+
232
+ return $ok == 1;
233
+ }
234
+ }
235
+
236
+ class OAuthRequest {
237
+ protected $parameters;
238
+ protected $http_method;
239
+ protected $http_url;
240
+ // for debug purposes
241
+ public $base_string;
242
+ public static $version = '1.0';
243
+ public static $POST_INPUT = 'php://input';
244
+
245
+ function __construct($http_method, $http_url, $parameters=NULL) {
246
+ $parameters = ($parameters) ? $parameters : array();
247
+ $parameters = array_merge( OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters);
248
+ $this->parameters = $parameters;
249
+ $this->http_method = $http_method;
250
+ $this->http_url = $http_url;
251
+ }
252
+
253
+
254
+ /**
255
+ * attempt to build up a request from what was passed to the server
256
+ */
257
+ public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) {
258
+ $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on")
259
+ ? 'http'
260
+ : 'https';
261
+ $http_url = ($http_url) ? $http_url : $scheme .
262
+ '://' . $_SERVER['SERVER_NAME'] .
263
+ ':' .
264
+ $_SERVER['SERVER_PORT'] .
265
+ $_SERVER['REQUEST_URI'];
266
+ $http_method = ($http_method) ? $http_method : $_SERVER['REQUEST_METHOD'];
267
+
268
+ // We weren't handed any parameters, so let's find the ones relevant to
269
+ // this request.
270
+ // If you run XML-RPC or similar you should use this to provide your own
271
+ // parsed parameter-list
272
+ if (!$parameters) {
273
+ // Find request headers
274
+ $request_headers = OAuthUtil::get_headers();
275
+
276
+ // Parse the query-string to find GET parameters
277
+ $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']);
278
+
279
+ // It's a POST request of the proper content-type, so parse POST
280
+ // parameters and add those overriding any duplicates from GET
281
+ if ($http_method == "POST"
282
+ && isset($request_headers['Content-Type'])
283
+ && strstr($request_headers['Content-Type'],
284
+ 'application/x-www-form-urlencoded')
285
+ ) {
286
+ $post_data = OAuthUtil::parse_parameters(
287
+ file_get_contents(self::$POST_INPUT)
288
+ );
289
+ $parameters = array_merge($parameters, $post_data);
290
+ }
291
+
292
+ // We have a Authorization-header with OAuth data. Parse the header
293
+ // and add those overriding any duplicates from GET or POST
294
+ if (isset($request_headers['Authorization']) && substr($request_headers['Authorization'], 0, 6) == 'OAuth ') {
295
+ $header_parameters = OAuthUtil::split_header(
296
+ $request_headers['Authorization']
297
+ );
298
+ $parameters = array_merge($parameters, $header_parameters);
299
+ }
300
+
301
+ }
302
+
303
+ return new OAuthRequest($http_method, $http_url, $parameters);
304
+ }
305
+
306
+ /**
307
+ * pretty much a helper function to set up the request
308
+ */
309
+ public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {
310
+ $parameters = ($parameters) ? $parameters : array();
311
+ $defaults = array("oauth_version" => OAuthRequest::$version,
312
+ "oauth_nonce" => OAuthRequest::generate_nonce(),
313
+ "oauth_timestamp" => OAuthRequest::generate_timestamp(),
314
+ "oauth_consumer_key" => $consumer->key);
315
+ if ($token)
316
+ $defaults['oauth_token'] = $token->key;
317
+
318
+ $parameters = array_merge($defaults, $parameters);
319
+
320
+ return new OAuthRequest($http_method, $http_url, $parameters);
321
+ }
322
+
323
+ public function set_parameter($name, $value, $allow_duplicates = true) {
324
+ if ($allow_duplicates && isset($this->parameters[$name])) {
325
+ // We have already added parameter(s) with this name, so add to the list
326
+ if (is_scalar($this->parameters[$name])) {
327
+ // This is the first duplicate, so transform scalar (string)
328
+ // into an array so we can add the duplicates
329
+ $this->parameters[$name] = array($this->parameters[$name]);
330
+ }
331
+
332
+ $this->parameters[$name][] = $value;
333
+ } else {
334
+ $this->parameters[$name] = $value;
335
+ }
336
+ }
337
+
338
+ public function get_parameter($name) {
339
+ return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
340
+ }
341
+
342
+ public function get_parameters() {
343
+ return $this->parameters;
344
+ }
345
+
346
+ public function unset_parameter($name) {
347
+ unset($this->parameters[$name]);
348
+ }
349
+
350
+ /**
351
+ * The request parameters, sorted and concatenated into a normalized string.
352
+ * @return string
353
+ */
354
+ public function get_signable_parameters() {
355
+ // Grab all parameters
356
+ $params = $this->parameters;
357
+
358
+ // Remove oauth_signature if present
359
+ // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
360
+ if (isset($params['oauth_signature'])) {
361
+ unset($params['oauth_signature']);
362
+ }
363
+
364
+ return OAuthUtil::build_http_query($params);
365
+ }
366
+
367
+ /**
368
+ * Returns the base string of this request
369
+ *
370
+ * The base string defined as the method, the url
371
+ * and the parameters (normalized), each urlencoded
372
+ * and the concated with &.
373
+ */
374
+ public function get_signature_base_string() {
375
+ $parts = array(
376
+ $this->get_normalized_http_method(),
377
+ $this->get_normalized_http_url(),
378
+ $this->get_signable_parameters()
379
+ );
380
+
381
+ $parts = OAuthUtil::urlencode_rfc3986($parts);
382
+
383
+ return implode('&', $parts);
384
+ }
385
+
386
+ /**
387
+ * just uppercases the http method
388
+ */
389
+ public function get_normalized_http_method() {
390
+ return strtoupper($this->http_method);
391
+ }
392
+
393
+ /**
394
+ * parses the url and rebuilds it to be
395
+ * scheme://host/path
396
+ */
397
+ public function get_normalized_http_url() {
398
+ $parts = parse_url($this->http_url);
399
+
400
+ $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
401
+ $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80');
402
+ $host = (isset($parts['host'])) ? strtolower($parts['host']) : '';
403
+ $path = (isset($parts['path'])) ? $parts['path'] : '';
404
+
405
+ if (($scheme == 'https' && $port != '443')
406
+ || ($scheme == 'http' && $port != '80')) {
407
+ $host = "$host:$port";
408
+ }
409
+ return "$scheme://$host$path";
410
+ }
411
+
412
+ /**
413
+ * builds a url usable for a GET request
414
+ */
415
+ public function to_url() {
416
+ $post_data = $this->to_postdata();
417
+ $out = $this->get_normalized_http_url();
418
+ if ($post_data) {
419
+ $out .= '?'.$post_data;
420
+ }
421
+ return $out;
422
+ }
423
+
424
+ /**
425
+ * builds the data one would send in a POST request
426
+ */
427
+ public function to_postdata() {
428
+ return OAuthUtil::build_http_query($this->parameters);
429
+ }
430
+
431
+ /**
432
+ * builds the Authorization: header
433
+ */
434
+ public function to_header($realm=null) {
435
+ $first = true;
436
+ if($realm) {
437
+ $out = 'Authorization: OAuth realm="' . OAuthUtil::urlencode_rfc3986($realm) . '"';
438
+ $first = false;
439
+ } else
440
+ $out = 'Authorization: OAuth';
441
+
442
+ $total = array();
443
+ foreach ($this->parameters as $k => $v) {
444
+ if (substr($k, 0, 5) != "oauth") continue;
445
+ if (is_array($v)) {
446
+ throw new OAuthException('Arrays not supported in headers');
447
+ }
448
+ $out .= ($first) ? ' ' : ',';
449
+ $out .= OAuthUtil::urlencode_rfc3986($k) .
450
+ '="' .
451
+ OAuthUtil::urlencode_rfc3986($v) .
452
+ '"';
453
+ $first = false;
454
+ }
455
+ return $out;
456
+ }
457
+
458
+ public function __toString() {
459
+ return $this->to_url();
460
+ }
461
+
462
+
463
+ public function sign_request($signature_method, $consumer, $token) {
464
+ $this->set_parameter(
465
+ "oauth_signature_method",
466
+ $signature_method->get_name(),
467
+ false
468
+ );
469
+ $signature = $this->build_signature($signature_method, $consumer, $token);
470
+ $this->set_parameter("oauth_signature", $signature, false);
471
+ }
472
+
473
+ public function build_signature($signature_method, $consumer, $token) {
474
+ $signature = $signature_method->build_signature($this, $consumer, $token);
475
+ return $signature;
476
+ }
477
+
478
+ /**
479
+ * util function: current timestamp
480
+ */
481
+ private static function generate_timestamp() {
482
+ return time();
483
+ }
484
+
485
+ /**
486
+ * util function: current nonce
487
+ */
488
+ private static function generate_nonce() {
489
+ $mt = microtime();
490
+ $rand = mt_rand();
491
+
492
+ return md5($mt . $rand); // md5s look nicer than numbers
493
+ }
494
+ }
495
+
496
+ class OAuthServer {
497
+ protected $timestamp_threshold = 300; // in seconds, five minutes
498
+ protected $version = '1.0'; // hi blaine
499
+ protected $signature_methods = array();
500
+
501
+ protected $data_store;
502
+
503
+ function __construct($data_store) {
504
+ $this->data_store = $data_store;
505
+ }
506
+
507
+ public function add_signature_method($signature_method) {
508
+ $this->signature_methods[$signature_method->get_name()] =
509
+ $signature_method;
510
+ }
511
+
512
+ // high level functions
513
+
514
+ /**
515
+ * process a request_token request
516
+ * returns the request token on success
517
+ */
518
+ public function fetch_request_token(&$request) {
519
+ $this->get_version($request);
520
+
521
+ $consumer = $this->get_consumer($request);
522
+
523
+ // no token required for the initial token request
524
+ $token = NULL;
525
+
526
+ $this->check_signature($request, $consumer, $token);
527
+
528
+ // Rev A change
529
+ $callback = $request->get_parameter('oauth_callback');
530
+ $new_token = $this->data_store->new_request_token($consumer, $callback);
531
+
532
+ return $new_token;
533
+ }
534
+
535
+ /**
536
+ * process an access_token request
537
+ * returns the access token on success
538
+ */
539
+ public function fetch_access_token(&$request) {
540
+ $this->get_version($request);
541
+
542
+ $consumer = $this->get_consumer($request);
543
+
544
+ // requires authorized request token
545
+ $token = $this->get_token($request, $consumer, "request");
546
+
547
+ $this->check_signature($request, $consumer, $token);
548
+
549
+ // Rev A change
550
+ $verifier = $request->get_parameter('oauth_verifier');
551
+ $new_token = $this->data_store->new_access_token($token, $consumer, $verifier);
552
+
553
+ return $new_token;
554
+ }
555
+
556
+ /**
557
+ * verify an api call, checks all the parameters
558
+ */
559
+ public function verify_request(&$request) {
560
+ $this->get_version($request);
561
+ $consumer = $this->get_consumer($request);
562
+ $token = $this->get_token($request, $consumer, "access");
563
+ $this->check_signature($request, $consumer, $token);
564
+ return array($consumer, $token);
565
+ }
566
+
567
+ // Internals from here
568
+ /**
569
+ * version 1
570
+ */
571
+ private function get_version(&$request) {
572
+ $version = $request->get_parameter("oauth_version");
573
+ if (!$version) {
574
+ // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present.
575
+ // Chapter 7.0 ("Accessing Protected Ressources")
576
+ $version = '1.0';
577
+ }
578
+ if ($version !== $this->version) {
579
+ throw new OAuthException("OAuth version '$version' not supported");
580
+ }
581
+ return $version;
582
+ }
583
+
584
+ /**
585
+ * figure out the signature with some defaults
586
+ */
587
+ private function get_signature_method($request) {
588
+ $signature_method = $request instanceof OAuthRequest
589
+ ? $request->get_parameter("oauth_signature_method")
590
+ : NULL;
591
+
592
+ if (!$signature_method) {
593
+ // According to chapter 7 ("Accessing Protected Ressources") the signature-method
594
+ // parameter is required, and we can't just fallback to PLAINTEXT
595
+ throw new OAuthException('No signature method parameter. This parameter is required');
596
+ }
597
+
598
+ if (!in_array($signature_method,
599
+ array_keys($this->signature_methods))) {
600
+ throw new OAuthException(
601
+ "Signature method '$signature_method' not supported " .
602
+ "try one of the following: " .
603
+ implode(", ", array_keys($this->signature_methods))
604
+ );
605
+ }
606
+ return $this->signature_methods[$signature_method];
607
+ }
608
+
609
+ /**
610
+ * try to find the consumer for the provided request's consumer key
611
+ */
612
+ private function get_consumer($request) {
613
+ $consumer_key = $request instanceof OAuthRequest
614
+ ? $request->get_parameter("oauth_consumer_key")
615
+ : NULL;
616
+
617
+ if (!$consumer_key) {
618
+ throw new OAuthException("Invalid consumer key");
619
+ }
620
+
621
+ $consumer = $this->data_store->lookup_consumer($consumer_key);
622
+ if (!$consumer) {
623
+ throw new OAuthException("Invalid consumer");
624
+ }
625
+
626
+ return $consumer;
627
+ }
628
+
629
+ /**
630
+ * try to find the token for the provided request's token key
631
+ */
632
+ private function get_token($request, $consumer, $token_type="access") {
633
+ $token_field = $request instanceof OAuthRequest
634
+ ? $request->get_parameter('oauth_token')
635
+ : NULL;
636
+
637
+ $token = $this->data_store->lookup_token(
638
+ $consumer, $token_type, $token_field
639
+ );
640
+ if (!$token) {
641
+ throw new OAuthException("Invalid $token_type token: $token_field");
642
+ }
643
+ return $token;
644
+ }
645
+
646
+ /**
647
+ * all-in-one function to check the signature on a request
648
+ * should guess the signature method appropriately
649
+ */
650
+ private function check_signature($request, $consumer, $token) {
651
+ // this should probably be in a different method
652
+ $timestamp = $request instanceof OAuthRequest
653
+ ? $request->get_parameter('oauth_timestamp')
654
+ : NULL;
655
+ $nonce = $request instanceof OAuthRequest
656
+ ? $request->get_parameter('oauth_nonce')
657
+ : NULL;
658
+
659
+ $this->check_timestamp($timestamp);
660
+ $this->check_nonce($consumer, $token, $nonce, $timestamp);
661
+
662
+ $signature_method = $this->get_signature_method($request);
663
+
664
+ $signature = $request->get_parameter('oauth_signature');
665
+ $valid_sig = $signature_method->check_signature(
666
+ $request,
667
+ $consumer,
668
+ $token,
669
+ $signature
670
+ );
671
+
672
+ if (!$valid_sig) {
673
+ throw new OAuthException("Invalid signature");
674
+ }
675
+ }
676
+
677
+ /**
678
+ * check that the timestamp is new enough
679
+ */
680
+ private function check_timestamp($timestamp) {
681
+ if( ! $timestamp )
682
+ throw new OAuthException(
683
+ 'Missing timestamp parameter. The parameter is required'
684
+ );
685
+
686
+ // verify that timestamp is recentish
687
+ $now = time();
688
+ if (abs($now - $timestamp) > $this->timestamp_threshold) {
689
+ throw new OAuthException(
690
+ "Expired timestamp, yours $timestamp, ours $now"
691
+ );
692
+ }
693
+ }
694
+
695
+ /**
696
+ * check that the nonce is not repeated
697
+ */
698
+ private function check_nonce($consumer, $token, $nonce, $timestamp) {
699
+ if( ! $nonce )
700
+ throw new OAuthException(
701
+ 'Missing nonce parameter. The parameter is required'
702
+ );
703
+
704
+ // verify that the nonce is uniqueish
705
+ $found = $this->data_store->lookup_nonce(
706
+ $consumer,
707
+ $token,
708
+ $nonce,
709
+ $timestamp
710
+ );
711
+ if ($found) {
712
+ throw new OAuthException("Nonce already used: $nonce");
713
+ }
714
+ }
715
+
716
+ }
717
+
718
+ class OAuthDataStore {
719
+ function lookup_consumer($consumer_key) {
720
+ // implement me
721
+ }
722
+
723
+ function lookup_token($consumer, $token_type, $token) {
724
+ // implement me
725
+ }
726
+
727
+ function lookup_nonce($consumer, $token, $nonce, $timestamp) {
728
+ // implement me
729
+ }
730
+
731
+ function new_request_token($consumer, $callback = null) {
732
+ // return a new token attached to this consumer
733
+ }
734
+
735
+ function new_access_token($token, $consumer, $verifier = null) {
736
+ // return a new access token attached to this consumer
737
+ // for the user associated with this token if the request token
738
+ // is authorized
739
+ // should also invalidate the request token
740
+ }
741
+
742
+ }
743
+
744
+ class OAuthUtil {
745
+ public static function urlencode_rfc3986($input) {
746
+ if (is_array($input)) {
747
+ return array_map(array('OAuthUtil', 'urlencode_rfc3986'), $input);
748
+ } else if (is_scalar($input)) {
749
+ return str_replace(
750
+ '+',
751
+ ' ',
752
+ str_replace('%7E', '~', rawurlencode($input))
753
+ );
754
+ } else {
755
+ return '';
756
+ }
757
+ }
758
+
759
+
760
+ // This decode function isn't taking into consideration the above
761
+ // modifications to the encoding process. However, this method doesn't
762
+ // seem to be used anywhere so leaving it as is.
763
+ public static function urldecode_rfc3986($string) {
764
+ return urldecode($string);
765
+ }
766
+
767
+ // Utility function for turning the Authorization: header into
768
+ // parameters, has to do some unescaping
769
+ // Can filter out any non-oauth parameters if needed (default behaviour)
770
+ // May 28th, 2010 - method updated to tjerk.meesters for a speed improvement.
771
+ // see http://code.google.com/p/oauth/issues/detail?id=163
772
+ public static function split_header($header, $only_allow_oauth_parameters = true) {
773
+ $params = array();
774
+ if (preg_match_all('/('.($only_allow_oauth_parameters ? 'oauth_' : '').'[a-z_-]*)=(:?"([^"]*)"|([^,]*))/', $header, $matches)) {
775
+ foreach ($matches[1] as $i => $h) {
776
+ $params[$h] = OAuthUtil::urldecode_rfc3986(empty($matches[3][$i]) ? $matches[4][$i] : $matches[3][$i]);
777
+ }
778
+ if (isset($params['realm'])) {
779
+ unset($params['realm']);
780
+ }
781
+ }
782
+ return $params;
783
+ }
784
+
785
+ // helper to try to sort out headers for people who aren't running apache
786
+ public static function get_headers() {
787
+ if (function_exists('apache_request_headers')) {
788
+ // we need this to get the actual Authorization: header
789
+ // because apache tends to tell us it doesn't exist
790
+ $headers = apache_request_headers();
791
+
792
+ // sanitize the output of apache_request_headers because
793
+ // we always want the keys to be Cased-Like-This and arh()
794
+ // returns the headers in the same case as they are in the
795
+ // request
796
+ $out = array();
797
+ foreach ($headers AS $key => $value) {
798
+ $key = str_replace(
799
+ " ",
800
+ "-",
801
+ ucwords(strtolower(str_replace("-", " ", $key)))
802
+ );
803
+ $out[$key] = $value;
804
+ }
805
+ } else {
806
+ // otherwise we don't have apache and are just going to have to hope
807
+ // that $_SERVER actually contains what we need
808
+ $out = array();
809
+ if( isset($_SERVER['CONTENT_TYPE']) )
810
+ $out['Content-Type'] = $_SERVER['CONTENT_TYPE'];
811
+ if( isset($_ENV['CONTENT_TYPE']) )
812
+ $out['Content-Type'] = $_ENV['CONTENT_TYPE'];
813
+
814
+ foreach ($_SERVER as $key => $value) {
815
+ if (substr($key, 0, 5) == "HTTP_") {
816
+ // this is chaos, basically it is just there to capitalize the first
817
+ // letter of every word that is not an initial HTTP and strip HTTP
818
+ // code from przemek
819
+ $key = str_replace(
820
+ " ",
821
+ "-",
822
+ ucwords(strtolower(str_replace("_", " ", substr($key, 5))))
823
+ );
824
+ $out[$key] = $value;
825
+ }
826
+ }
827
+ }
828
+ return $out;
829
+ }
830
+
831
+ // This function takes a input like a=b&a=c&d=e and returns the parsed
832
+ // parameters like this
833
+ // array('a' => array('b','c'), 'd' => 'e')
834
+ public static function parse_parameters( $input ) {
835
+ if (!isset($input) || !$input) return array();
836
+
837
+ $pairs = explode('&', $input);
838
+
839
+ $parsed_parameters = array();
840
+ foreach ($pairs as $pair) {
841
+ $split = explode('=', $pair, 2);
842
+ $parameter = OAuthUtil::urldecode_rfc3986($split[0]);
843
+ $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : '';
844
+
845
+ if (isset($parsed_parameters[$parameter])) {
846
+ // We have already recieved parameter(s) with this name, so add to the list
847
+ // of parameters with this name
848
+
849
+ if (is_scalar($parsed_parameters[$parameter])) {
850
+ // This is the first duplicate, so transform scalar (string) into an array
851
+ // so we can add the duplicates
852
+ $parsed_parameters[$parameter] = array($parsed_parameters[$parameter]);
853
+ }
854
+
855
+ $parsed_parameters[$parameter][] = $value;
856
+ } else {
857
+ $parsed_parameters[$parameter] = $value;
858
+ }
859
+ }
860
+ return $parsed_parameters;
861
+ }
862
+
863
+ public static function build_http_query($params) {
864
+ if (!$params) return '';
865
+
866
+ // Urlencode both keys and values
867
+ $keys = OAuthUtil::urlencode_rfc3986(array_keys($params));
868
+ $values = OAuthUtil::urlencode_rfc3986(array_values($params));
869
+ $params = array_combine($keys, $values);
870
+
871
+ // Parameters are sorted by name, using lexicographical byte value ordering.
872
+ // Ref: Spec: 9.1.1 (1)
873
+ uksort($params, 'strcmp');
874
+
875
+ $pairs = array();
876
+ foreach ($params as $parameter => $value) {
877
+ if (is_array($value)) {
878
+ // If two or more parameters share the same name, they are sorted by their value
879
+ // Ref: Spec: 9.1.1 (1)
880
+ // June 12th, 2010 - changed to sort because of issue 164 by hidetaka
881
+ sort($value, SORT_STRING);
882
+ foreach ($value as $duplicate_value) {
883
+ $pairs[] = $parameter . '=' . $duplicate_value;
884
+ }
885
+ } else {
886
+ $pairs[] = $parameter . '=' . $value;
887
+ }
888
+ }
889
+ // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61)
890
+ // Each name-value pair is separated by an '&' character (ASCII code 38)
891
+ return implode('&', $pairs);
892
+ }
893
+ }
894
+
895
+ ?>
wp-gdata/wp-gdata.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WP_GData - WordPress Google Data API Library
4
+ *
5
+ * @author Pete Mall
6
+ */
7
+
8
+ // Load the OAuth library.
9
+ if ( ! class_exists( 'OAuthConsumer' ) )
10
+ require( 'OAuth.php' );
11
+
12
+ class WP_GData {
13
+ /* Contains the last HTTP status code returned. */
14
+ public $http_code;
15
+
16
+ const request_token_url = 'https://www.google.com/accounts/OAuthGetRequestToken';
17
+ const authorize_url = 'https://www.google.com/accounts/OAuthAuthorizeToken';
18
+ const access_token_url = 'https://www.google.com/accounts/OAuthGetAccessToken';
19
+
20
+ function __construct( $parameters = array(), $oauth_token = null, $oauth_token_secret = null ) {
21
+ $this->parameters = $parameters;
22
+ $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1();
23
+ $this->consumer = new OAuthConsumer( 'anonymous', 'anonymous' );
24
+
25
+ if ( !empty( $oauth_token ) && !empty( $oauth_token_secret ) )
26
+ $this->token = new OAuthConsumer( $oauth_token, $oauth_token_secret );
27
+ else
28
+ $this->token = null;
29
+ }
30
+
31
+ function get_request_token( $oauth_callback = null ) {
32
+ $parameters = $this->parameters;
33
+ if ( !empty( $oauth_callback ) )
34
+ $parameters['oauth_callback'] = $oauth_callback;
35
+
36
+ $request = $this->oauth_request( self::request_token_url, 'GET', $parameters );
37
+ $token = OAuthUtil::parse_parameters( wp_remote_retrieve_body( $request ) );
38
+ $this->token = new OAuthConsumer( $token['oauth_token'], $token['oauth_token_secret'] );
39
+ return $token;
40
+ }
41
+
42
+ /**
43
+ * Format and sign an OAuth / API request
44
+ */
45
+ private function oauth_request( $url, $method, $parameters ) {
46
+ $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->token, $method, $url, $parameters );
47
+ $request->sign_request( $this->signature_method, $this->consumer, $this->token );
48
+
49
+ if ( 'GET' == $method )
50
+ return wp_remote_get( $request->to_url() );
51
+ else
52
+ return wp_remote_post( $request->to_url(), $request->to_postdata() );
53
+ }
54
+
55
+ function get_authorize_url( $token ) {
56
+ if ( is_array( $token ) )
57
+ $token = $token['oauth_token'];
58
+
59
+ return self::authorize_url . "?oauth_token={$token}";
60
+ }
61
+
62
+ /**
63
+ * Exchange request token and secret for an access token and
64
+ * secret, to sign API calls.
65
+ *
66
+ * @returns array( 'oauth_token' => 'the-access-token',
67
+ * 'oauth_token_secret' => 'the-access-secret' )
68
+ */
69
+ function get_access_token( $oauth_verifier = '' ) {
70
+ $parameters = array();
71
+ if ( !empty( $oauth_verifier ) )
72
+ $parameters['oauth_verifier'] = $oauth_verifier;
73
+
74
+ $request = $this->oauth_request( self::access_token_url, 'GET', $parameters );
75
+ $token = OAuthUtil::parse_parameters( wp_remote_retrieve_body( $request ) );
76
+ $this->token = new OAuthConsumer( $token['oauth_token'], $token['oauth_token_secret'] );
77
+ return $token;
78
+ }
79
+
80
+ /**
81
+ * GET wrapper for oAuthRequest.
82
+ */
83
+ public function get( $url, $parameters = array() ) {
84
+ return $this->oauth_request( $url, 'GET', $parameters );
85
+ }
86
+
87
+ /**
88
+ * POST wrapper for oAuthRequest.
89
+ */
90
+ public function post( $url, $parameters = array() ) {
91
+ $defaults = array(
92
+ 'method' => 'POST',
93
+ 'timeout' => 30,
94
+ 'redirection' => 5,
95
+ 'httpversion' => '1.0',
96
+ 'blocking' => true,
97
+ 'body' => array(),
98
+ 'headers' => array(),
99
+ 'cookies' => array()
100
+ );
101
+ $parameters = array_merge( $defaults, $parameters );
102
+
103
+ return $this->oauth_request( $url, 'POST', $parameters );
104
+ }
105
+ }
yst_plugin_tools.css CHANGED
@@ -1,81 +1,96 @@
1
- td.yst_desc {
2
- font-weight: normal;
3
- font-size: 12px;
4
- line-height: 12px;
5
- color:#777;
6
- }
7
-
8
- tr.yst_row {
9
- padding: 5px 0 0 0;
10
- margin: 5px 0 0 0;
11
- }
12
- tr.yst_row.even {
13
- background-color: #f6f6f6;
14
- }
15
-
16
- div.inside ul {
17
- margin-left: 20px;
18
- }
19
-
20
- div.inside ul li {
21
- list-style: square;
22
- line-height:16px;
23
- }
24
-
25
- div.inside a, div.inside a.rsswidget {
26
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
27
- text-decoration: none;
28
- }
29
- div.inside a:hover, div.inside a.rsswidget:hover {
30
- text-decoration: underline;
31
- }
32
- div.inside ul li.rss {
33
- list-style-image: url(images/rss.png);
34
- }
35
-
36
- div.inside ul li.email {
37
- list-style-image: url(images/email_sub.png);
38
- }
39
-
40
- div.inside ul li.yoast {
41
- list-style-image: url(images/yoast-16x16.png);
42
- }
43
-
44
- .text, .select {
45
- width: 250px;
46
- }
47
-
48
- .postbox p {
49
- text-align:left;
50
- margin: 0 10px 10px 10px;
51
- font-size: 13px;
52
- line-height: 150%;
53
- }
54
-
55
- .postbox pre {
56
- margin: 5px 10px;
57
- padding:4px;
58
- background: lightyellow;
59
- }
60
-
61
- .side .postbox p, .side .postbox a, .side .postbox a.rsswidget {
62
- font-size: 11px;
63
- }
64
 
65
- div.inside .button:hover, div.inside .button-primary:hover {
66
- text-decoration: none;
67
  }
68
 
69
- .button, .button-primary {
70
- margin-top: 10px;
71
  }
72
 
73
- .postbox#donate {
74
- border-color: green;
75
- border-width: 2px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  }
77
- strong.red {
78
- color: green;
79
- font-weight: bold;
80
- font-size: 105%;
81
- }
1
+ td.yst_desc {
2
+ font-weight: normal;
3
+ font-size: 12px;
4
+ line-height: 12px;
5
+ color:#777;
6
+ }
7
+
8
+ tr.yst_row {
9
+ padding: 5px 0 0 0;
10
+ margin: 5px 0 0 0;
11
+ }
12
+ tr.yst_row.even {
13
+ background-color: #f6f6f6;
14
+ }
15
+
16
+ div.inside ul {
17
+ margin-left: 20px;
18
+ }
19
+
20
+ div.inside ul li {
21
+ list-style: square;
22
+ line-height:16px;
23
+ }
24
+
25
+ div.inside a, div.inside a.rsswidget {
26
+ font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
27
+ text-decoration: none;
28
+ }
29
+ div.inside a:hover, div.inside a.rsswidget:hover {
30
+ text-decoration: underline;
31
+ }
32
+ div.inside ul li.rss {
33
+ list-style-image: url(images/rss.png);
34
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
+ div.inside ul li.twitter {
37
+ list-style-image: url(images/twitter-icon.png);
38
  }
39
 
40
+ div.inside ul li.facebook {
41
+ list-style-image: url(images/facebook-icon.png);
42
  }
43
 
44
+ div.inside ul li.googleplus {
45
+ list-style-image: url(images/google-plus-icon.png);
46
+ }
47
+
48
+ div.inside ul li.email {
49
+ list-style-image: url(images/email_sub.png);
50
+ }
51
+
52
+ div.inside ul li.yoast {
53
+ list-style-image: url(images/yoast-16x16.png);
54
+ }
55
+
56
+ .text, .select {
57
+ width: 250px;
58
+ }
59
+
60
+ .postbox p {
61
+ text-align:left;
62
+ margin: 0 10px 10px 10px;
63
+ font-size: 13px;
64
+ line-height: 150%;
65
+ }
66
+
67
+ .postbox pre {
68
+ margin: 5px 10px;
69
+ padding:4px;
70
+ background: lightyellow;
71
+ }
72
+
73
+ .side .postbox p, .side .postbox a, .side .postbox a.rsswidget {
74
+ font-size: 11px;
75
+ }
76
+
77
+ div.inside .button:hover, div.inside .button-primary:hover {
78
+ text-decoration: none;
79
+ }
80
+
81
+ .button, .button-primary {
82
+ margin-top: 10px;
83
+ }
84
+
85
+ .postbox#donate {
86
+ border-color: green;
87
+ border-width: 2px;
88
+ }
89
+ strong.red {
90
+ color: green;
91
+ font-weight: bold;
92
+ font-size: 105%;
93
+ }
94
+ .postbox {
95
+ margin: 0 10px 10px 0;
96
  }
 
 
 
 
 
yst_plugin_tools.php CHANGED
@@ -1,257 +1,267 @@
1
- <?php
2
-
3
- /**
4
- * Backend Class for use in all Yoast plugins
5
- * Version 0.2
6
- */
7
-
8
- if (!class_exists('Yoast_GA_Plugin_Admin')) {
9
- class Yoast_GA_Plugin_Admin {
10
-
11
- var $feed = 'http://yoast.com/feed/';
12
- var $hook = '';
13
- var $filename = '';
14
- var $longname = '';
15
- var $shortname = '';
16
- var $ozhicon = '';
17
- var $optionname = '';
18
- var $homepage = '';
19
- var $accesslvl = 'edit_users';
20
-
21
- function __construct() {
22
- }
23
-
24
- function add_ozh_adminmenu_icon( $hook ) {
25
- if ($hook == $this->hook)
26
- return $this->plugin_url.$this->ozhicon;
27
- return $hook;
28
- }
29
-
30
- function config_page_styles() {
31
- if (isset($_GET['page']) && $_GET['page'] == $this->hook) {
32
- wp_enqueue_style('dashboard');
33
- wp_enqueue_style('thickbox');
34
- wp_enqueue_style('global');
35
- wp_enqueue_style('wp-admin');
36
- wp_enqueue_style('ga-admin-css', $this->plugin_url . 'yst_plugin_tools.css');
37
- }
38
- }
39
-
40
- function register_settings_page() {
41
- add_options_page($this->longname, $this->shortname, $this->accesslvl, $this->hook, array(&$this,'config_page'));
42
- }
43
-
44
- function plugin_options_url() {
45
- return admin_url( 'options-general.php?page='.$this->hook );
46
- }
47
-
48
- /**
49
- * Add a link to the settings page to the plugins list
50
- */
51
- function add_action_link( $links, $file ) {
52
- static $this_plugin;
53
- if( empty($this_plugin) ) $this_plugin = $this->filename;
54
- if ( $file == $this_plugin ) {
55
- $settings_link = '<a href="' . $this->plugin_options_url() . '">' . __('Settings') . '</a>';
56
- array_unshift( $links, $settings_link );
57
- }
58
- return $links;
59
- }
60
-
61
- function config_page() {
62
-
63
- }
64
-
65
- function config_page_scripts() {
66
- if (isset($_GET['page']) && $_GET['page'] == $this->hook) {
67
- wp_enqueue_script('postbox');
68
- wp_enqueue_script('dashboard');
69
- wp_enqueue_script('thickbox');
70
- wp_enqueue_script('media-upload');
71
- }
72
- }
73
-
74
- /**
75
- * Create a Checkbox input field
76
- */
77
- function checkbox($id) {
78
- $options = get_option( $this->optionname );
79
- return '<input type="checkbox" id="'.$id.'" name="'.$id.'"'. checked($options[$id],true,false).'/>';
80
- }
81
-
82
- /**
83
- * Create a Text input field
84
- */
85
- function textinput($id) {
86
- $options = get_option( $this->optionname );
87
- return '<input class="text" type="text" id="'.$id.'" name="'.$id.'" size="30" value="'.$options[$id].'"/>';
88
- }
89
-
90
- /**
91
- * Create a dropdown field
92
- */
93
- function select($id, $options, $multiple = false) {
94
- $opt = get_option($this->optionname);
95
- $output = '<select class="select" name="'.$id.'" id="'.$id.'">';
96
- foreach ($options as $val => $name) {
97
- $sel = '';
98
- if ($opt[$id] == $val)
99
- $sel = ' selected="selected"';
100
- if ($name == '')
101
- $name = $val;
102
- $output .= '<option value="'.$val.'"'.$sel.'>'.$name.'</option>';
103
- }
104
- $output .= '</select>';
105
- return $output;
106
- }
107
-
108
- /**
109
- * Create a potbox widget
110
- */
111
- function postbox($id, $title, $content) {
112
- ?>
113
- <div id="<?php echo $id; ?>" class="postbox">
114
- <div class="handlediv" title="Click to toggle"><br /></div>
115
- <h3 class="hndle"><span><?php echo $title; ?></span></h3>
116
- <div class="inside">
117
- <?php echo $content; ?>
118
- </div>
119
- </div>
120
- <?php
121
- }
122
-
123
-
124
- /**
125
- * Create a form table from an array of rows
126
- */
127
- function form_table($rows) {
128
- $content = '<table class="form-table">';
129
- $i = 1;
130
- foreach ($rows as $row) {
131
- $class = '';
132
- if ($i > 1) {
133
- $class .= 'yst_row';
134
- }
135
- if ($i % 2 == 0) {
136
- $class .= ' even';
137
- }
138
- $content .= '<tr id="'.$row['id'].'_row" class="'.$class.'"><th valign="top" scrope="row">';
139
- if (isset($row['id']) && $row['id'] != '')
140
- $content .= '<label for="'.$row['id'].'">'.$row['label'].':</label>';
141
- else
142
- $content .= $row['label'];
143
- $content .= '</th><td valign="top">';
144
- $content .= $row['content'];
145
- $content .= '</td></tr>';
146
- if ( isset($row['desc']) && !empty($row['desc']) ) {
147
- $content .= '<tr class="'.$class.'"><td colspan="2" class="yst_desc"><small>'.$row['desc'].'</small></td></tr>';
148
- }
149
-
150
- $i++;
151
- }
152
- $content .= '</table>';
153
- return $content;
154
- }
155
-
156
- /**
157
- * Create a "plugin like" box.
158
- */
159
- function plugin_like($hook = '') {
160
- if (empty($hook)) {
161
- $hook = $this->hook;
162
- }
163
- $content = '<p>'.__('Why not do any or all of the following:','ystplugin').'</p>';
164
- $content .= '<ul>';
165
- $content .= '<li><a href="'.$this->homepage.'">'.__('Link to it so other folks can find out about it.','ystplugin').'</a></li>';
166
- $content .= '<li><a href="http://wordpress.org/extend/plugins/'.$hook.'/">'.__('Give it a good rating on WordPress.org.','ystplugin').'</a></li>';
167
- $content .= '<li><a href="http://wordpress.org/extend/plugins/'.$hook.'/">'.__('Let other people know that it works with your WordPress setup.','ystplugin').'</a></li>';
168
- $content .= '</ul>';
169
- $this->postbox($hook.'like', 'Like this plugin?', $content);
170
- }
171
-
172
- /**
173
- * Info box with link to the bug tracker.
174
- */
175
- function plugin_support($hook = '') {
176
- if (empty($hook)) {
177
- $hook = $this->hook;
178
- }
179
- $content = '<p>If you\'ve found a bug in this plugin, please submit it in the <a href="http://yoast.com/mantis/bug_report_page.php">Yoast Bug Tracker</a> with a clear description.</p>';
180
- $this->postbox($this->hook.'support', __('Found a bug?','ystplugin'), $content);
181
- }
182
-
183
- /**
184
- * Box with latest news from Yoast.com
185
- */
186
- function news() {
187
- include_once(ABSPATH . WPINC . '/feed.php');
188
- $rss = fetch_feed( $this->feed );
189
- $rss_items = $rss->get_items( 0, $rss->get_item_quantity(5) );
190
- $content = '<ul>';
191
- if ( !$rss_items ) {
192
- $content .= '<li class="yoast">'.__('No news items, feed might be broken...').'</li>';
193
- } else {
194
- foreach ( $rss_items as $item ) {
195
- $content .= '<li class="yoast">';
196
- $content .= '<a class="rsswidget" href="'.esc_url( $item->get_permalink(), $protocolls=null, 'display' ).'">'. htmlentities($item->get_title()) .'</a> ';
197
- $content .= '</li>';
198
- }
199
- }
200
- $content .= '<li class="rss"><a href="http://yoast.com/feed/">'.__('Subscribe with RSS').'</a></li>';
201
- $content .= '<li class="email"><a href="http://yoast.com/email-blog-updates/">'.__('Subscribe by email').'</a></li>';
202
- $content .= '</ul>';
203
- $this->postbox('yoastlatest', __('Latest news from Yoast'), $content);
204
- }
205
-
206
- function text_limit( $text, $limit, $finish = ' [&hellip;]') {
207
- if( strlen( $text ) > $limit ) {
208
- $text = substr( $text, 0, $limit );
209
- $text = substr( $text, 0, - ( strlen( strrchr( $text,' ') ) ) );
210
- $text .= $finish;
211
- }
212
- return $text;
213
- }
214
-
215
- function db_widget() {
216
- $options = get_option('yoastdbwidget');
217
- if (isset($_POST['yoast_removedbwidget'])) {
218
- $options['removedbwidget'] = true;
219
- update_option('yoastdbwidget',$options);
220
- }
221
- if ($options['removedbwidget']) {
222
- _e("If you reload, this widget will be gone and never appear again, unless you decide to delete the database option 'yoastdbwidget'.");
223
- return;
224
- }
225
- require_once( ABSPATH . WPINC .'/rss.php' );
226
- if ( $rss = fetch_rss( $this->feed ) ) {
227
- echo '<div class="rss-widget">';
228
- echo '<a href="http://yoast.com/" title="'.__('Go to Yoast.com').'"><img src="'.$this->plugin_url.'images/yoast-logo-rss.png" class="alignright" alt="Yoast"/></a>';
229
- echo '<ul>';
230
- $rss->items = array_slice( $rss->items, 0, 3 );
231
- foreach ( (array) $rss->items as $item ) {
232
- echo '<li>';
233
- echo '<a class="rsswidget" href="'.clean_url( $item['link'], $protocolls=null, 'display' ).'">'. htmlentities($item['title']) .'</a> ';
234
- echo '<span class="rss-date">'. date('F j, Y', strtotime($item['pubdate'])) .'</span>';
235
- echo '<div class="rssSummary">'. $this->text_limit($item['summary'],250) .'</div>';
236
- echo '</li>';
237
- }
238
- echo '</ul>';
239
- echo '<div style="border-top: 1px solid #ddd; padding-top: 10px; text-align:center;">';
240
- echo '<a href="http://feeds2.feedburner.com/joostdevalk"><img src="'.get_bloginfo('wpurl').'/wp-includes/images/rss.png" alt=""/> '.__('Subscribe with RSS').'</a>';
241
- echo ' &nbsp; &nbsp; &nbsp; ';
242
- echo '<a href="http://yoast.com/email-blog-updates/"><img src="'.$this->plugin_url.'images/email_sub.png" alt=""/> '.__('Subscribe by email').'</a>';
243
- echo '<form class="alignright" method="post"><input type="hidden" name="yoast_removedbwidget" value="true"/><input title="'.__('Remove this widget from all users dashboards').'" type="submit" value="X"/></form>';
244
- echo '</div>';
245
- echo '</div>';
246
- }
247
- }
248
-
249
- function widget_setup() {
250
- $options = get_option('yoastdbwidget');
251
- if (!$options['removedbwidget'])
252
- wp_add_dashboard_widget( 'yoast_db_widget' , __('The Latest news from Yoast') , array(&$this, 'db_widget'));
253
- }
254
- }
255
- }
256
-
 
 
 
 
 
 
 
 
 
 
257
  ?>
1
+ <?php
2
+
3
+ /**
4
+ * Backend Class for use in all Yoast plugins
5
+ * Version 0.2
6
+ */
7
+
8
+ if (!class_exists('Yoast_GA_Plugin_Admin')) {
9
+ class Yoast_GA_Plugin_Admin {
10
+
11
+ var $hook = '';
12
+ var $filename = '';
13
+ var $longname = '';
14
+ var $shortname = '';
15
+ var $ozhicon = '';
16
+ var $optionname = '';
17
+ var $homepage = '';
18
+ var $accesslvl = 'edit_users';
19
+
20
+ function Yoast_GA_Plugin_Admin() {
21
+ add_action( 'admin_menu', array(&$this, 'register_settings_page') );
22
+ add_filter( 'plugin_action_links', array(&$this, 'add_action_link'), 10, 2 );
23
+ add_filter( 'ozh_adminmenu_icon', array(&$this, 'add_ozh_adminmenu_icon' ) );
24
+
25
+ add_action('admin_print_scripts', array(&$this,'config_page_scripts'));
26
+ add_action('admin_print_styles', array(&$this,'config_page_styles'));
27
+
28
+ add_action('wp_dashboard_setup', array(&$this,'widget_setup'));
29
+ }
30
+
31
+ function add_ozh_adminmenu_icon( $hook ) {
32
+ if ($hook == $this->hook)
33
+ return plugin_dir_url( __FILE__ ).$this->ozhicon;
34
+ return $hook;
35
+ }
36
+
37
+ function config_page_styles() {
38
+ if (isset($_GET['page']) && $_GET['page'] == $this->hook) {
39
+ wp_enqueue_style('dashboard');
40
+ wp_enqueue_style('thickbox');
41
+ wp_enqueue_style('global');
42
+ wp_enqueue_style('wp-admin');
43
+ wp_enqueue_style('gawp-css', plugin_dir_url( __FILE__ ). 'yst_plugin_tools.css');
44
+ }
45
+ }
46
+
47
+ function register_settings_page() {
48
+ add_options_page($this->longname, $this->shortname, $this->accesslvl, $this->hook, array(&$this,'config_page'));
49
+ }
50
+
51
+ function plugin_options_url() {
52
+ return admin_url( 'options-general.php?page='.$this->hook );
53
+ }
54
+
55
+ /**
56
+ * Add a link to the settings page to the plugins list
57
+ */
58
+ function add_action_link( $links, $file ) {
59
+ static $this_plugin;
60
+ if( empty($this_plugin) ) $this_plugin = $this->filename;
61
+ if ( $file == $this_plugin ) {
62
+ $settings_link = '<a href="' . $this->plugin_options_url() . '">' . __('Settings', 'gawp_yoast') . '</a>';
63
+ array_unshift( $links, $settings_link );
64
+ }
65
+ return $links;
66
+ }
67
+
68
+ function config_page() {
69
+
70
+ }
71
+
72
+ function config_page_scripts() {
73
+ if (isset($_GET['page']) && $_GET['page'] == $this->hook) {
74
+ wp_enqueue_script('postbox');
75
+ wp_enqueue_script('dashboard');
76
+ wp_enqueue_script('thickbox');
77
+ wp_enqueue_script('media-upload');
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Create a Checkbox input field
83
+ */
84
+ function checkbox($id) {
85
+ $options = get_option( $this->optionname );
86
+ return '<input type="checkbox" id="'.$id.'" name="'.$id.'"'. checked($options[$id],true,false).'/>';
87
+ }
88
+
89
+ /**
90
+ * Create a Text input field
91
+ */
92
+ function textinput($id) {
93
+ $options = get_option( $this->optionname );
94
+ return '<input class="text" type="text" id="'.$id.'" name="'.$id.'" size="30" value="'.$options[$id].'"/>';
95
+ }
96
+
97
+ /**
98
+ * Create a dropdown field
99
+ */
100
+ function select($id, $options, $multiple = false) {
101
+ $opt = get_option($this->optionname);
102
+ $output = '<select class="select" name="'.$id.'" id="'.$id.'">';
103
+ foreach ($options as $val => $name) {
104
+ $sel = '';
105
+ if ($opt[$id] == $val)
106
+ $sel = ' selected="selected"';
107
+ if ($name == '')
108
+ $name = $val;
109
+ $output .= '<option value="'.$val.'"'.$sel.'>'.$name.'</option>';
110
+ }
111
+ $output .= '</select>';
112
+ return $output;
113
+ }
114
+
115
+ /**
116
+ * Create a potbox widget
117
+ */
118
+ function postbox($id, $title, $content) {
119
+ ?>
120
+ <div id="<?php echo $id; ?>" class="postbox">
121
+ <div class="handlediv" title="Click to toggle"><br /></div>
122
+ <h3 class="hndle"><span><?php echo $title; ?></span></h3>
123
+ <div class="inside">
124
+ <?php echo $content; ?>
125
+ </div>
126
+ </div>
127
+ <?php
128
+ }
129
+
130
+
131
+ /**
132
+ * Create a form table from an array of rows
133
+ */
134
+ function form_table($rows) {
135
+ $content = '<table class="form-table">';
136
+ $i = 1;
137
+ foreach ($rows as $row) {
138
+ $class = '';
139
+ if ($i > 1) {
140
+ $class .= 'yst_row';
141
+ }
142
+ if ($i % 2 == 0) {
143
+ $class .= ' even';
144
+ }
145
+ $content .= '<tr id="'.$row['id'].'_row" class="'.$class.'"><th valign="top" scrope="row">';
146
+ if (isset($row['id']) && $row['id'] != '')
147
+ $content .= '<label for="'.$row['id'].'">'.$row['label'].':</label>';
148
+ else
149
+ $content .= $row['label'];
150
+ $content .= '</th><td valign="top">';
151
+ $content .= $row['content'];
152
+ $content .= '</td></tr>';
153
+ if ( isset($row['desc']) && !empty($row['desc']) ) {
154
+ $content .= '<tr class="'.$class.'"><td colspan="2" class="yst_desc"><small>'.$row['desc'].'</small></td></tr>';
155
+ }
156
+
157
+ $i++;
158
+ }
159
+ $content .= '</table>';
160
+ return $content;
161
+ }
162
+
163
+ /**
164
+ * Create a "plugin like" box.
165
+ */
166
+ function plugin_like($hook = '') {
167
+ if (empty($hook)) {
168
+ $hook = $this->hook;
169
+ }
170
+ $content = '<p>'.__('Why not do any or all of the following:', 'gawp_yoast' ).'</p>';
171
+ $content .= '<ul>';
172
+ $content .= '<li><a href="'.$this->homepage.'">'.__('Link to it so other folks can find out about it.', 'gawp_yoast' ).'</a></li>';
173
+ $content .= '<li><a href="http://wordpress.org/extend/plugins/'.$hook.'/">'.__('Give it a 5 star rating on WordPress.org.', 'gawp_yoast' ).'</a></li>';
174
+ $content .= '<li><a href="http://wordpress.org/extend/plugins/'.$hook.'/">'.__('Let other people know that it works with your WordPress setup.', 'gawp_yoast' ).'</a></li>';
175
+ $content .= '</ul>';
176
+ $this->postbox($hook.'like', __( 'Like this plugin?', 'gawp_yoast' ), $content);
177
+ }
178
+
179
+ /**
180
+ * Info box with link to the bug tracker.
181
+ */
182
+ function plugin_support($hook = '') {
183
+ if (empty($hook)) {
184
+ $hook = $this->hook;
185
+ }
186
+ $content = '<p>'.sprintf( __( 'If you\'ve found a bug in this plugin, please submit it in the <a href="%s">Yoast Bug Tracker</a> with a clear description.', 'gawp_yoast' ), 'http://yoast.com/mantis/bug_report_page.php').'</p>';
187
+ $this->postbox($this->hook.'support', __('Found a bug?', 'gawp_yoast' ), $content);
188
+ }
189
+
190
+ /**
191
+ * Box with latest news from Yoast.com
192
+ */
193
+ function news() {
194
+ include_once(ABSPATH . WPINC . '/feed.php');
195
+ $rss = fetch_feed('http://feeds.feedburner.com/joostdevalk');
196
+ $rss_items = $rss->get_items( 0, $rss->get_item_quantity(5) );
197
+ $content = '<ul>';
198
+ if ( !$rss_items ) {
199
+ $content .= '<li class="yoast">'.__( 'No news items, feed might be broken...', 'gawp_yoast' ).'</li>';
200
+ } else {
201
+ foreach ( $rss_items as $item ) {
202
+ $content .= '<li class="yoast">';
203
+ $content .= '<a class="rsswidget" href="'.esc_url( $item->get_permalink(), $protocolls=null, 'display' ).'">'. esc_html($item->get_title()) .'</a> ';
204
+ $content .= '</li>';
205
+ }
206
+ }
207
+ $content .= '<li class="facebook"><a href="https://www.facebook.com/yoastcom">'.__( 'Like Yoast on Facebook', 'gawp_yoast' ).'</a></li>';
208
+ $content .= '<li class="twitter"><a href="http://twitter.com/yoast">'.__( 'Follow Yoast on Twitter', 'gawp_yoast' ).'</a></li>';
209
+ $content .= '<li class="googleplus"><a href="https://plus.google.com/115369062315673853712/posts">'.__( 'Circle Yoast on Google+', 'gawp_yoast' ).'</a></li>';
210
+ $content .= '<li class="rss"><a href="http://yoast.com/feed/">'.__( 'Subscribe with RSS', 'gawp_yoast' ).'</a></li>';
211
+ $content .= '<li class="email"><a href="http://yoast.com/email-blog-updates/">'.__( 'Subscribe by email', 'gawp_yoast' ).'</a></li>';
212
+ $content .= '</ul>';
213
+ $this->postbox('yoastlatest', __( 'Latest news from Yoast', 'gawp_yoast' ), $content);
214
+ }
215
+
216
+ function text_limit( $text, $limit, $finish = ' [&hellip;]') {
217
+ if( strlen( $text ) > $limit ) {
218
+ $text = substr( $text, 0, $limit );
219
+ $text = substr( $text, 0, - ( strlen( strrchr( $text,' ') ) ) );
220
+ $text .= $finish;
221
+ }
222
+ return $text;
223
+ }
224
+
225
+ function db_widget() {
226
+ $options = get_option('yoastdbwidget');
227
+ if (isset($_POST['yoast_removedbwidget'])) {
228
+ $options['removedbwidget'] = true;
229
+ update_option('yoastdbwidget',$options);
230
+ }
231
+ if ($options['removedbwidget']) {
232
+ _e( "If you reload, this widget will be gone and never appear again, unless you decide to delete the database option 'yoastdbwidget'.", 'gawp_yoast' );
233
+ return;
234
+ }
235
+ require_once(ABSPATH.WPINC.'/rss.php');
236
+ if ( $rss = fetch_rss( 'http://yoast.com/feed/' ) ) {
237
+ echo '<div class="rss-widget">';
238
+ echo '<a href="http://yoast.com/" title="Go to Yoast.com"><img src="'.plugin_dir_url().'images/yoast-logo-rss.png" class="alignright" alt="Yoast"/></a>';
239
+ echo '<ul>';
240
+ $rss->items = array_slice( $rss->items, 0, 3 );
241
+ foreach ( (array) $rss->items as $item ) {
242
+ echo '<li>';
243
+ echo '<a class="rsswidget" href="'.clean_url( $item['link'], $protocolls=null, 'display' ).'">'. esc_html($item['title']) .'</a> ';
244
+ echo '<span class="rss-date">'. date('F j, Y', strtotime($item['pubdate'])) .'</span>';
245
+ echo '<div class="rssSummary">'. $this->text_limit($item['summary'],250) .'</div>';
246
+ echo '</li>';
247
+ }
248
+ echo '</ul>';
249
+ echo '<div style="border-top: 1px solid #ddd; padding-top: 10px; text-align:center;">';
250
+ echo '<a href="http://feeds2.feedburner.com/joostdevalk"><img src="'.get_bloginfo('wpurl').'/wp-includes/images/rss.png" alt=""/> Subscribe with RSS</a>';
251
+ echo ' &nbsp; &nbsp; &nbsp; ';
252
+ echo '<a href="http://yoast.com/email-blog-updates/"><img src="'.plugin_dir_url().'images/email_sub.png" alt=""/> '.__( 'Subscribe by email', 'gawp_yoast' ).'</a>';
253
+ echo '<form class="alignright" method="post"><input type="hidden" name="yoast_removedbwidget" value="true"/><input title="'.__( 'Remove this widget from all users dashboards', 'gawp_yoast' ).'" type="submit" value="X"/></form>';
254
+ echo '</div>';
255
+ echo '</div>';
256
+ }
257
+ }
258
+
259
+ function widget_setup() {
260
+ $options = get_option('yoastdbwidget');
261
+ if (!$options['removedbwidget'])
262
+ wp_add_dashboard_widget( 'yoast_db_widget' , __( 'The Latest news from Yoast', 'gawp_yoast' ) , array(&$this, 'db_widget'));
263
+ }
264
+ }
265
+ }
266
+
267
  ?>