Google Analytics for WordPress by MonsterInsights - Version 5.0

Version Description

Download this release

Release Info

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

Code changes from version 4.3.5 to 5.0

Files changed (72) hide show
  1. .gruntjshintrc +18 -0
  2. .jscsrc +112 -0
  3. CONTRIBUTING.md +37 -0
  4. README.md +51 -0
  5. admin/ajax.php +0 -19
  6. admin/class-admin-ga-js.php +18 -0
  7. admin/class-admin-universal.php +18 -0
  8. admin/class-admin.php +569 -725
  9. admin/class-pointer.php +0 -129
  10. admin/index.php +4 -0
  11. admin/license-manager/README.md +21 -0
  12. admin/license-manager/class-api-request.php +140 -0
  13. admin/license-manager/class-license-manager.php +568 -0
  14. admin/license-manager/class-plugin-license-manager.php +90 -0
  15. admin/license-manager/class-plugin-update-manager.php +102 -0
  16. admin/license-manager/class-product.php +228 -0
  17. admin/license-manager/class-theme-license-manager.php +53 -0
  18. admin/license-manager/class-theme-update-manager.php +149 -0
  19. admin/license-manager/class-update-manager.php +211 -0
  20. admin/license-manager/index.php +2 -0
  21. admin/license-manager/samples/index.php +2 -0
  22. admin/license-manager/samples/sample-plugin.php +74 -0
  23. admin/license-manager/samples/sample-product.php +23 -0
  24. admin/license-manager/samples/sample-theme-functions.php +11 -0
  25. admin/license-manager/views/form.php +94 -0
  26. admin/license-manager/views/index.php +2 -0
  27. admin/license-manager/views/script.php +67 -0
  28. admin/pages/dashboard.php +16 -0
  29. admin/pages/extensions.php +21 -0
  30. admin/pages/settings.php +119 -0
  31. admin/views/content_footer.php +9 -0
  32. admin/views/content_head.php +2 -0
  33. admin/wp-gdata/index.php +2 -0
  34. admin/xmlparser.php +0 -129
  35. admin/yst_plugin_tools.css +0 -68
  36. admin/yst_plugin_tools.php +0 -190
  37. css/yoast_ga_styles.css +161 -0
  38. custom_se_async.js +0 -141
  39. frontend/class-frontend.php +165 -602
  40. frontend/class-ga-js.php +306 -0
  41. frontend/class-universal.php +306 -0
  42. frontend/index.php +4 -0
  43. frontend/js/yst_ga.js +0 -0
  44. frontend/views/tracking_debug.php +3 -0
  45. frontend/views/tracking_ga_js.php +26 -0
  46. frontend/views/tracking_universal.php +23 -0
  47. frontend/views/tracking_usergroup.php +3 -0
  48. googleanalytics.php +14 -22
  49. images/banner-conversion-review.png +0 -0
  50. images/banner-ga-goals.png +0 -0
  51. images/banner-website-review.png +0 -0
  52. images/favicon.ico +0 -0
  53. images/ga-icon-32x32.png +0 -0
  54. images/ga-logo-532.png +0 -0
  55. img/banner-local-seo.png +0 -0
  56. img/banner-premium-seo.png +0 -0
  57. img/banner-video-seo.png +0 -0
  58. img/banner-website-review.png +0 -0
  59. img/eBook_261x130.png +0 -0
  60. img/eComm_130x100.png +0 -0
  61. img/yoast-icon.png +0 -0
  62. img/yoast_avatar_joost.png +0 -0
  63. inc/class-tracking.php +0 -158
  64. inc/functions.php +0 -20
  65. includes/class-options.php +51 -0
  66. index.php +4 -0
  67. js/index.php +4 -0
  68. js/yoast_ga_admin.js +37 -0
  69. languages/google-analytics-for-wordpress.pot +107 -81
  70. languages/index.php +4 -0
  71. lib/languages/google-analytics-for-wordpress.pot +94 -0
  72. readme.txt +36 -56
.gruntjshintrc ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "boss": true,
3
+ "curly": true,
4
+ "eqeqeq": true,
5
+ "eqnull": true,
6
+ "es3": true,
7
+ "immed": true,
8
+ "latedef": true,
9
+ "newcap": true,
10
+ "noarg": true,
11
+ "quotmark": "single",
12
+ "sub": true,
13
+ "strict": true,
14
+ "undef": true,
15
+ "unused": true,
16
+
17
+ "node": true
18
+ }
.jscsrc ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "requireSpacesInConditionalExpression": true,
3
+ "requireSpacesInFunctionExpression": {
4
+ "beforeOpeningCurlyBrace": true
5
+ },
6
+ "disallowSpacesInFunctionExpression": {
7
+ "beforeOpeningRoundBrace": true
8
+ },
9
+ "requireMultipleVarDecl": "onevar",
10
+ "requireSpacesInsideObjectBrackets": "all",
11
+ "disallowSpaceAfterObjectKeys": true,
12
+ "requireSpaceAfterBinaryOperators": [
13
+ "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=",
14
+ "&=", "|=", "^=", "+=",
15
+
16
+ "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&",
17
+ "|", "^", "&&", "||", "===", "==", ">=",
18
+ "<=", "<", ">", "!=", "!=="
19
+ ],
20
+ "requireSpaceBeforeBinaryOperators": [
21
+ "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=",
22
+ "&=", "|=", "^=", "+=",
23
+
24
+ "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&",
25
+ "|", "^", "&&", "||", "===", "==", ">=",
26
+ "<=", "<", ">", "!=", "!=="
27
+ ],
28
+ "disallowKeywords": ["with"],
29
+ "disallowMultipleLineBreaks": true,
30
+ "validateLineBreaks": "LF",
31
+ "disallowMixedSpacesAndTabs": "smart",
32
+ "disallowTrailingWhitespace": true,
33
+
34
+ "requireCurlyBraces": [ "if", "else", "for", "while", "do", "try", "catch" ],
35
+ "requireSpaceBeforeBlockStatements": true,
36
+ "requireParenthesesAroundIIFE": true,
37
+ "requireBlocksOnNewline": true,
38
+ "requireRightStickedOperators": [],
39
+ "requireOperatorBeforeLineBreak": [
40
+ "?",
41
+ "=",
42
+ "+",
43
+ "-",
44
+ "/",
45
+ "*",
46
+ "==",
47
+ "===",
48
+ "!=",
49
+ "!==",
50
+ ">",
51
+ ">=",
52
+ "<",
53
+ "<="
54
+ ],
55
+ "disallowLeftStickedOperators": [
56
+ "?",
57
+ "=",
58
+ "+",
59
+ "-",
60
+ "/",
61
+ "*",
62
+ "==",
63
+ "===",
64
+ "!=",
65
+ "!==",
66
+ ">",
67
+ ">=",
68
+ "<",
69
+ "<="
70
+ ],
71
+ "disallowRightStickedOperators": [
72
+ "?",
73
+ "=",
74
+ "+",
75
+ "/",
76
+ "*",
77
+ ":",
78
+ "==",
79
+ "===",
80
+ "!=",
81
+ "!==",
82
+ ">",
83
+ ">=",
84
+ "<",
85
+ "<="
86
+ ],
87
+ "requireLeftStickedOperators": [","],
88
+ "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~"],
89
+ "requireSpaceAfterPrefixUnaryOperators": ["!"],
90
+ "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
91
+ "requireCamelCaseOrUpperCaseIdentifiers": true,
92
+ "disallowMultipleLineStrings": true,
93
+ "validateQuoteMarks": "'",
94
+ "validateIndentation": "\t",
95
+ "requireLineFeedAtFileEnd": true,
96
+ "requireDotNotation": true,
97
+
98
+ "disallowTrailingComma": true,
99
+ "disallowPaddingNewlinesInBlocks": true,
100
+ "disallowEmptyBlocks": true,
101
+ "disallowQuotedKeysInObjects": "allButReserved",
102
+ "disallowDanglingUnderscores": true,
103
+ "requireCommaBeforeLineBreak": true,
104
+ "disallowKeywordsOnNewLine": ["else"],
105
+ "requireCapitalizedConstructors": true,
106
+ "safeContextKeyword": [ "that" ],
107
+ "validateJSDoc": {
108
+ "checkParamNames": true,
109
+ "checkRedundantParams": true,
110
+ "requireParamTypes": true
111
+ }
112
+ }
CONTRIBUTING.md ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #Contribute To Google Analytics for WordPress
2
+
3
+ Community made patches, localisations, bug reports and contributions are very welcome and help make Google Analytics for WordPress the #1 GA plugin for WordPress.
4
+
5
+ When contributing please ensure you follow the guidelines below so that we can keep on top of things.
6
+
7
+ __Please Note:__ GitHub is for bug reports and contributions only - if you have a support question or a request for a customisation don't post here, go to our [Support Forum](http://wordpress.org/support/plugin/google-analytics-for-wordpress) instead.
8
+
9
+ For localization, please refer to [translate.yoast.com](http://translate.yoast.com/projects/google-analytics-for-wordpress), though bugs with strings that can't be translated are welcome here.
10
+
11
+ ## Getting Started
12
+
13
+ * Submit a ticket for your issue, assuming one does not already exist.
14
+ * Raise it on our [Issue Tracker](https://github.com/Yoast/google-analytics-for-wordpress/issues)
15
+ * Clearly describe the issue including steps to reproduce the bug.
16
+ * Make sure you fill in the earliest version that you know has the issue as well as the version of WordPress you're using.
17
+
18
+ ## Making Changes
19
+
20
+ * Fork the repository on GitHub
21
+ * Make the changes to your forked repository
22
+ * Ensure you stick to the [WordPress Coding Standards](http://codex.wordpress.org/WordPress_Coding_Standards) and have properly documented any new functions.
23
+ * When committing, reference your issue (if present) and include a note about the fix.
24
+ * Push the changes to your fork and submit a pull request to the 'master' branch of the Google Analytics for WordPress repository.
25
+
26
+ ## Code Documentation
27
+
28
+ * We ensure that every Google Analytics for WordPress function is documented well and follows the standards set by phpDoc.
29
+ * An example function can be found [here](https://gist.github.com/jdevalk/5574677)
30
+ * Please make sure that every function is documented so that when we update our API Documentation things don't go awry!
31
+ * Finally, please use tabs and not spaces. The tab indent size should be 8 for all Google Analytics for WordPress code.
32
+
33
+ At this point you're waiting on us to merge your pull request. We'll review all pull requests, and make suggestions and changes if necessary.
34
+
35
+ # Additional Resources
36
+ * [General GitHub Documentation](http://help.github.com/)
37
+ * [GitHub Pull Request documentation](http://help.github.com/send-pull-requests/)
README.md ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Google Analytics for WordPress
2
+ ==============================
3
+
4
+ Add Google Analytics to WordPress and be able to use all the powerful functions Google Analytics offers!
5
+
6
+
7
+ Welcome to the Google Analytics for WordPress Github repository
8
+ ----------------------------------------------
9
+
10
+ While the documentation for the [Google Analytics for WordPress plugin](http://yoast.com/wordpress/google-analytics/) can be found on yoast.com, here
11
+ you can browse the source of the project, find and discuss open issues and even
12
+ [contribute yourself](https://github.com/Yoast/google-analytics-for-wordpress/blob/master/CONTRIBUTING.md).
13
+
14
+ Installation
15
+ ------------
16
+
17
+ Here's a [guide on how to install Google Analytics for WordPress in your WordPress site](http://yoast.com/wordpress/google-analytics/installation/).
18
+ If you want to run the Git version though, you have two options:
19
+
20
+ * You can clone the GitHub repository: https://github.com/Yoast/google-analytics-for-wordpress.git
21
+ * Download it directly as a ZIP file: https://github.com/Yoast/google-analytics-for-wordpress/archive/master.zip
22
+
23
+ This will download the latest development version of Google Analytics for WordPress by Yoast. While this version is usually stable,
24
+ it is not recommended for use in a production environment.
25
+
26
+ Bugs
27
+ ----
28
+ If you find an issue, [let us know here](https://github.com/Yoast/google-analytics-for-wordpress/issues/new)!
29
+
30
+ Support
31
+ -------
32
+ This is a developer's portal for Google Analytics for WordPress by Yoast and should not be used for support. Please visit the
33
+ [support forums](http://wordpress.org/support/plugin/google-analytics-for-wordpress).
34
+
35
+ Contributions
36
+ -------------
37
+ Anyone is welcome to contribute to Google Analytics for WordPress. Please
38
+ [read the guidelines](https://github.com/Yoast/google-analytics-for-wordpress/blob/master/CONTRIBUTING.md) for contributing to this
39
+ repository.
40
+
41
+ There are various ways you can contribute:
42
+
43
+ * [Raise an issue](https://github.com/Yoast/google-analytics-for-wordpress/issues) on GitHub.
44
+ * Send us a Pull Request with your bug fixes and/or new features.
45
+ * [Translate Google Analytics for WordPress by Yoast into different languages](http://translate.yoast.com/projects/google-analytics-for-wordpress).
46
+ * Provide feedback and [suggestions on enhancements](https://github.com/Yoast/google-analytics-for-wordpress/issues?direction=desc&labels=Enhancement&page=1&sort=created&state=open).
47
+
48
+ Changelog
49
+ =========
50
+
51
+ Please see readme.txt for the changelog.
admin/ajax.php DELETED
@@ -1,19 +0,0 @@
1
- <?php
2
-
3
- function yoast_ga_store_tracking_response() {
4
- if ( !wp_verify_nonce( $_POST['nonce'], 'wpga_activate_tracking' ) )
5
- die();
6
-
7
- $options = get_option( 'Yoast_Google_Analytics' );
8
-
9
- $options['tracking_popup'] = 'done';
10
-
11
- if ( $_POST['allow_tracking'] == 'yes' )
12
- $options['yoast_tracking'] = true;
13
- else
14
- $options['yoast_tracking'] = false;
15
-
16
- update_option( 'Yoast_Google_Analytics', $options );
17
- }
18
-
19
- add_action( 'wp_ajax_wpga_tracking_data', 'yoast_ga_store_tracking_response' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/class-admin-ga-js.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This class is the backend ga.js class, extends the basic admin class
4
+ */
5
+
6
+ if ( ! class_exists( 'Yoast_GA_Admin_GA_JS' ) ) {
7
+
8
+ class Yoast_GA_Admin_GA_JS extends Yoast_GA_Admin {
9
+
10
+ public function __construct() {
11
+
12
+ }
13
+
14
+ }
15
+
16
+ global $yoast_ga_admin_ga_js;
17
+ $yoast_ga_admin_ga_js = new Yoast_GA_Admin_GA_JS;
18
+ }
admin/class-admin-universal.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This class is the backend universal class, extends the basic admin class
4
+ */
5
+
6
+ if ( ! class_exists( 'Yoast_GA_Admin_Universal' ) ) {
7
+
8
+ class Yoast_GA_Admin_Universal extends Yoast_GA_Admin {
9
+
10
+ public function __construct() {
11
+
12
+ }
13
+
14
+ }
15
+
16
+ global $yoast_ga_admin_universal;
17
+ $yoast_ga_admin_universal = new Yoast_GA_Admin_Universal;
18
+ }
admin/class-admin.php CHANGED
@@ -1,293 +1,431 @@
1
  <?php
 
 
 
 
 
 
2
 
3
- /*
4
- * Admin User Interface
5
- */
6
-
7
- require_once plugin_dir_path( __FILE__ ) . 'yst_plugin_tools.php';
8
  require_once plugin_dir_path( __FILE__ ) . '/wp-gdata/wp-gdata.php';
9
 
10
- $options = get_option( 'Yoast_Google_Analytics' );
11
 
12
- global $wp_version;
13
- if ( version_compare( $wp_version, '3.3', '>=' ) && !isset( $options['tracking_popup'] ) )
14
- require_once plugin_dir_path( __FILE__ ) . 'class-pointer.php';
15
 
16
- class GA_Admin extends Yoast_GA_Plugin_Admin {
17
 
18
- var $hook = 'google-analytics-for-wordpress';
19
- var $longname = '';
20
- var $shortname = '';
21
- var $ozhicon = 'images/chart_curve.png';
22
- var $optionname = 'Yoast_Google_Analytics';
23
- var $homepage = 'http://yoast.com/wordpress/google-analytics/';
24
- var $toc = '';
25
 
26
- /**
27
- * Constructur, load all required stuff.
28
- */
29
- function __construct() {
30
- $this->longname = __( 'Google Analytics Configuration', 'google-analytics-for-wordpress' );
31
- $this->shortname = __( 'Google Analytics', 'google-analytics-for-wordpress' );
32
 
33
- $this->upgrade();
 
 
 
34
 
35
- $this->plugin_url = plugins_url( '', __FILE__ ) . '/';
 
 
 
 
 
 
 
36
 
37
- // Register the settings page
38
- add_action( 'admin_menu', array( &$this, 'register_settings_page' ) );
 
 
 
39
 
40
- // Register the contextual help for the settings page
41
- // add_action( 'contextual_help', array(&$this, 'plugin_help'), 10, 3 );
 
 
42
 
43
- // Give the plugin a settings link in the plugin overview
44
- add_filter( 'plugin_action_links', array( &$this, 'add_action_link' ), 10, 2 );
 
 
45
 
46
- // Print Scripts and Styles
47
- add_action( 'admin_print_scripts', array( &$this, 'config_page_scripts' ) );
48
- add_action( 'admin_print_styles', array( &$this, 'config_page_styles' ) );
 
 
 
 
 
49
 
50
- // Print stuff in the settings page's head
51
- add_action( 'admin_head', array( &$this, 'config_page_head' ) );
52
 
53
- // Drop a warning on each page of the admin when Google Analytics hasn't been configured
54
- add_action( 'admin_footer', array( &$this, 'warning' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
- // Save settings
57
- // TODO: replace with Options API
58
- add_action( 'admin_init', array( &$this, 'save_settings' ) );
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
- // Authenticate
61
- add_action( 'admin_init', array( &$this, 'authenticate' ) );
62
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
- function config_page_head() {
65
-
66
- global $current_screen;
67
- if ( 'settings_page_' . $this->hook == $current_screen->id ) {
68
- ?>
69
-
70
- <script type="text/javascript">
71
- jQuery(document).ready(function () {
72
- jQuery(".chzn-select").chosen({ allow_single_deselect:true });
73
- jQuery('#position').change(function () {
74
- if (jQuery('#position').val() == 'header') {
75
- jQuery('#position_header').css("display", "block");
76
- jQuery('#position_manual').css("display", "none");
77
- } else {
78
- jQuery('#position_header').css("display", "none");
79
- jQuery('#position_manual').css("display", "block");
80
- }
81
- }).change();
82
- jQuery('#switchtomanual').change(function () {
83
- if (jQuery('#switchtomanual').is(':checked')) {
84
- jQuery('#uastring_manual').css('display', 'block');
85
- jQuery('#uastring_automatic').css('display', 'none');
86
- } else {
87
- jQuery('#uastring_manual').css('display', 'none');
88
- jQuery('#uastring_automatic').css('display', 'block');
89
- }
90
- }).change();
91
- jQuery('#trackoutbound').change(function () {
92
- if (jQuery('#trackoutbound').is(':checked')) {
93
- jQuery('#internallinktracking').css("display", "block");
94
- jQuery('.internallinktracking').css("display", "list-item");
95
- } else {
96
- jQuery('#internallinktracking').css("display", "none");
97
- jQuery('.internallinktracking').css("display", "none");
98
- }
99
- }).change();
100
- jQuery('#advancedsettings').change(function () {
101
- if (jQuery('#advancedsettings').is(':checked')) {
102
- jQuery('#advancedgasettings').css("display", "block");
103
- jQuery('#customvarsettings').css("display", "block");
104
- jQuery('.advancedgasettings').css("display", "list-item");
105
- jQuery('.customvarsettings').css("display", "list-item");
106
- } else {
107
- jQuery('#advancedgasettings').css("display", "none");
108
- jQuery('#customvarsettings').css("display", "none");
109
- jQuery('.advancedgasettings').css("display", "none");
110
- jQuery('.customvarsettings').css("display", "none");
111
- }
112
- }).change();
113
- jQuery('#extrase').change(function () {
114
- if (jQuery('#extrase').is(':checked')) {
115
- jQuery('#extrasebox').css("display", "block");
116
- } else {
117
- jQuery('#extrasebox').css("display", "none");
118
- }
119
- }).change();
120
- jQuery('#gajslocalhosting').change(function () {
121
- if (jQuery('#gajslocalhosting').is(':checked')) {
122
- jQuery('#localhostingbox').css("display", "block");
123
- } else {
124
- jQuery('#localhostingbox').css("display", "none");
125
- }
126
- }).change();
127
- jQuery('#customvarsettings :input').change(function () {
128
- if (jQuery("#customvarsettings :input:checked").size() > 5) {
129
- 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.', 'google-analytics-for-wordpress' ); ?>");
130
- jQuery(this).attr('checked', false);
131
- }
132
- });
133
- jQuery('#uastring').change(function () {
134
- if (jQuery('#switchtomanual').is(':checked')) {
135
- if (!jQuery(this).val().match(/^UA-[\d-]+$/)) {
136
- 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.', 'google-analytics-for-wordpress' ); ?>");
137
- jQuery(this).focus();
138
- }
139
- }
140
- });
141
- });
142
- </script>
143
- <link rel="shortcut icon" href="<?php echo GAWP_URL; ?>images/favicon.ico"/>
144
- <?php
145
  }
146
- }
147
 
148
- function plugin_help( $contextual_help, $screen_id, $screen ) {
149
- if ( $screen_id == 'settings_page_' . $this->hook ) {
 
 
 
 
 
 
 
150
 
151
- $contextual_help = '<h2>' . __( 'Having problems?', 'google-analytics-for-wordpress' ) . '</h2>' .
152
- '<p>' . sprintf( __( "If you're having problems with this plugin, please refer to its <a href='%s'>FAQ page</a>.", 'google-analytics-for-wordpress' ), 'http://yoast.com/wordpress/google-analytics/ga-wp-faq/' ) . '</p>';
153
  }
154
- return $contextual_help;
155
- }
156
 
157
- function save_settings() {
158
- $options = get_option( $this->optionname );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
- if ( isset( $_REQUEST['reset'] ) && $_REQUEST['reset'] == "true" && isset( $_REQUEST['plugin'] ) && $_REQUEST['plugin'] == 'google-analytics-for-wordpress' ) {
161
- $options = $this->set_defaults();
162
- $options['msg'] = "<div class=\"updated\"><p>" . __( 'Google Analytics settings reset.', 'google-analytics-for-wordpress' ) . "</p></div>\n";
163
- } elseif ( isset( $_POST['submit'] ) && isset( $_POST['plugin'] ) && $_POST['plugin'] == 'google-analytics-for-wordpress' ) {
 
 
 
 
164
 
165
- if ( !current_user_can( 'manage_options' ) ) wp_die( __( 'You cannot edit the Google Analytics for WordPress options.', 'google-analytics-for-wordpress' ) );
166
- check_admin_referer( 'analyticspp-config' );
 
 
 
 
 
 
167
 
168
- foreach ( array( 'uastring', 'dlextensions', 'domainorurl', 'position', 'domain', 'customcode', 'ga_token', 'extraseurl', 'gajsurl', 'gfsubmiteventpv', 'trackprefix', 'ignore_userlevel', 'internallink', 'internallinklabel', 'primarycrossdomain', 'othercrossdomains' ) as $option_name ) {
169
- if ( isset( $_POST[$option_name] ) )
170
- $options[$option_name] = $_POST[$option_name];
171
- else
172
- $options[$option_name] = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  }
 
174
 
175
- 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', 'yoast_tracking' ) as $option_name ) {
176
- if ( isset( $_POST[$option_name] ) && $_POST[$option_name] == 'on' )
177
- $options[$option_name] = true;
178
- else
179
- $options[$option_name] = false;
 
 
 
 
 
 
 
 
180
  }
181
 
182
- if ( isset( $_POST['manual_uastring'] ) && isset( $_POST['uastring_man'] ) ) {
183
- $options['uastring'] = $_POST['uastring_man'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  }
185
 
186
- if ( $options['trackcrossdomain'] ) {
187
- if ( !$options['allowlinker'] )
188
- $options['allowlinker'] = true;
 
 
 
 
189
 
190
- if ( empty( $options['primarycrossdomain'] ) ) {
191
- $origin = yoast_ga_get_domain( $_SERVER["HTTP_HOST"] );
192
- $options['primarycrossdomain'] = $origin["domain"];
193
- }
194
  }
195
 
196
- if ( function_exists( 'w3tc_pgcache_flush' ) )
197
- w3tc_pgcache_flush();
198
 
199
- if ( function_exists( 'w3tc_dbcache_flush' ) )
200
- w3tc_dbcache_flush();
 
 
 
 
 
201
 
202
- if ( function_exists( 'w3tc_minify_flush' ) )
203
- w3tc_minify_flush();
204
 
205
- if ( function_exists( 'w3tc_objectcache_flush' ) )
206
- w3tc_objectcache_flush();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
 
208
- if ( function_exists( 'wp_cache_clear_cache' ) )
209
- wp_cache_clear_cache();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
- $options['msg'] = "<div id=\"updatemessage\" class=\"updated fade\"><p>" . __( "Google Analytics settings updated.", "gawp" ) . "</p></div>\n";
212
- $options['msg'] .= "<script type=\"text/javascript\">setTimeout(function(){jQuery('#updatemessage').hide('slow');}, 3000);</script>";
213
  }
214
- update_option( $this->optionname, $options );
215
- }
216
 
217
- function save_button() {
218
- return '<div class="alignright"><input type="submit" class="button-primary" name="submit" value="' . __( 'Update Google Analytics Settings &raquo;', 'google-analytics-for-wordpress' ) . '" /></div><br class="clear"/>';
219
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
 
221
- function upgrade() {
222
- $options = get_option( $this->optionname );
223
- if ( isset( $options['version'] ) && $options['version'] < '4.04' ) {
224
- if ( !isset( $options['ignore_userlevel'] ) || $options['ignore_userlevel'] == '' )
225
- $options['ignore_userlevel'] = 11;
226
- }
227
- if ( !isset( $options['version'] ) || $options['version'] != GAWP_VERSION ) {
228
- $options['version'] = GAWP_VERSION;
229
  }
230
- update_option( $this->optionname, $options );
231
- }
232
 
233
- function config_page() {
234
- $options = get_option( $this->optionname );
235
- if ( isset( $options['msg'] ) )
236
- echo $options['msg'];
237
- $options['msg'] = '';
238
- update_option( $this->optionname, $options );
239
-
240
- if ( !isset( $options['uastring'] ) )
241
- $options = $this->set_defaults();
242
- $modules = array();
243
-
244
- if ( !isset( $options['manual_uastring'] ) )
245
- $options['manual_uastring'] = '';
246
- ?>
247
- <div class="wrap">
248
- <a href="http://yoast.com/">
249
- <div id="yoast-icon"
250
- style="background: url('<?php echo GAWP_URL; ?>images/ga-icon-32x32.png') no-repeat;"
251
- class="icon32"><br/></div>
252
- </a>
253
-
254
- <h2><?php _e( "Google Analytics for WordPress Configuration", 'google-analytics-for-wordpress' ) ?></h2>
255
-
256
- <div class="postbox-container" style="width:60%;">
257
- <div class="metabox-holder">
258
- <div class="meta-box-sortables">
259
- <form action="<?php echo $this->plugin_options_url(); ?>" method="post" id="analytics-conf">
260
- <input type="hidden" name="plugin" value="google-analytics-for-wordpress"/>
261
- <?php
262
- wp_nonce_field( 'analyticspp-config' );
263
-
264
- if ( empty( $options['uastring'] ) && empty( $options['ga_token'] ) ) {
265
- $query = $this->plugin_options_url() . '&reauth=true';
266
- $line = __( 'Please authenticate with Google Analytics to retrieve your tracking code:', 'google-analytics-for-wordpress' ) . '<br/><br/> <a class="button-primary" href="' . $query . '">' . __( 'Click here to authenticate with Google', 'google-analytics-for-wordpress' ) . '</a>';
267
- } else if ( isset( $options['ga_token'] ) && !empty( $options['ga_token'] ) ) {
268
- $token = $options['ga_token'];
269
-
270
- require_once plugin_dir_path( __FILE__ ) . 'xmlparser.php';
271
- if ( file_exists( ABSPATH . 'wp-includes/class-http.php' ) )
272
- require_once( ABSPATH . 'wp-includes/class-http.php' );
273
-
274
- if ( !isset( $options['ga_api_responses'][$token] ) ) {
275
- $options['ga_api_responses'] = array();
276
-
277
- if ( $oauth = $options['gawp_oauth'] ) {
278
- if ( isset( $oauth['params']['oauth_token'], $oauth['params']['oauth_token_secret'] ) ) {
279
- $options['gawp_oauth']['access_token'] = array(
280
- 'oauth_token' => base64_decode( $oauth['params']['oauth_token'] ),
281
- 'oauth_token_secret' => base64_decode( $oauth['params']['oauth_token_secret'] )
282
- );
283
- unset( $options['gawp_oauth']['params'] );
284
- update_option( $this->optionname, $options );
285
- }
286
- }
287
 
288
  $args = array(
289
  'scope' => 'https://www.googleapis.com/auth/analytics.readonly',
290
- 'xoauth_displayname' => 'Google Analytics for WordPress by Yoast'
291
  );
292
  $access_token = $options['gawp_oauth']['access_token'];
293
  $gdata = new WP_Gdata( $args, $access_token['oauth_token'], $access_token['oauth_token_secret'] );
@@ -304,526 +442,232 @@ class GA_Admin extends Yoast_GA_Plugin_Admin {
304
  $options['ga_token'] = $token;
305
  update_option( 'Yoast_Google_Analytics', $options );
306
  }
307
- }
308
 
309
- if ( isset( $options['ga_api_responses'][$token] ) && is_array( $options['ga_api_responses'][$token] ) && $options['ga_api_responses'][$token]['response']['code'] == 200 ) {
310
- $arr = yoast_xml2array( $options['ga_api_responses'][$token]['body'] );
311
 
312
- $ga_accounts = array();
313
 
314
- $currentua = '';
315
- if ( !empty( $options['uastring'] ) )
316
- $currentua = $options['uastring'];
317
 
318
- if ( isset( $arr['feed']['entry'] ) && is_array( $arr['feed']['entry'] ) ) {
319
  // Check whether the feed output is the new one, first set, or the old one, second set.
320
- if ( $arr['feed']['link_attr']['href'] == 'https://www.googleapis.com/analytics/v2.4/management/accounts/~all/webproperties/~all/profiles' ) {
321
- if ( isset( $arr['feed']['entry']['id'] ) ) {
322
- // Single account in the feed
323
- if ( isset( $arr['feed']['entry']['dxp:property']['1_attr']['value'] ) )
324
- $ua = trim( $arr['feed']['entry']['dxp:property']['1_attr']['value'] );
325
- if ( isset( $arr['feed']['entry']['dxp:property']['2_attr']['value'] ) )
326
- $title = trim( $arr['feed']['entry']['dxp:property']['2_attr']['value'] );
327
- if ( !empty( $ua ) && !empty( $title ) )
328
- $ga_accounts[$ua] = $title;
329
- } else {
330
- // Multiple accounts in the feed
331
- foreach ( $arr['feed']['entry'] as $site ) {
332
- if ( isset( $site['dxp:property']['1_attr']['value'] ) )
333
- $ua = trim( $site['dxp:property']['1_attr']['value'] );
334
- if ( isset( $site['dxp:property']['2_attr']['value'] ) )
335
- $title = trim( $site['dxp:property']['2_attr']['value'] );
336
- if ( !empty( $ua ) && !empty( $title ) )
337
- $ga_accounts[$ua] = $title;
338
  }
 
 
 
 
 
 
 
 
339
  }
340
- } else if ( $arr['feed']['link_attr']['href'] == 'https://www.google.com/analytics/feeds/accounts/default' ) {
341
- foreach ( $arr['feed']['entry'] as $site ) {
342
- if ( isset( $site['dxp:property']['3_attr']['value'] ) )
343
- $ua = trim( $site['dxp:property']['3_attr']['value'] );
344
- if ( isset( $site['dxp:property']['1_attr']['value'] ) )
345
- $title = trim( $site['dxp:property']['1_attr']['value'] );
346
- if ( !empty( $ua ) && !empty( $title ) )
347
- $ga_accounts[$ua] = $title;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
  }
349
  }
350
- asort( $ga_accounts );
351
 
352
- $select = '<select class="chzn-select" name="uastring" data-placeholder="' . __( 'Please select the correct Analytics Account', 'google-analytics-for-wordpress' ) . '" id="ga_account">';
353
- $select .= "\t<option></option>\n";
354
- foreach ( $ga_accounts as $ua => $title ) {
355
- $sel = selected( $ua, $currentua, false );
356
- $select .= "\t" . '<option ' . $sel . ' value="' . $ua . '">' . $title . ' - ' . $ua . '</option>' . "\n";
357
  }
358
- $select .= '</select>';
359
-
360
- $line = '<input type="hidden" name="ga_token" value="' . $token . '"/>';
361
- $line .= __( 'Please select the correct Analytics account to track:', 'google-analytics-for-wordpress' ) . '<br/>';
362
- $line .= '<table class="form_table">';
363
- $line .= '<tr><th>' . __( 'Profile', 'google-analytics-for-wordpress' ) . ':</th><td>' . $select . '</td></tr>';
364
- $line .= '</table>';
365
-
366
- $try = 1;
367
- if ( isset( $_GET['try'] ) )
368
- $try = $_GET['try'] + 1;
369
-
370
- if ( count( $ga_accounts ) == 0 && $try < 4 && isset( $_GET['token'] ) ) {
371
- $line .= '<script type="text/javascript">
372
- window.location="' . $this->plugin_options_url() . '&switchua=1&token=' . $token . '&try=' . $try . '";
373
- </script>';
374
  }
375
- $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.', 'google-analytics-for-wordpress' );
376
- $line .= '<br/><br/>';
377
- $line .= __( 'Refresh this listing or switch to another account: ', 'google-analytics-for-wordpress' );
378
- } else {
379
- $line = __( 'Unfortunately, an error occurred while connecting to Google, please try again:', 'google-analytics-for-wordpress' );
380
  }
381
- } else {
382
- $line = __( 'Unfortunately, an error occurred while connecting to Google, please try again:', 'google-analytics-for-wordpress' );
383
  }
384
 
385
- $query = $this->plugin_options_url() . '&reauth=true';
386
- $line .= '<a class="button" href="' . $query . '">' . __( 'Re-authenticate with Google', 'google-analytics-for-wordpress' ) . '</a>';
387
- } else {
388
- $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;', 'google-analytics-for-wordpress' ) . '</a>';
389
- }
390
- $line = '<div id="uastring_automatic">' . $line . '</div><div style="display:none;" id="uastring_manual">' . __( 'Manually enter your UA code: ', 'google-analytics-for-wordpress' ) . '<input id="uastring" name="uastring_man" type="text" size="20" maxlength="40" value="' . $options['uastring'] . '"/></div>';
391
- $rows = array();
392
- $content = '';
393
- $rows[] = array(
394
- 'id' => 'uastring',
395
- 'label' => __( 'Analytics Profile', 'google-analytics-for-wordpress' ),
396
- 'desc' => '<input type="checkbox" name="manual_uastring" ' . checked( $options['manual_uastring'], true, false ) . ' id="switchtomanual"/> <label for="switchtomanual">' . __( 'Manually enter your UA code', 'google-analytics-for-wordpress' ) . '</label>',
397
- 'content' => $line
398
- );
399
- $temp_content = $this->select( 'position', array( 'header' => __( 'In the header (default)', 'google-analytics-for-wordpress' ), 'manual' => __( 'Insert manually', 'google-analytics-for-wordpress' ) ) );
400
- if ( $options['theme_updated'] && $options['position'] == 'manual' ) {
401
- $temp_content .= '<input type="hidden" name="theme_updated" value="off"/>';
402
- echo '<div id="message" class="updated" style="background-color:lightgreen;border-color:green;"><p><strong>' . __( 'Notice', 'google-analytics-for-wordpress' ), ':</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.', 'google-analytics-for-wordpress' ) . '</p></div>';
403
- remove_action( 'admin_footer', array( &$this, 'theme_switch_warning' ) );
404
- }
405
- $desc = '<div id="position_header">' . sprintf( __( '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 %sread this page%s.' ), '<a href="http://yoast.com/wordpress/google-analytics/manual-placement/">', '</a>' ) . '</div>';
406
- $desc .= '<div id="position_manual">' . sprintf( __( '%sFollow the instructions here%s to choose the location for your tracking code manually.', 'google-analytics-for-wordpress' ), '<a href="http://yoast.com/wordpress/google-analytics/manual-placement/">', '</a>' ) . '</div>';
407
-
408
- $rows[] = array(
409
- 'id' => 'position',
410
- 'label' => __( 'Where should the tracking code be placed', 'google-analytics-for-wordpress' ),
411
- 'desc' => $desc,
412
- 'content' => $temp_content,
413
- );
414
- $rows[] = array(
415
- 'id' => 'trackoutbound',
416
- 'label' => __( 'Track outbound clicks &amp; downloads', 'google-analytics-for-wordpress' ),
417
- 'desc' => __( 'Clicks &amp; downloads will be tracked as events, you can find these under Content &raquo; Event Tracking in your Google Analytics reports.', 'google-analytics-for-wordpress' ),
418
- 'content' => $this->checkbox( 'trackoutbound' ),
419
- );
420
- $rows[] = array(
421
- 'id' => 'advancedsettings',
422
- 'label' => __( 'Show advanced settings', 'google-analytics-for-wordpress' ),
423
- 'desc' => __( 'Only adviced for advanced users who know their way around Google Analytics', 'google-analytics-for-wordpress' ),
424
- 'content' => $this->checkbox( 'advancedsettings' ),
425
- );
426
- $rows[] = array(
427
- 'id' => 'yoast_tracking',
428
- 'label' => __( 'Allow tracking of anonymous data', 'google-analytics-for-wordpress' ),
429
- 'desc' => __( 'By allowing us to track anonymous data we can better help you, because we know with which WordPress configurations, themes and plugins we should test. No personal data will be submitted.', 'google-analytics-for-wordpress' ),
430
- 'content' => $this->checkbox( 'yoast_tracking' ),
431
- );
432
- $this->postbox( 'gasettings', __( 'Google Analytics Settings', 'google-analytics-for-wordpress' ), $this->form_table( $rows ) . $this->save_button() );
433
-
434
- $rows = array();
435
- $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.', 'google-analytics-for-wordpress' ) . '</p>';
436
- $pre_content .= '<p>' . __( 'If you want to start using these custom variables, go to Visitors &raquo; Custom Variables in your Analytics reports.', 'google-analytics-for-wordpress' ) . '</p>';
437
- $rows[] = array(
438
- 'id' => 'cv_loggedin',
439
- 'label' => __( 'Logged in Users', 'google-analytics-for-wordpress' ),
440
- '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.', 'google-analytics-for-wordpress' ),
441
- 'content' => $this->checkbox( 'cv_loggedin' ),
442
- );
443
- $rows[] = array(
444
- 'id' => 'cv_post_type',
445
- 'label' => __( 'Post type', 'google-analytics-for-wordpress' ),
446
- 'desc' => __( 'Allows you to see pageviews per post type, especially useful if you use multiple custom post types.', 'google-analytics-for-wordpress' ),
447
- 'content' => $this->checkbox( 'cv_post_type' ),
448
- );
449
- $rows[] = array(
450
- 'id' => 'cv_authorname',
451
- 'label' => __( 'Author Name', 'google-analytics-for-wordpress' ),
452
- 'desc' => __( 'Allows you to see pageviews per author.', 'google-analytics-for-wordpress' ),
453
- 'content' => $this->checkbox( 'cv_authorname' ),
454
- );
455
- $rows[] = array(
456
- 'id' => 'cv_tags',
457
- 'label' => __( 'Tags', 'google-analytics-for-wordpress' ),
458
- 'desc' => __( 'Allows you to see pageviews per tags using advanced segments.', 'google-analytics-for-wordpress' ),
459
- 'content' => $this->checkbox( 'cv_tags' ),
460
- );
461
- $rows[] = array(
462
- 'id' => 'cv_year',
463
- 'label' => __( 'Publication year', 'google-analytics-for-wordpress' ),
464
- 'desc' => __( 'Allows you to see pageviews per year of publication, showing you if your old posts still get traffic.', 'google-analytics-for-wordpress' ),
465
- 'content' => $this->checkbox( 'cv_year' ),
466
- );
467
- $rows[] = array(
468
- 'id' => 'cv_category',
469
- 'label' => __( 'Single Category', 'google-analytics-for-wordpress' ),
470
- 'desc' => __( 'Allows you to see pageviews per category, works best when each post is in only one category.', 'google-analytics-for-wordpress' ),
471
- 'content' => $this->checkbox( 'cv_category' ),
472
- );
473
- $rows[] = array(
474
- 'id' => 'cv_all_categories',
475
- 'label' => __( 'All Categories', 'google-analytics-for-wordpress' ),
476
- 'desc' => __( 'Allows you to see pageviews per category using advanced segments, should be used when you use multiple categories per post.', 'google-analytics-for-wordpress' ),
477
- 'content' => $this->checkbox( 'cv_all_categories' ),
478
- );
479
-
480
- $modules['Custom Variables'] = 'customvarsettings';
481
- $this->postbox( 'customvarsettings', __( 'Custom Variables Settings', 'google-analytics-for-wordpress' ), $pre_content . $this->form_table( $rows ) . $this->save_button() );
482
-
483
- $rows = array();
484
- $rows[] = array(
485
- 'id' => 'ignore_userlevel',
486
- 'label' => __( 'Ignore users', 'google-analytics-for-wordpress' ),
487
- 'desc' => __( 'Users of the role you select and higher will be ignored, so if you select Editor, all Editors and Administrators will be ignored.', 'google-analytics-for-wordpress' ),
488
- 'content' => $this->select( 'ignore_userlevel', array(
489
- '11' => __( 'Ignore no-one', 'google-analytics-for-wordpress' ),
490
- '8' => __( 'Administrator', 'google-analytics-for-wordpress' ),
491
- '5' => __( 'Editor', 'google-analytics-for-wordpress' ),
492
- '2' => __( 'Author', 'google-analytics-for-wordpress' ),
493
- '1' => __( 'Contributor', 'google-analytics-for-wordpress' ),
494
- '0' => __( 'Subscriber (ignores all logged in users)', 'google-analytics-for-wordpress' ),
495
- ) ),
496
- );
497
- $rows[] = array(
498
- 'id' => 'outboundpageview',
499
- 'label' => __( 'Track outbound clicks as pageviews', 'google-analytics-for-wordpress' ),
500
- '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.', 'google-analytics-for-wordpress' ),
501
- 'content' => $this->checkbox( 'outboundpageview' ),
502
- );
503
- $rows[] = array(
504
- 'id' => 'downloadspageview',
505
- 'label' => __( 'Track downloads as pageviews', 'google-analytics-for-wordpress' ),
506
- 'desc' => __( 'Not recommended, as this would skew your statistics, but it does make it possible to track downloads as goals.', 'google-analytics-for-wordpress' ),
507
- 'content' => $this->checkbox( 'downloadspageview' ),
508
- );
509
- $rows[] = array(
510
- 'id' => 'dlextensions',
511
- 'label' => __( 'Extensions of files to track as downloads', 'google-analytics-for-wordpress' ),
512
- 'content' => $this->textinput( 'dlextensions' ),
513
- );
514
- if ( $options['outboundpageview'] ) {
515
- $rows[] = array(
516
- 'id' => 'trackprefix',
517
- 'label' => __( 'Prefix to use in Analytics before the tracked pageviews', 'google-analytics-for-wordpress' ),
518
- '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.', 'google-analytics-for-wordpress' ),
519
- 'content' => $this->textinput( 'trackprefix' ),
520
- );
521
- }
522
- $rows[] = array(
523
- 'id' => 'domainorurl',
524
- 'label' => __( 'Track full URL of outbound clicks or just the domain', 'google-analytics-for-wordpress' ),
525
- 'content' => $this->select( 'domainorurl', array(
526
- 'domain' => __( 'Just the domain', 'google-analytics-for-wordpress' ),
527
- 'url' => __( 'Track the complete URL', 'google-analytics-for-wordpress' ),
528
- )
529
- ),
530
- );
531
- $rows[] = array(
532
- 'id' => 'domain',
533
- 'label' => __( 'Subdomain Tracking', 'google-analytics-for-wordpress' ),
534
- 'desc' => sprintf( __( 'This allows you to set the domain that\'s set by %s<code>setDomainName</code>%s for tracking subdomains, if empty this will not be set.', 'google-analytics-for-wordpress' ), '<a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setDomainName">', '</a>' ),
535
- 'content' => $this->textinput( 'domain' ),
536
- );
537
- $rows[] = array(
538
- 'id' => 'trackcrossdomain',
539
- 'label' => __( 'Enable Cross Domain Tracking', 'google-analytics-for-wordpress' ),
540
- 'desc' => sprintf( __( 'This allows you to enable %sCross-Domain Tracking%s for this site. When endabled <code>_setAllowLinker:</code> will be enabled if it is not already.', 'google-analytics-for-wordpress' ), '<a href="http://code.google.com/apis/analytics/docs/tracking/gaTrackingSite.html">', '</a>' ),
541
- 'content' => $this->checkbox( 'trackcrossdomain' ),
542
- );
543
- $rows[] = array(
544
- 'id' => 'primarycrossdomain',
545
- 'label' => __( 'Cross-Domain Tracking, Primary Domain', 'google-analytics-for-wordpress' ),
546
- 'desc' => sprintf( __( 'Set the primary domain used in %s<code>setDomainName</code>%s for cross domain tracking (eg. <code>example-petstore.com</code> ), if empty this will default to your configured Home URL.', 'google-analytics-for-wordpress' ), '<a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setDomainName">', '</a>' ),
547
- 'content' => $this->textinput( 'primarycrossdomain' ),
548
- );
549
- $rows[] = array(
550
- 'id' => 'othercrossdomains',
551
- 'label' => __( 'Cross-Domain Tracking, Other Domains', 'google-analytics-for-wordpress' ),
552
- '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>)', 'google-analytics-for-wordpress' ),
553
- 'content' => $this->textinput( 'othercrossdomains' ),
554
- );
555
- $rows[] = array(
556
- 'id' => 'customcode',
557
- 'label' => __( 'Custom Code', 'google-analytics-for-wordpress' ),
558
- 'desc' => __( 'Not for the average user: this allows you to add a line of code, to be added before the <code>trackPageview</code> call.', 'google-analytics-for-wordpress' ),
559
- 'content' => $this->textinput( 'customcode' ),
560
- );
561
- $rows[] = array(
562
- 'id' => 'trackadsense',
563
- 'label' => __( 'Track AdSense', 'google-analytics-for-wordpress' ),
564
- '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>.', 'google-analytics-for-wordpress' ),
565
- 'content' => $this->checkbox( 'trackadsense' ),
566
- );
567
- $rows[] = array(
568
- 'id' => 'gajslocalhosting',
569
- 'label' => __( 'Host ga.js locally', 'google-analytics-for-wordpress' ),
570
- 'content' => $this->checkbox( 'gajslocalhosting' ) . '<div id="localhostingbox">
571
- ' . __( 'You have to provide a URL to your ga.js file:', 'google-analytics-for-wordpress' ) . '
572
- <input type="text" name="gajsurl" size="30" value="' . $options['gajsurl'] . '"/>
573
- </div>',
574
- '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.', 'google-analytics-for-wordpress' )
575
- );
576
- $rows[] = array(
577
- 'id' => 'extrase',
578
- 'label' => __( 'Track extra Search Engines', 'google-analytics-for-wordpress' ),
579
- 'content' => $this->checkbox( 'extrase' ) . '<div id="extrasebox">
580
- ' . __( 'You can provide a custom URL to the extra search engines file if you want:', 'google-analytics-for-wordpress' ) . '
581
- <input type="text" name="extraseurl" size="30" value="' . $options['extraseurl'] . '"/>
582
- </div>',
583
- );
584
- $rows[] = array(
585
- 'id' => 'rsslinktagging',
586
- 'label' => __( 'Tag links in RSS feed with campaign variables', 'google-analytics-for-wordpress' ),
587
- '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.', 'google-analytics-for-wordpress' ),
588
- 'content' => $this->checkbox( 'rsslinktagging' ),
589
- );
590
- $rows[] = array(
591
- 'id' => 'trackregistration',
592
- 'label' => __( 'Add tracking to the login and registration forms', 'google-analytics-for-wordpress' ),
593
- 'content' => $this->checkbox( 'trackregistration' ),
594
- );
595
- $rows[] = array(
596
- 'id' => 'trackcommentform',
597
- 'label' => __( 'Add tracking to the comment forms', 'google-analytics-for-wordpress' ),
598
- 'content' => $this->checkbox( 'trackcommentform' ),
599
- );
600
- $rows[] = array(
601
- 'id' => 'allowanchor',
602
- 'label' => __( 'Use # instead of ? for Campaign tracking', 'google-analytics-for-wordpress' ),
603
- '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.', 'google-analytics-for-wordpress' ),
604
- 'content' => $this->checkbox( 'allowanchor' ),
605
- );
606
- $rows[] = array(
607
- 'id' => 'allowlinker',
608
- 'label' => __( 'Add <code>_setAllowLinker</code>', 'google-analytics-for-wordpress' ),
609
- '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.', 'google-analytics-for-wordpress' ),
610
- 'content' => $this->checkbox( 'allowlinker' ),
611
- );
612
- $rows[] = array(
613
- 'id' => 'allowhash',
614
- 'label' => __( 'Set <code>_setAllowHash</code> to false', 'google-analytics-for-wordpress' ),
615
- '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.', 'google-analytics-for-wordpress' ),
616
- 'content' => $this->checkbox( 'allowhash' ),
617
- );
618
- $rows[] = array(
619
- 'id' => 'anonymizeip',
620
- 'label' => __( 'Anonymize IP\'s', 'google-analytics-for-wordpress' ),
621
- '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.', 'google-analytics-for-wordpress' ),
622
- 'content' => $this->checkbox( 'anonymizeip' ),
623
- );
624
- $modules['Advanced Settings'] = 'advancedgasettings';
625
- $this->postbox( 'advancedgasettings', __( 'Advanced Settings', 'google-analytics-for-wordpress' ), $this->form_table( $rows ) . $this->save_button() );
626
-
627
- $rows = array();
628
- $rows[] = array(
629
- 'id' => 'internallink',
630
- 'label' => __( 'Internal links to track as outbound', 'google-analytics-for-wordpress' ),
631
- '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>', 'google-analytics-for-wordpress' ),
632
- 'content' => $this->textinput( 'internallink' ),
633
- );
634
- $rows[] = array(
635
- 'id' => 'internallinklabel',
636
- 'label' => __( 'Label to use', 'google-analytics-for-wordpress' ),
637
- '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".', 'google-analytics-for-wordpress' ),
638
- 'content' => $this->textinput( 'internallinklabel' ),
639
- );
640
- $modules['Internal Link Tracking'] = 'internallinktracking';
641
- $this->postbox( 'internallinktracking', __( 'Internal Links to Track as Outbound', 'google-analytics-for-wordpress' ), $this->form_table( $rows ) . $this->save_button() );
642
-
643
- if ( defined( 'WPSC_VERSION' ) ) {
644
- $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.', 'google-analytics-for-wordpress' );
645
- $rows = array();
646
- $rows[] = array(
647
- 'id' => 'wpec_tracking',
648
- 'label' => __( 'Enable transaction tracking', 'google-analytics-for-wordpress' ),
649
- 'content' => $this->checkbox( 'wpec_tracking' ),
650
- );
651
- $this->postbox( 'wpecommerce', __( 'WordPress e-Commerce Settings', 'google-analytics-for-wordpress' ), $pre_content . $this->form_table( $rows ) . $this->save_button() );
652
- $modules['WordPress e-Commerce'] = 'wpecommerce';
653
  }
654
 
655
- global $Shopp;
656
- if ( isset( $Shopp ) ) {
657
- $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.', 'google-analytics-for-wordpress' );
658
- $rows = array();
659
- $rows[] = array(
660
- 'id' => 'shopp_tracking',
661
- 'label' => __( 'Enable transaction tracking', 'google-analytics-for-wordpress' ),
662
- 'content' => $this->checkbox( 'shopp_tracking' ),
663
- );
664
- $this->postbox( 'shoppecommerce', __( 'Shopp e-Commerce Settings', 'google-analytics-for-wordpress' ), $pre_content . $this->form_table( $rows ) . $this->save_button() );
665
- $modules['Shopp'] = 'shoppecommerce';
666
  }
667
- $pre_content = '<p>' . sprintf( __( 'If you want to confirm that tracking on your blog is working as it should, enable this option and check the console in %sFirebug%s (for Firefox), %sFirebug Lite%s (for other browsers) or Chrome &amp; Safari\'s Web Inspector. Be absolutely sure to disable debugging afterwards, as it is slower than normal tracking.', 'google-analytics-for-wordpress' ), '<a href="http://getfirebug.com/">', '</a>', '<a href="http://getfirebug.com/firebuglite">', '</a>' ) . '</p>';
668
- $pre_content .= '<p><strong>' . __( 'Note', 'google-analytics-for-wordpress' ) . '</strong>: ' . __( 'the debugging and firebug scripts are only loaded for admins.', 'google-analytics-for-wordpress' ) . '</p>';
669
- $rows = array();
670
- $rows[] = array(
671
- 'id' => 'debug',
672
- 'label' => __( 'Enable debug mode', 'google-analytics-for-wordpress' ),
673
- 'content' => $this->checkbox( 'debug' ),
674
- );
675
- $rows[] = array(
676
- 'id' => 'firebuglite',
677
- 'label' => __( 'Enable Firebug Lite', 'google-analytics-for-wordpress' ),
678
- 'content' => $this->checkbox( 'firebuglite' ),
679
- );
680
- $this->postbox( 'debugmode', __( 'Debug Mode', 'google-analytics-for-wordpress' ), $pre_content . $this->form_table( $rows ) . $this->save_button() );
681
- $modules['Debug Mode'] = 'debugmode';
682
- ?>
683
- </form>
684
- <form action="<?php echo $this->plugin_options_url(); ?>" method="post"
685
- onsubmit="javascript:return(confirm('<?php _e( 'Do you really want to reset all settings?', 'google-analytics-for-wordpress' ); ?>'));">
686
- <input type="hidden" name="reset" value="true"/>
687
- <input type="hidden" name="plugin" value="google-analytics-for-wordpress"/>
688
-
689
- <div class="submit"><input type="submit" value="<?php _e( 'Reset All Settings &raquo;', 'google-analytics-for-wordpress' ); ?>'"/></div>
690
- </form>
691
- </div>
692
- </div>
693
- </div>
694
- <div class="postbox-container side" style="width:261px;">
695
- <div class="metabox-holder">
696
- <div class="meta-box-sortables">
697
- <?php
698
- $this->postbox( 'spread', '<strong>' . __( 'Help Spread the Word!', 'google-analytics-for-wordpress' ) . '</strong>',
699
- '<ul>'
700
- . '<li><a href="http://wordpress.org/extend/plugins/google-analytics-for-wordpress/">' . __( 'Rate the plugin 5★ on WordPress.org', 'google-analytics-for-wordpress' ) . '</a></li>'
701
- . '<li><a href="http://wordpress.org/tags/google-analytics-for-wordpress">' . __( 'Help out other users in the forums', 'google-analytics-for-wordpress' ) . '</a></li>'
702
- . '<li>' . sprintf( __( 'Blog about it & link to the %1$splugin page%2$s' ), '<a href="http://yoast.com/wordpress/google-analytics/#utm_source=wpadmin&utm_medium=sidebanner&utm_term=link&utm_campaign=wpgaplugin">', '</a>' ) . '</li></ul>' );
703
- ?>
704
- <a target="_blank"
705
- href="https://yoast.com/hire-us/create-ga-goals/#utm_source=gawp-config&utm_medium=banner&utm_campaign=ga-goals-banner"><img
706
- src="<?php echo GAWP_URL; ?>images/banner-ga-goals.png" alt="Google Analytics Goals"/></a><br/>
707
- <br/>
708
- <a target="_blank"
709
- href="https://yoast.com/hire-us/website-review/#utm_source=gawp-config&utm_medium=banner&utm_campaign=website-review-banner"><img
710
- src="<?php echo GAWP_URL; ?>images/banner-website-review.png" alt="Website Review"/></a><br/>
711
- <br/>
712
- <a target="_blank"
713
- href="https://yoast.com/hire-us/conversion-review/#utm_source=gawp-config&utm_medium=banner&utm_campaign=conversion-review-banner"><img
714
- src="<?php echo GAWP_URL; ?>images/banner-conversion-review.png" alt="Conversion Review"/></a>
715
- </div>
716
- <br/><br/><br/>
717
- </div>
718
- </div>
719
- </div>
720
- <?php
721
- }
722
 
723
- function set_defaults() {
724
- $options = array(
725
- 'advancedsettings' => false,
726
- 'allowanchor' => false,
727
- 'allowhash' => false,
728
- 'allowlinker' => false,
729
- 'anonymizeip' => false,
730
- 'customcode' => '',
731
- 'cv_loggedin' => false,
732
- 'cv_authorname' => false,
733
- 'cv_category' => false,
734
- 'cv_all_categories' => false,
735
- 'cv_tags' => false,
736
- 'cv_year' => false,
737
- 'cv_post_type' => false,
738
- 'debug' => false,
739
- 'dlextensions' => 'doc,exe,js,pdf,ppt,tgz,zip,xls',
740
- 'domain' => '',
741
- 'domainorurl' => 'domain',
742
- 'extrase' => false,
743
- 'extraseurl' => '',
744
- 'firebuglite' => false,
745
- 'ga_token' => '',
746
- 'ga_api_responses' => array(),
747
- 'gajslocalhosting' => false,
748
- 'gajsurl' => '',
749
- 'ignore_userlevel' => '11',
750
- 'internallink' => false,
751
- 'internallinklabel' => '',
752
- 'outboundpageview' => false,
753
- 'downloadspageview' => false,
754
- 'othercrossdomains' => '',
755
- 'position' => 'footer',
756
- 'primarycrossdomain' => '',
757
- 'theme_updated' => false,
758
- 'trackcommentform' => true,
759
- 'trackcrossdomain' => false,
760
- 'trackadsense' => false,
761
- 'trackoutbound' => true,
762
- 'trackregistration' => false,
763
- 'rsslinktagging' => true,
764
- 'uastring' => '',
765
- 'version' => GAWP_VERSION,
766
- );
767
- update_option( $this->optionname, $options );
768
- return $options;
769
- }
770
 
771
- function warning() {
772
- $options = get_option( $this->optionname );
773
- if ( !isset( $options['uastring'] ) || empty( $options['uastring'] ) ) {
774
- echo "<div id='message' class='error'><p><strong>" . __( "Google Analytics is not active.", 'google-analytics-for-wordpress' ) . "</strong> " . sprintf( __( "You must %sselect which Analytics Profile to track%s before it can work.", 'google-analytics-for-wordpress' ), "<a href='" . $this->plugin_options_url() . "'>", "</a>" ) . "</p></div>";
775
- }
776
- } // end warning()
 
777
 
 
 
 
778
 
779
- function authenticate() {
780
- if ( isset( $_REQUEST['ga_oauth_callback'] ) ) {
781
- $o = get_option( $this->optionname );
782
- if ( isset( $o['gawp_oauth']['oauth_token'] ) && $o['gawp_oauth']['oauth_token'] == $_REQUEST['oauth_token'] ) {
783
  $gdata = new WP_GData(
784
  array(
785
  'scope' => 'https://www.google.com/analytics/feeds/',
786
- 'xoauth_displayname' => 'Google Analytics for WordPress by Yoast'
787
- ),
788
- $o['gawp_oauth']['oauth_token'],
789
- $o['gawp_oauth']['oauth_token_secret']
790
  );
791
 
792
- $o['gawp_oauth']['access_token'] = $gdata->get_access_token( $_REQUEST['oauth_verifier'] );
793
- unset( $o['gawp_oauth']['oauth_token'] );
794
- unset( $o['gawp_oauth']['oauth_token_secret'] );
795
- $o['ga_token'] = $o['gawp_oauth']['access_token']['oauth_token'];
 
 
 
 
 
 
 
 
796
  }
 
797
 
798
- update_option( $this->optionname, $o );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
799
 
800
- wp_redirect( menu_page_url( $this->hook, false ) );
801
- exit;
802
  }
803
 
804
- if ( !empty( $_GET['reauth'] ) ) {
805
- $gdata = new WP_GData(
806
- array(
807
- 'scope' => 'https://www.google.com/analytics/feeds/',
808
- 'xoauth_displayname' => 'Google Analytics for WordPress by Yoast'
809
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
810
  );
811
 
812
- $oauth_callback = add_query_arg( array( 'ga_oauth_callback' => 1 ), menu_page_url( 'google-analytics-for-wordpress', false ) );
813
- $request_token = $gdata->get_request_token( $oauth_callback );
814
 
815
- $options = get_option( $this->optionname );
816
- unset( $options['ga_token'] );
817
- unset( $options['gawp_oauth']['access_token'] );
818
- $options['gawp_oauth']['oauth_token'] = $request_token['oauth_token'];
819
- $options['gawp_oauth']['oauth_token_secret'] = $request_token['oauth_token_secret'];
820
- update_option( $this->optionname, $options );
821
 
822
- wp_redirect( $gdata->get_authorize_url( $request_token ) );
823
- exit;
824
  }
825
 
826
- } //end reauthenticate()
827
- } // end class GA_Admin
828
 
829
- $ga_admin = new GA_Admin();
 
 
1
  <?php
2
+ /**
3
+ * This class is for the backend, extendable for all child classes
4
+ */
5
+ if ( ! function_exists( 'wp_verify_nonce' ) ) {
6
+ require_once( ABSPATH . 'wp-includes/pluggable.php' );
7
+ }
8
 
 
 
 
 
 
9
  require_once plugin_dir_path( __FILE__ ) . '/wp-gdata/wp-gdata.php';
10
 
11
+ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
12
 
13
+ class Yoast_GA_Admin {
 
 
14
 
15
+ private $form_namespace;
16
 
17
+ public $options;
 
 
 
 
 
 
18
 
19
+ private $form_prefix = 'ga_general';
 
 
 
 
 
20
 
21
+ public function __construct() {
22
+ add_action( 'plugins_loaded', array( $this, 'init_ga' ) );
23
+ add_action( 'admin_init', array( $this, 'init_settings' ) );
24
+ }
25
 
26
+ /**
27
+ * Init function when the plugin is loaded
28
+ */
29
+ public function init_ga() {
30
+ add_action( 'admin_menu', array( $this, 'create_menu' ), 5 );
31
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
32
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
33
+ }
34
 
35
+ /**
36
+ * Init function for the settings of GA
37
+ */
38
+ public function init_settings() {
39
+ $this->options = get_option( 'yst_ga' );
40
 
41
+ if ( false == $this->options ) {
42
+ add_option( 'yst_ga', $this->default_ga_values() );
43
+ $this->options = get_option( 'yst_ga' );
44
+ }
45
 
46
+ if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
47
+ if ( isset( $_POST['ga-form-settings'] ) && wp_verify_nonce( $_POST['yoast_ga_nonce'], 'save_settings' ) ) {
48
+ // Post submitted and verified with our nonce
49
+ $this->save_settings( $_POST );
50
 
51
+ add_settings_error(
52
+ 'yoast_google_analytics',
53
+ 'yoast_google_analytics',
54
+ __( 'Settings saved!', 'google-analytics-for-wordpress' ),
55
+ 'updated'
56
+ );
57
+ }
58
+ }
59
 
60
+ $this->connect_with_google_analytics();
61
+ }
62
 
63
+ /**
64
+ * Set the default GA settings here
65
+ * @return array
66
+ */
67
+ public function default_ga_values() {
68
+ return array(
69
+ $this->form_prefix => array(
70
+ 'analytics_profile' => NULL,
71
+ 'manual_ua_code' => 0,
72
+ 'manual_ua_code_field' => NULL,
73
+ 'track_internal_as_outbound' => NULL,
74
+ 'track_internal_as_label' => NULL,
75
+ 'track_outbound' => 0,
76
+ 'anonymous_data' => 0,
77
+ 'enable_universal' => 0,
78
+ 'demographics' => 0,
79
+ 'ignore_users' => 'editor',
80
+ 'anonymize_ips' => NULL,
81
+ 'track_download_as' => 'event',
82
+ 'extensions_of_files' => 'doc,exe,js,pdf,ppt,tgz,zip,xls',
83
+ 'track_full_url' => 'domain',
84
+ 'subdomain_tracking' => NULL,
85
+ 'tag_links_in_rss' => 0,
86
+ 'allow_anchor' => 0,
87
+ 'add_allow_linker' => 0,
88
+ 'custom_code' => NULL,
89
+ 'debug_mode' => 0,
90
+ 'firebug_lite' => 0,
91
+ )
92
+ );
93
+ }
94
 
95
+ /**
96
+ * Return the setting by name
97
+ *
98
+ * @param $name
99
+ *
100
+ * @return null
101
+ */
102
+ public function get_setting( $name ) {
103
+
104
+ if ( isset( $this->options[$this->form_prefix][$name] ) ) {
105
+ return $this->options[$this->form_prefix][$name];
106
+ } else {
107
+ return NULL;
108
+ }
109
+ }
110
 
111
+ /**
112
+ * This function saves the settings in the option field and returns a wp success message on success
113
+ *
114
+ * @param $data
115
+ */
116
+ public function save_settings( $data ) {
117
+ foreach ( $data as $key => $value ) {
118
+ $this->options[$this->form_prefix][$key] = $value;
119
+ }
120
+
121
+ // Check checkboxes, on a uncheck they won't be posted to this function
122
+ $defaults = $this->default_ga_values();
123
+ foreach ( $defaults['ga_general'] as $key => $value ) {
124
+ if ( ! isset( $data[$key] ) ) {
125
+ $this->options[$this->form_prefix][$key] = $value;
126
+ }
127
+ }
128
+
129
+ if ( update_option( 'yst_ga', $this->options ) ) {
130
+ // Success!
131
+ } else {
132
+ // Fail..
133
+ }
134
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  }
 
136
 
137
+ /**
138
+ * Get the singleton instance of this class
139
+ *
140
+ * @return object
141
+ */
142
+ public static function get_instance() {
143
+ if ( ! ( self::$instance instanceof self ) ) {
144
+ self::$instance = new self();
145
+ }
146
 
147
+ return self::$instance;
 
148
  }
 
 
149
 
150
+ /**
151
+ * Create the admin menu
152
+ *
153
+ * @todo, we need to implement a new icon for this, currently we're using the WP seo icon
154
+ */
155
+ public function create_menu( $param = NULL ) {
156
+ // Add main page
157
+ add_menu_page( __( 'Yoast Google Analytics:', 'google-analytics-for-wordpress' ) . ' ' . __( 'General Settings', 'google-analytics-for-wordpress' ), __( 'Analytics', 'google-analytics-for-wordpress' ), 'manage_options', 'yst_ga_dashboard', array(
158
+ $this,
159
+ 'load_page'
160
+ ), plugins_url( 'img/yoast-icon.png', GAWP_FILE ), '2.00013467543' );
161
+
162
+ // Sub menu pages
163
+ $submenu_pages = array(
164
+ array(
165
+ 'yst_ga_dashboard',
166
+ __( 'Yoast Google Analytics:', 'google-analytics-for-wordpress' ) . ' ' . __( 'Dashboard', 'google-analytics-for-wordpress' ),
167
+ __( 'Dashboard', 'google-analytics-for-wordpress' ),
168
+ 'manage_options',
169
+ 'yst_ga_dashboard',
170
+ array( $this, 'load_page' ),
171
+ array( array( $this, 'yst_ga_dashboard' ) )
172
+ ),
173
+ array(
174
+ 'yst_ga_dashboard',
175
+ __( 'Yoast Google Analytics:', 'google-analytics-for-wordpress' ) . ' ' . __( 'Settings', 'google-analytics-for-wordpress' ),
176
+ __( 'Settings', 'google-analytics-for-wordpress' ),
177
+ 'manage_options',
178
+ 'yst_ga_settings',
179
+ array( $this, 'load_page' ),
180
+ array( array( $this, 'yst_ga_settings' ) )
181
+ ),
182
+ array(
183
+ 'yst_ga_dashboard',
184
+ __( 'Yoast Google Analytics:', 'google-analytics-for-wordpress' ) . ' ' . __( 'Extensions', 'google-analytics-for-wordpress' ),
185
+ __( '<span style="color:#f18500">' . __( 'Extensions', 'google-analytics-for-wordpress' ) . '</span>', 'google-analytics-for-wordpress' ),
186
+ 'manage_options',
187
+ 'yst_ga_licenses',
188
+ array( $this, 'load_page' ),
189
+ null
190
+ ),
191
+ );
192
+
193
+ if ( count( $submenu_pages ) ) {
194
+ foreach ( $submenu_pages as $submenu_page ) {
195
+ // Add submenu page
196
+ add_submenu_page( $submenu_page[0], $submenu_page[1], $submenu_page[2], $submenu_page[3], $submenu_page[4], $submenu_page[5] );
197
+ }
198
+ }
199
+ }
200
 
201
+ /**
202
+ * Add the scripts to the admin head
203
+ *
204
+ * @todo add minified JS files
205
+ */
206
+ public function enqueue_scripts() {
207
+ wp_enqueue_script( 'yoast_ga_admin', GAWP_URL . 'js/yoast_ga_admin.js' );
208
+ }
209
 
210
+ /**
211
+ * Add the styles in the admin head
212
+ *
213
+ * @todo add minified CSS files
214
+ */
215
+ public function enqueue_styles() {
216
+ wp_enqueue_style( 'yoast_ga_styles', GAWP_URL . 'css/yoast_ga_styles.css' );
217
+ }
218
 
219
+ /**
220
+ * Load the page of a menu item in the GA plugin
221
+ */
222
+ public function load_page() {
223
+
224
+ require_once GAWP_PATH . 'admin/class-admin-ga-js.php';
225
+
226
+ if ( isset( $_GET['page'] ) ) {
227
+ switch ( $_GET['page'] ) {
228
+ case 'yst_ga_settings':
229
+ require_once( GAWP_PATH . 'admin/pages/settings.php' );
230
+
231
+ break;
232
+ case 'yst_ga_licenses':
233
+ require_once( GAWP_PATH . 'admin/pages/extensions.php' );
234
+ break;
235
+ case 'yst_ga_dashboard':
236
+ default:
237
+ require_once( GAWP_PATH . 'admin/pages/dashboard.php' );
238
+ break;
239
+ }
240
  }
241
+ }
242
 
243
+ /**
244
+ * Create a form element to init a form
245
+ *
246
+ * @param $namespace
247
+ *
248
+ * @return string
249
+ */
250
+ public function create_form( $namespace ) {
251
+ $this->form_namespace = $namespace;
252
+
253
+ $action = $_SERVER['PHP_SELF'];
254
+ if ( isset( $_GET['page'] ) ) {
255
+ $action .= '?page=' . $_GET['page'];
256
  }
257
 
258
+ return '<form action="' . $action . '" method="post" id="yoast-ga-form-' . $this->form_namespace . '" class="yoast_ga_form">' . wp_nonce_field( 'save_settings', 'yoast_ga_nonce', NULL, false );
259
+ }
260
+
261
+ /**
262
+ * Return the form end tag and the submit button
263
+ *
264
+ * @param string $button_label
265
+ * @param string $name
266
+ *
267
+ * @return null|string
268
+ */
269
+ public function end_form( $button_label = "Save changes", $name = 'submit' ) {
270
+ $output = NULL;
271
+ $output .= '<div class="ga-form ga-form-input">';
272
+ $output .= '<input type="submit" name="ga-form-' . $name . '" value="' . $button_label . '" class="button button-primary ga-form-submit" id="yoast-ga-form-submit-' . $this->form_namespace . '">';
273
+ $output .= '</div></form>';
274
+
275
+ return $output;
276
+ }
277
+
278
+ /**
279
+ * Create a input form element with our labels and wrap them
280
+ *
281
+ * @param string $type
282
+ * @param null $title
283
+ * @param null $name
284
+ * @param null $text_label
285
+ * @param null $description
286
+ *
287
+ * @return null|string
288
+ */
289
+ public function input( $type = 'text', $title = NULL, $name = NULL, $text_label = NULL, $description = NULL ) {
290
+ $input = NULL;
291
+ $id = str_replace( '[', '-', $name );
292
+ $id = str_replace( ']', '', $id );
293
+
294
+ $input .= '<div class="ga-form ga-form-input">';
295
+ if ( ! is_null( $title ) ) {
296
+ $input .= '<label class="ga-form ga-form-' . $type . '-label ga-form-label-left" id="yoast-ga-form-label-' . $type . '-' . $this->form_namespace . '-' . $id . '" />' . $title . ':</label>';
297
  }
298
 
299
+ if ( $type == 'checkbox' && $this->get_setting( $name ) == 1 ) {
300
+ $input .= '<input type="' . $type . '" class="ga-form ga-form-checkbox" id="yoast-ga-form-' . $type . '-' . $this->form_namespace . '-' . $id . '" name="' . $name . '" value="1" checked="checked" />';
301
+ } elseif ( $type == 'checkbox' ) {
302
+ $input .= '<input type="' . $type . '" class="ga-form ga-form-checkbox" id="yoast-ga-form-' . $type . '-' . $this->form_namespace . '-' . $id . '" name="' . $name . '" value="1" />';
303
+ } else {
304
+ $input .= '<input type="' . $type . '" class="ga-form ga-form-' . $type . '" id="yoast-ga-form-' . $type . '-' . $this->form_namespace . '-' . $id . '" name="' . $name . '" value="' . stripslashes( $this->get_setting( $name ) ) . '" />';
305
+ }
306
 
307
+ if ( ! is_null( $text_label ) ) {
308
+ $input .= '<label class="ga-form ga-form-' . $type . '-label" id="yoast-ga-form-label-' . $type . '-textlabel-' . $this->form_namespace . '-' . $id . '" for="yoast-ga-form-' . $type . '-' . $this->form_namespace . '-' . $id . '" />' . __( $text_label, 'google-analytics-for-wordpress' ) . '</label>';
 
 
309
  }
310
 
311
+ $input .= '</div>';
 
312
 
313
+ // If we get a description, append it to this select field in a new row
314
+ if ( ! is_null( $description ) ) {
315
+ $input .= '<div class="ga-form ga-form-input">';
316
+ $input .= '<label class="ga-form ga-form-select-label ga-form-label-left" id="yoast-ga-form-description-select-' . $this->form_namespace . '-' . $id . '" />&nbsp;</label>';
317
+ $input .= '<span class="ga-form ga-form-description">' . __( $description, 'google-analytics-for-wordpress' ) . '</span>';
318
+ $input .= '</div>';
319
+ }
320
 
321
+ return $input;
322
+ }
323
 
324
+ /**
325
+ * Generate a select box
326
+ *
327
+ * @param $title
328
+ * @param $name
329
+ * @param $values
330
+ * @param null $description
331
+ * @param bool $multiple
332
+ *
333
+ * @return null|string
334
+ */
335
+ public function select( $title, $name, $values, $description = NULL, $multiple = false ) {
336
+ $select = NULL;
337
+ $id = str_replace( '[', '-', $name );
338
+ $id = str_replace( ']', '', $id );
339
+ $select .= '<div class="ga-form ga-form-input">';
340
+ if ( ! is_null( $title ) ) {
341
+ $select .= '<label class="ga-form ga-form-select-label ga-form-label-left" id="yoast-ga-form-label-select-' . $this->form_namespace . '-' . $id . '" />' . __( $title, 'google-analytics-for-wordpress' ) . ':</label>';
342
+ }
343
 
344
+ if ( $multiple ) {
345
+ $select .= '<select multiple name="' . $name . '[]" id="yoast-ga-form-select-' . $this->form_namespace . '-' . $id . '" class="ga-multiple">';
346
+ } else {
347
+ $select .= '<select name="' . $name . '" id="yoast-ga-form-select-' . $this->form_namespace . '-' . $id . '">';
348
+ }
349
+ if ( count( $values ) >= 1 ) {
350
+ foreach ( $values as $value ) {
351
+ if ( is_array( $this->get_setting( $name ) ) ) {
352
+ if ( in_array( $value['id'], $this->get_setting( $name ) ) ) {
353
+ $select .= '<option value="' . $value['id'] . '" selected="selected">' . stripslashes( $value['name'] ) . '</option>';
354
+ } else {
355
+ $select .= '<option value="' . $value['id'] . '">' . stripslashes( $value['name'] ) . '</option>';
356
+ }
357
+ } else {
358
+ $select .= '<option value="' . $value['id'] . '" ' . selected( $this->get_setting( $name ), $value['id'], false ) . '>' . stripslashes( $value['name'] ) . '</option>';
359
+ }
360
+ }
361
+ }
362
+ $select .= '</select>';
363
+ $select .= '</div>';
364
+
365
+ // If we get a description, append it to this select field in a new row
366
+ if ( ! is_null( $description ) ) {
367
+ $select .= '<div class="ga-form ga-form-input">';
368
+ $select .= '<label class="ga-form ga-form-select-label ga-form-label-left" id="yoast-ga-form-description-select-' . $this->form_namespace . '-' . $id . '" />&nbsp;</label>';
369
+ $select .= '<span class="ga-form ga-form-description">' . __( $description, 'google-analytics-for-wordpress' ) . '</span>';
370
+ $select .= '</div>';
371
+ }
372
 
373
+ return $select;
 
374
  }
 
 
375
 
376
+ /**
377
+ * Generate a textarea field
378
+ *
379
+ * @param $title
380
+ * @param $name
381
+ * @param null $description
382
+ *
383
+ * @return null|string
384
+ */
385
+ public function textarea( $title, $name, $description = NULL ) {
386
+ $text = NULL;
387
+ $id = $this->form_prefix . '_' . $name;
388
+ $text .= '<div class="ga-form ga-form-input">';
389
+ if ( ! is_null( $title ) ) {
390
+ $text .= '<label class="ga-form ga-form-select-label ga-form-label-left" id="yoast-ga-form-label-select-' . $this->form_namespace . '-' . $id . '" />' . __( $title, 'google-analytics-for-wordpress' ) . ':</label>';
391
+ }
392
+ $text .= '<textarea rows="5" cols="60" name="' . $name . '" id="yoast-ga-form-textarea-' . $this->form_namespace . '-' . $id . '">' . stripslashes( $this->get_setting( $name ) ) . '</textarea>';
393
+ $text .= '</div>';
394
+
395
+ // If we get a description, append it to this select field in a new row
396
+ if ( ! is_null( $description ) ) {
397
+ $text .= '<div class="ga-form ga-form-input">';
398
+ $text .= '<label class="ga-form ga-form-select-label ga-form-label-left" id="yoast-ga-form-description-select-' . $this->form_namespace . '-' . $id . '" />&nbsp;</label>';
399
+ $text .= '<span class="ga-form ga-form-description">' . __( $description, 'google-analytics-for-wordpress' ) . '</span>';
400
+ $text .= '</div>';
401
+ }
402
 
403
+ return $text;
 
 
 
 
 
 
 
404
  }
 
 
405
 
406
+ /**
407
+ * Get the Google Analytics profiles which are in this google account
408
+ * @return array
409
+ * @todo OAuth connection to Google.com?
410
+ */
411
+ public function get_profiles() {
412
+
413
+ // Enqueue the chosen css file
414
+ wp_enqueue_style( 'chosen_css', plugins_url( 'js/chosen.css', GAWP_FILE ) );
415
+
416
+ // Eqneue the chosen js file
417
+ wp_enqueue_script( 'chosen_js', plugins_url( 'js/chosen.jquery.min.js', GAWP_FILE ), array(), false, true );
418
+
419
+ $option_name = 'Yoast_Google_Analytics';
420
+ $options = get_option( $option_name );
421
+ $return = array();
422
+
423
+ if ( ! empty ( $options['ga_token'] ) ) {
424
+ $token = $options['ga_token'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
425
 
426
  $args = array(
427
  'scope' => 'https://www.googleapis.com/auth/analytics.readonly',
428
+ 'xoauth_displayname' => 'Google Analytics for WordPress by Yoast',
429
  );
430
  $access_token = $options['gawp_oauth']['access_token'];
431
  $gdata = new WP_Gdata( $args, $access_token['oauth_token'], $access_token['oauth_token_secret'] );
442
  $options['ga_token'] = $token;
443
  update_option( 'Yoast_Google_Analytics', $options );
444
  }
 
445
 
446
+ $xml_reader = new SimpleXMLElement( $options['ga_api_responses'][$token]['body'] );
 
447
 
448
+ if ( ! empty( $xml_reader->entry ) ) {
449
 
450
+ $ga_accounts = array();
 
 
451
 
 
452
  // Check whether the feed output is the new one, first set, or the old one, second set.
453
+ if ( $xml_reader->link['href'] == 'https://www.googleapis.com/analytics/v2.4/management/accounts/~all/webproperties/~all/profiles' ) {
454
+ foreach ( $xml_reader->entry AS $entry ) {
455
+ $ns = $entry->getNamespaces( true );
456
+ $properties = $entry->children( $ns['dxp'] )->property;
457
+
458
+ if ( isset ( $properties[1]->attributes()->value ) ) {
459
+ $ua = (string) trim( $properties[1]->attributes()->value );
460
+ }
461
+
462
+ if ( isset ( $properties[2]->attributes()->value ) ) {
463
+ $title = (string) trim( $properties[2]->attributes()->value );
 
 
 
 
 
 
 
464
  }
465
+
466
+ if ( ! empty( $ua ) && ! empty( $title ) ) {
467
+ $ga_accounts[] = array(
468
+ 'ua' => $ua,
469
+ 'title' => $title,
470
+ );
471
+ }
472
+
473
  }
474
+ } else {
475
+ if ( $xml_reader->link['href'] == 'https://www.google.com/analytics/feeds/accounts/default' ) {
476
+ foreach ( $xml_reader->entry AS $entry ) {
477
+ $ns = $entry->getNamespaces( true );
478
+ $properties = $entry->children( $ns['dxp'] )->property;
479
+
480
+ if ( isset ( $properties[3]->attributes()->value ) ) {
481
+ $ua = (string) trim( $properties[3]->attributes()->value );
482
+ }
483
+
484
+ if ( isset ( $properties[2]->attributes()->value ) ) {
485
+ $title = (string) trim( $properties[2]->attributes()->value );
486
+ }
487
+
488
+ if ( ! empty( $ua ) && ! empty( $title ) ) {
489
+ $ga_accounts[] = array(
490
+ 'ua' => $ua,
491
+ 'title' => $title,
492
+ );
493
+ }
494
+
495
+ }
496
  }
497
  }
 
498
 
499
+ if ( is_array( $ga_accounts ) ) {
500
+ usort( $ga_accounts, array( $this, 'sort_profiles' ) );
 
 
 
501
  }
502
+
503
+ foreach ( $ga_accounts as $key => $ga_account ) {
504
+ $return[] = array(
505
+ 'id' => $ga_account['ua'],
506
+ 'name' => $ga_account['title'] . ' (' . $ga_account['ua'] . ')',
507
+ );
 
 
 
 
 
 
 
 
 
 
508
  }
 
 
 
 
 
509
  }
 
 
510
  }
511
 
512
+ return $return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
513
  }
514
 
515
+ /**
516
+ * Sorting the array in alphabetic order
517
+ *
518
+ * @param $a
519
+ * @param $b
520
+ *
521
+ * @return int
522
+ */
523
+ public function sort_profiles( $a, $b ) {
524
+ return strcmp( $a["title"], $b["title"] );
 
525
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
 
527
+ /**
528
+ * Checks if there is a callback or reauth to get token from Google Analytics api
529
+ *
530
+ */
531
+ private function connect_with_google_analytics() {
532
+
533
+ $option_name = 'Yoast_Google_Analytics';
534
+
535
+ if ( isset( $_REQUEST['ga_oauth_callback'] ) ) {
536
+ $o = get_option( $option_name );
537
+ if ( isset( $o['gawp_oauth']['oauth_token'] ) && $o['gawp_oauth']['oauth_token'] == $_REQUEST['oauth_token'] ) {
538
+ $gdata = new WP_GData(
539
+ array(
540
+ 'scope' => 'https://www.google.com/analytics/feeds/',
541
+ 'xoauth_displayname' => 'Google Analytics by Yoast'
542
+ ),
543
+ $o['gawp_oauth']['oauth_token'],
544
+ $o['gawp_oauth']['oauth_token_secret']
545
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
546
 
547
+ $o['gawp_oauth']['access_token'] = $gdata->get_access_token( $_REQUEST['oauth_verifier'] );
548
+ unset( $o['gawp_oauth']['oauth_token'] );
549
+ unset( $o['gawp_oauth']['oauth_token_secret'] );
550
+ $o['ga_token'] = $o['gawp_oauth']['access_token']['oauth_token'];
551
+ }
552
+
553
+ update_option( $option_name, $o );
554
 
555
+ wp_redirect( menu_page_url( 'yst_ga_settings', false ) );
556
+ exit;
557
+ }
558
 
559
+ if ( ! empty ( $_GET['reauth'] ) ) {
 
 
 
560
  $gdata = new WP_GData(
561
  array(
562
  'scope' => 'https://www.google.com/analytics/feeds/',
563
+ 'xoauth_displayname' => 'Google Analytics by Yoast'
564
+ )
 
 
565
  );
566
 
567
+ $oauth_callback = add_query_arg( array( 'ga_oauth_callback' => 1 ), menu_page_url( 'yst_ga_settings', false ) );
568
+ $request_token = $gdata->get_request_token( $oauth_callback );
569
+
570
+ $options = get_option( $option_name );
571
+ unset( $options['ga_token'] );
572
+ unset( $options['gawp_oauth']['access_token'] );
573
+ $options['gawp_oauth']['oauth_token'] = $request_token['oauth_token'];
574
+ $options['gawp_oauth']['oauth_token_secret'] = $request_token['oauth_token_secret'];
575
+ update_option( $option_name, $options );
576
+
577
+ wp_redirect( $gdata->get_authorize_url( $request_token ) );
578
+ exit;
579
  }
580
+ }
581
 
582
+ /**
583
+ * Get the user roles of this WordPress blog
584
+ * @return array
585
+ */
586
+ public function get_userroles() {
587
+ global $wp_roles;
588
+
589
+ $all_roles = $wp_roles->roles;
590
+ $roles = array();
591
+ $editable_roles = apply_filters( 'editable_roles', $all_roles );
592
+ foreach ( $editable_roles as $id => $name ) {
593
+ $roles[] = array(
594
+ 'id' => $id,
595
+ 'name' => $name['name'],
596
+ );
597
+ }
598
 
599
+ return $roles;
 
600
  }
601
 
602
+ /**
603
+ * Get types of how we can track downloads
604
+ * @return array
605
+ */
606
+ public function track_download_types() {
607
+ return array(
608
+ 0 => array( 'id' => 'event', 'name' => 'Event' ),
609
+ 1 => array( 'id' => 'pageview', 'name' => 'Pageview' ),
610
+ );
611
+ }
612
+
613
+ /**
614
+ * Get options for the track full url or links setting
615
+ * @return array
616
+ */
617
+ public function get_track_full_url() {
618
+ return array(
619
+ 0 => array( 'id' => 'domain', 'name' => 'Just the domain' ),
620
+ 1 => array( 'id' => 'full_links', 'name' => 'Full links' ),
621
+ );
622
+ }
623
+
624
+ /**
625
+ * Render the admin page head for the GA Plugin
626
+ */
627
+ public function content_head() {
628
+ require( "views/content_head.php" );
629
+ }
630
+
631
+ /**
632
+ * Render the admin page footer with sidebar for the GA Plugin
633
+ */
634
+ public function content_footer() {
635
+ $banners = array();
636
+ $banners[] = array(
637
+ 'url' => 'https://yoast.com/hire-us/website-review/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',
638
+ 'banner' => GAWP_URL . 'img/banner-website-review.png',
639
+ 'title' => 'Get a website review by Yoast'
640
+ );
641
+ $banners[] = array(
642
+ 'url' => 'https://yoast.com/wordpress/plugins/seo-premium/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',
643
+ 'banner' => GAWP_URL . 'img/banner-premium-seo.png',
644
+ 'title' => 'Get WordPress SEO premium'
645
+ );
646
+ $banners[] = array(
647
+ 'url' => 'https://yoast.com/ebook-optimize-wordpress-site/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',
648
+ 'banner' => GAWP_URL . 'img/eBook_261x130.png',
649
+ 'title' => 'Get the Yoast ebook!'
650
+ );
651
+ $banners[] = array(
652
+ 'url' => 'https://yoast.com/wordpress/plugins/local-seo/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',
653
+ 'banner' => GAWP_URL . 'img/banner-local-seo.png',
654
+ 'title' => 'Get WooCommerce integrated in your Analytics'
655
  );
656
 
657
+ shuffle( $banners );
 
658
 
659
+ if ( true == WP_DEBUG ) {
660
+ // Show the debug information if debug is enabled in the wp_config file
661
+ echo '<div id="ga-debug-info" class="postbox"><h3 class="hndle"><span>'.__('Debug information', 'google-analytics-for-wordpress').'</span></h3><div class="inside"><pre>';
662
+ var_dump( $this->options );
663
+ echo '</pre></div></div>';
664
+ }
665
 
666
+ require( "views/content_footer.php" );
 
667
  }
668
 
669
+ }
 
670
 
671
+ global $yoast_ga_admin;
672
+ $yoast_ga_admin = new Yoast_GA_Admin;
673
+ }
admin/class-pointer.php DELETED
@@ -1,129 +0,0 @@
1
- <?php
2
- /**
3
- * @package Admin
4
- */
5
-
6
- /**
7
- * This class handles the pointers for the GA for WP plugin.
8
- */
9
- class GA_Pointer {
10
-
11
- /**
12
- * Class constructor.
13
- */
14
- function __construct() {
15
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) );
16
- }
17
-
18
- /**
19
- * Enqueue styles and scripts needed for the pointers.
20
- */
21
- function enqueue() {
22
- $options = get_option( 'Yoast_Google_Analytics' );
23
- if ( !isset( $options['tracking_popup'] ) && !isset( $_GET['allow_tracking'] ) ) {
24
- wp_enqueue_style( 'wp-pointer' );
25
- wp_enqueue_script( 'jquery-ui' );
26
- wp_enqueue_script( 'wp-pointer' );
27
- wp_enqueue_script( 'utils' );
28
- add_action( 'admin_print_footer_scripts', array( $this, 'tracking_request' ) );
29
- }
30
- }
31
-
32
- /**
33
- * Shows a popup that asks for permission to allow tracking.
34
- */
35
- function tracking_request() {
36
- $id = '#wpadminbar';
37
- $content = '<h3>' . __( 'Help improve Google Analytics for WordPress', 'google-analytics-for-wordpress' ) . '</h3>';
38
- $content .= '<p>' . __( 'You\'ve just installed Google Analytics for WordPress by Yoast. Please helps us improve it by allowing us to gather anonymous usage stats so we know which configurations, plugins and themes to test with.', 'google-analytics-for-wordpress' ) . '</p>';
39
- $opt_arr = array(
40
- 'content' => $content,
41
- 'position' => array( 'edge' => 'top', 'align' => 'center' )
42
- );
43
- $button2 = __( 'Allow tracking', 'google-analytics-for-wordpress' );
44
- $nonce = wp_create_nonce( 'wpga_activate_tracking' );
45
-
46
- $function2 = 'wpga_store_answer("yes","'.$nonce.'");';
47
- $function1 = 'wpga_store_answer("no","'.$nonce.'");';
48
-
49
- $this->print_scripts( $id, $opt_arr, __( 'Do not allow tracking', 'google-analytics-for-wordpress' ), $button2, $function2, $function1 );
50
- }
51
-
52
- /**
53
- * Load a tiny bit of CSS in the head
54
- */
55
- function admin_head() {
56
- ?>
57
- <style type="text/css" media="screen">
58
- #pointer-primary {
59
- margin: 0 5px 0 0;
60
- }
61
- </style>
62
- <?php
63
- }
64
-
65
- /**
66
- * Prints the pointer script
67
- *
68
- * @param string $selector The CSS selector the pointer is attached to.
69
- * @param array $options The options for the pointer.
70
- * @param string $button1 Text for button 1
71
- * @param string|bool $button2 Text for button 2 (or false to not show it, defaults to false)
72
- * @param string $button2_function The JavaScript function to attach to button 2
73
- * @param string $button1_function The JavaScript function to attach to button 1
74
- */
75
- function print_scripts( $selector, $options, $button1, $button2 = false, $button2_function = '', $button1_function = '' ) {
76
- ?>
77
- <script type="text/javascript">
78
- //<![CDATA[
79
- function wpga_store_answer( input, nonce ) {
80
- var wpga_tracking_data = {
81
- action : 'wpga_tracking_data',
82
- allow_tracking : input,
83
- nonce: nonce
84
- }
85
- jQuery.post( ajaxurl, wpga_tracking_data, function( response ) {
86
- jQuery('#wp-pointer-0').remove();
87
- } );
88
- }
89
-
90
- (function ($) {
91
- var gawp_pointer_options = <?php echo json_encode( $options ); ?>, setup;
92
-
93
- gawp_pointer_options = $.extend(gawp_pointer_options, {
94
- buttons:function (event, t) {
95
- button = jQuery('<a id="pointer-close" style="margin-left:5px" class="button-secondary">' + '<?php echo $button1; ?>' + '</a>');
96
- button.bind('click.pointer', function () {
97
- t.element.pointer('close');
98
- });
99
- return button;
100
- },
101
- close:function () {
102
- }
103
- });
104
-
105
- setup = function () {
106
- $('<?php echo $selector; ?>').pointer(gawp_pointer_options).pointer('open');
107
- <?php if ( $button2 ) { ?>
108
- jQuery('#pointer-close').after('<a id="pointer-primary" class="button-primary">' + '<?php echo $button2; ?>' + '</a>');
109
- jQuery('#pointer-primary').click(function () {
110
- <?php echo $button2_function; ?>
111
- });
112
- jQuery('#pointer-close').click(function () {
113
- <?php echo $button1_function; ?>
114
- });
115
- <?php } ?>
116
- };
117
-
118
- if (gawp_pointer_options.position && gawp_pointer_options.position.defer_loading)
119
- $(window).bind('load.wp-pointers', setup);
120
- else
121
- $(document).ready(setup);
122
- })(jQuery);
123
- //]]>
124
- </script>
125
- <?php
126
- }
127
- }
128
-
129
- $ga_pointer = new GA_Pointer;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/index.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ //Nothing to see here
3
+
4
+ header( 'HTTP/1.0 403 Forbidden' );
admin/license-manager/README.md ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Yoast License Manager
2
+ =====================
3
+
4
+ This library will take care of the following.
5
+
6
+ - Managing license related options
7
+ - Setting license key from a constant
8
+ - Obfuscasting (valid) license keys
9
+ - Remote license activation / deactivation
10
+ - Checking for plugin or theme updates
11
+
12
+ ## Usage
13
+
14
+ ### Inside Plugins
15
+
16
+ A sample plugin is included, [have a look at its source](https://github.com/Yoast/License-Manager/blob/master/samples/sample-plugin.php).
17
+
18
+ ### Inside Themes
19
+
20
+ A sample theme `functions.php` file is included, [have a look here](https://github.com/Yoast/License-Manager/blob/master/samples/sample-theme-functions.php).
21
+
admin/license-manager/class-api-request.php ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! class_exists( "Yoast_API_Request", false ) ) {
4
+
5
+ /**
6
+ * Handles requests to the Yoast EDD API
7
+ */
8
+ class Yoast_API_Request {
9
+
10
+ /**
11
+ * @var string Request URL
12
+ */
13
+ private $url = '';
14
+
15
+ /**
16
+ * @var array Request parameters
17
+ */
18
+ private $args = array(
19
+ 'method' => 'GET',
20
+ 'timeout' => 10,
21
+ 'sslverify' => false,
22
+ 'headers' => array(
23
+ 'Accept-Encoding' => '*',
24
+ 'X-Yoast-EDD' => '1'
25
+ )
26
+ );
27
+
28
+ /**
29
+ * @var boolean
30
+ */
31
+ private $success = false;
32
+
33
+ /**
34
+ * @var mixed
35
+ */
36
+ private $response;
37
+
38
+ /**
39
+ * @var string
40
+ */
41
+ private $error_message = '';
42
+
43
+ /**
44
+ * Constructor
45
+ *
46
+ * @param string url
47
+ * @param array $args
48
+ */
49
+ public function __construct( $url, array $args = array() ) {
50
+
51
+ // set api url
52
+ $this->url = $url;
53
+
54
+ // set request args (merge with defaults)
55
+ $this->args = wp_parse_args( $args, $this->args );
56
+
57
+ // fire the request
58
+ $this->success = $this->fire();
59
+ }
60
+
61
+ /**
62
+ * Fires the request, automatically called from constructor
63
+ *
64
+ * @return boolean
65
+ */
66
+ private function fire() {
67
+
68
+ // fire request to shop
69
+ $response = wp_remote_request( $this->url, $this->args );
70
+
71
+ // validate raw response
72
+ if( $this->validate_raw_response( $response ) === false ) {
73
+ return false;
74
+ }
75
+
76
+ // decode the response
77
+ $this->response = json_decode( wp_remote_retrieve_body( $response ) );
78
+
79
+ // response should be an object
80
+ if( ! is_object( $this->response ) ) {
81
+ $this->error_message = 'No JSON object was returned.';
82
+ return false;
83
+ }
84
+
85
+ return true;
86
+ }
87
+
88
+ /**
89
+ * @param object $response
90
+ * @return boolean
91
+ */
92
+ private function validate_raw_response( $response ) {
93
+
94
+ // make sure response came back okay
95
+ if( is_wp_error( $response ) ) {
96
+ $this->error_message = $response->get_error_message();
97
+ return false;
98
+ }
99
+
100
+ // check response code, should be 200
101
+ $response_code = wp_remote_retrieve_response_code( $response );
102
+
103
+ if( false === strstr( $response_code, '200' ) ) {
104
+
105
+ $response_message = wp_remote_retrieve_response_message( $response );
106
+ $this->error_message = "{$response_code} {$response_message}";
107
+
108
+ return false;
109
+ }
110
+
111
+ return true;
112
+ }
113
+
114
+ /**
115
+ * Was a valid response returned?
116
+ *
117
+ * @return boolean
118
+ */
119
+ public function is_valid() {
120
+ return ( $this->success === true );
121
+ }
122
+
123
+ /**
124
+ * @return string
125
+ */
126
+ public function get_error_message() {
127
+ return $this->error_message;
128
+ }
129
+
130
+ /**
131
+ * @return object
132
+ */
133
+ public function get_response() {
134
+ return $this->response;
135
+ }
136
+
137
+ }
138
+
139
+ }
140
+
admin/license-manager/class-license-manager.php ADDED
@@ -0,0 +1,568 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! interface_exists( 'iYoast_License_Manager', false ) ) {
4
+
5
+ interface iYoast_License_Manager {
6
+
7
+ public function specific_hooks();
8
+ public function setup_auto_updater();
9
+
10
+ }
11
+
12
+ }
13
+
14
+
15
+ if( ! class_exists( 'Yoast_License_Manager', false ) ) {
16
+
17
+ /**
18
+ * Class Yoast_License_Manager
19
+ *
20
+ * @todo Maybe create a license class that contains key and option
21
+ * @todo Not sure if Yoast_License_Manager is a good name for this class, it's more managing the product (plugin or theme)
22
+ */
23
+ abstract class Yoast_License_Manager implements iYoast_License_Manager {
24
+
25
+ /**
26
+ * @const VERSION The version number of the License_Manager class
27
+ */
28
+ const VERSION = 1;
29
+
30
+ /**
31
+ * @var Yoast_License The license
32
+ */
33
+ protected $product;
34
+
35
+ /**
36
+ * @var string
37
+ */
38
+ private $license_constant_name = '';
39
+
40
+ /**
41
+ * @var boolean True if license is defined with a constant
42
+ */
43
+ private $license_constant_is_defined = false;
44
+
45
+ /**
46
+ * @var boolean True if remote license activation just failed
47
+ */
48
+ private $remote_license_activation_failed = false;
49
+
50
+ /**
51
+ * @var array Array of license related options
52
+ */
53
+ private $options = array();
54
+
55
+ /**
56
+ * @var string Used to prefix ID's, option names, etc..
57
+ */
58
+ protected $prefix;
59
+
60
+ /**
61
+ * @var bool Boolean indicating whether this plugin is network activated
62
+ */
63
+ protected $is_network_activated = false;
64
+
65
+ /**
66
+ * Constructor
67
+ *
68
+ * @param Yoast_Product $product
69
+ */
70
+ public function __construct( Yoast_Product $product ) {
71
+
72
+ // Set the license
73
+ $this->product = $product;
74
+
75
+ // set prefix
76
+ $this->prefix = sanitize_title_with_dashes( $this->product->get_item_name() . '_', null, 'save' );
77
+
78
+ // maybe set license key from constant
79
+ $this->maybe_set_license_key_from_constant();
80
+ }
81
+
82
+ /**
83
+ * Setup hooks
84
+ *
85
+ */
86
+ public function setup_hooks() {
87
+
88
+ // show admin notice if license is not active
89
+ add_action( 'admin_notices', array( $this, 'display_admin_notices' ) );
90
+
91
+ // catch POST requests from license form
92
+ add_action( 'admin_init', array( $this, 'catch_post_request') );
93
+
94
+ // setup item type (plugin|theme) specific hooks
95
+ $this->specific_hooks();
96
+
97
+ // setup the auto updater
98
+ $this->setup_auto_updater();
99
+
100
+ }
101
+
102
+ /**
103
+ * Display license specific admin notices, namely:
104
+ *
105
+ * - License for the product isn't activated
106
+ * - External requests are blocked through WP_HTTP_BLOCK_EXTERNAL
107
+ */
108
+ public function display_admin_notices() {
109
+
110
+ if ( ! current_user_can( 'manage_options' ) ) {
111
+ return;
112
+ }
113
+
114
+ // show notice if license is invalid
115
+ if( ! $this->license_is_valid() ) {
116
+ if( $this->get_license_key() == '' ) {
117
+ $message = '<b>Warning!</b> You didn\'t set your %s license key yet, which means you\'re missing out on updates and support! <a href="%s">Enter your license key</a> or <a href="%s" target="_blank">get a license here</a>.';
118
+ } else {
119
+ $message = '<b>Warning!</b> Your %s license is inactive which means you\'re missing out on updates and support! <a href="%s">Activate your license</a> or <a href="%s" target="_blank">get a license here</a>.';
120
+ }
121
+ ?>
122
+ <div class="error">
123
+ <p><?php printf( __( $message, $this->product->get_text_domain() ), $this->product->get_item_name(), $this->product->get_license_page_url(), $this->product->get_tracking_url( 'activate-license-notice' ) ); ?></p>
124
+ </div>
125
+ <?php
126
+ }
127
+
128
+ // show notice if external requests are blocked through the WP_HTTP_BLOCK_EXTERNAL constant
129
+ if( defined( "WP_HTTP_BLOCK_EXTERNAL" ) && WP_HTTP_BLOCK_EXTERNAL === true ) {
130
+
131
+ // check if our API endpoint is in the allowed hosts
132
+ $host = parse_url( $this->product->get_api_url(), PHP_URL_HOST );
133
+
134
+ if( ! defined( "WP_ACCESSIBLE_HOSTS" ) || stristr( WP_ACCESSIBLE_HOSTS, $host ) === false ) {
135
+ ?>
136
+ <div class="error">
137
+ <p><?php printf( __( '<b>Warning!</b> You\'re blocking external requests which means you won\'t be able to get %s updates. Please add %s to %s.', $this->product->get_text_domain() ), $this->product->get_item_name(), '<strong>' . $host . '</strong>', '<code>WP_ACCESSIBLE_HOSTS</code>'); ?></p>
138
+ </div>
139
+ <?php
140
+ }
141
+
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Set a notice to display in the admin area
147
+ *
148
+ * @param string $type error|updated
149
+ * @param string $message The message to display
150
+ */
151
+ protected function set_notice( $message, $success = true ) {
152
+ $css_class = ( $success ) ? 'updated' : 'error';
153
+ add_settings_error( $this->prefix . 'license', 'license-notice', $message, $css_class );
154
+ }
155
+
156
+ /**
157
+ * Remotely activate License
158
+ * @return boolean True if the license is now activated, false if not
159
+ */
160
+ public function activate_license() {
161
+
162
+ $result = $this->call_license_api( 'activate' );
163
+
164
+
165
+ if( $result ) {
166
+
167
+ // story expiry date
168
+ if( isset( $result->expires ) ) {
169
+ $this->set_license_expiry_date( $result->expires );
170
+ $expiry_date = strtotime( $result->expires );
171
+ } else {
172
+ $expiry_date = false;
173
+ }
174
+
175
+ // show success notice if license is valid
176
+ if($result->license === 'valid') {
177
+
178
+ // show a custom notice if users have an unlimited license
179
+ if( $result->license_limit == 0 ) {
180
+ $message = sprintf( __( "Your %s license has been activated. You have an unlimited license. ", $this->product->get_text_domain() ), $this->product->get_item_name() );
181
+ } else {
182
+ $message = sprintf( __( "Your %s license has been activated. You have used %d/%d activations. ", $this->product->get_text_domain() ), $this->product->get_item_name(), $result->site_count, $result->license_limit );
183
+ }
184
+
185
+ // add upgrade notice if user has less than 3 activations left
186
+ if( $result->license_limit > 0 && ( $result->license_limit - $result->site_count ) <= 3 ) {
187
+ $message .= sprintf( __( '<a href="%s">Did you know you can upgrade your license?</a>', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-nearing-limit-notice' ) );
188
+ // add extend notice if license is expiring in less than 1 month
189
+ } elseif( $expiry_date !== false && $expiry_date < strtotime( "+1 month" ) ) {
190
+ $days_left = round( ( $expiry_date - strtotime( "now" ) ) / 86400 );
191
+ $message .= sprintf( __( '<a href="%s">Your license is expiring in %d days, would you like to extend it?</a>', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-expiring-notice' ), $days_left );
192
+ }
193
+
194
+ $this->set_notice( $message, true );
195
+
196
+ } else {
197
+
198
+ if( isset($result->error) && $result->error === 'no_activations_left' ) {
199
+ // show notice if user is at their activation limit
200
+ $this->set_notice( sprintf( __('You\'ve reached your activation limit. You must <a href="%s">upgrade your license</a> to use it on this site.', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-at-limit-notice' ) ), false );
201
+ } elseif( isset($result->error) && $result->error == "expired" ) {
202
+ // show notice if the license is expired
203
+ $this->set_notice( sprintf( __('Your license has expired. You must <a href="%s">extend your license</a> in order to use it again.', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-expired-notice' ) ), false );
204
+ } else {
205
+ // show a general notice if it's any other error
206
+ $this->set_notice( __( "Failed to activate your license, your license key seems to be invalid.", $this->product->get_text_domain() ), false );
207
+ }
208
+
209
+ $this->remote_license_activation_failed = true;
210
+ }
211
+
212
+ $this->set_license_status( $result->license );
213
+ }
214
+
215
+ return ( $this->license_is_valid() );
216
+ }
217
+
218
+ /**
219
+ * Remotely deactivate License
220
+ * @return boolean True if the license is now deactivated, false if not
221
+ */
222
+ public function deactivate_license () {
223
+
224
+ $result = $this->call_license_api( 'deactivate' );
225
+
226
+ if( $result ) {
227
+
228
+ // show notice if license is deactivated
229
+ if( $result->license === 'deactivated' ) {
230
+ $this->set_notice( sprintf( __( "Your %s license has been deactivated.", $this->product->get_text_domain() ), $this->product->get_item_name() ) );
231
+ } else {
232
+ $this->set_notice( sprintf( __( "Failed to deactivate your %s license.", $this->product->get_text_domain() ), $this->product->get_item_name() ), false );
233
+ }
234
+
235
+ $this->set_license_status( $result->license );
236
+ }
237
+
238
+ return ( $this->get_license_status() === 'deactivated' );
239
+ }
240
+
241
+ /**
242
+ * @param string $action activate|deactivate
243
+ * @return mixed
244
+ */
245
+ protected function call_license_api( $action ) {
246
+
247
+ // don't make a request if license key is empty
248
+ if( $this->get_license_key() === '' ) {
249
+ return false;
250
+ }
251
+
252
+ // data to send in our API request
253
+ $api_params = array(
254
+ 'edd_action' => $action . '_license',
255
+ 'license' => $this->get_license_key(),
256
+ 'item_name' => urlencode( trim( $this->product->get_item_name() ) ),
257
+ 'url' => get_option( 'home' ) // grab the URL straight from the option to prevent filters from breaking it.
258
+ );
259
+
260
+ // create api request url
261
+ $url = add_query_arg( $api_params, $this->product->get_api_url() );
262
+
263
+ require_once dirname( __FILE__ ) . '/class-api-request.php';
264
+ $request = new Yoast_API_Request( $url );
265
+
266
+ if( $request->is_valid() !== true ) {
267
+ $this->set_notice( sprintf( __( "Request error: \"%s\" (%scommon license notices%s)", $this->product->get_text_domain() ), $request->get_error_message(), '<a href="http://kb.yoast.com/article/13-license-activation-notices">', '</a>' ), false );
268
+ }
269
+
270
+ // get response
271
+ $response = $request->get_response();
272
+
273
+ // update license status
274
+ $license_data = $response;
275
+
276
+ return $license_data;
277
+ }
278
+
279
+
280
+
281
+ /**
282
+ * Set the license status
283
+ *
284
+ * @param string $license_status
285
+ */
286
+ public function set_license_status( $license_status ) {
287
+ $this->set_option( 'status', $license_status );
288
+ }
289
+
290
+ /**
291
+ * Get the license status
292
+ *
293
+ * @return string $license_status;
294
+ */
295
+ public function get_license_status() {
296
+ $license_status = $this->get_option( 'status' );
297
+ return trim( $license_status );
298
+ }
299
+
300
+ /**
301
+ * Set the license key
302
+ *
303
+ * @param string $license_key
304
+ */
305
+ public function set_license_key( $license_key ) {
306
+ $this->set_option( 'key', $license_key );
307
+ }
308
+
309
+ /**
310
+ * Gets the license key from constant or option
311
+ *
312
+ * @return string $license_key
313
+ */
314
+ public function get_license_key() {
315
+ $license_key = $this->get_option( 'key' );
316
+ return trim( $license_key );
317
+ }
318
+
319
+ /**
320
+ * Gets the license expiry date
321
+ *
322
+ * @return string
323
+ */
324
+ public function get_license_expiry_date() {
325
+ return $this->get_option( 'expiry_date');
326
+ }
327
+
328
+ /**
329
+ * Stores the license expiry date
330
+ */
331
+ public function set_license_expiry_date( $expiry_date ) {
332
+ $this->set_option( 'expiry_date', $expiry_date );
333
+ }
334
+
335
+ /**
336
+ * Checks whether the license status is active
337
+ *
338
+ * @return boolean True if license is active
339
+ */
340
+ public function license_is_valid() {
341
+ return ( $this->get_license_status() === 'valid' );
342
+ }
343
+
344
+ /**
345
+ * Get all license related options
346
+ *
347
+ * @return array Array of license options
348
+ */
349
+ protected function get_options() {
350
+
351
+ // create option name
352
+ $option_name = $this->prefix . 'license';
353
+
354
+ // get array of options from db
355
+ if( $this->is_network_activated ) {
356
+ $options = get_site_option( $option_name, array( ) );
357
+ } else {
358
+ $options = get_option( $option_name, array( ) );
359
+ }
360
+
361
+ // setup array of defaults
362
+ $defaults = array(
363
+ 'key' => '',
364
+ 'status' => '',
365
+ 'expiry_date' => ''
366
+ );
367
+
368
+ // merge options with defaults
369
+ $this->options = wp_parse_args( $options, $defaults );
370
+
371
+ return $this->options;
372
+ }
373
+
374
+ /**
375
+ * Set license related options
376
+ *
377
+ * @param array $options Array of new license options
378
+ */
379
+ protected function set_options( array $options ) {
380
+ // create option name
381
+ $option_name = $this->prefix . 'license';
382
+
383
+ // update db
384
+ if( $this->is_network_activated ) {
385
+ update_site_option( $option_name, $options );
386
+ } else {
387
+ update_option( $option_name, $options );
388
+ }
389
+
390
+ }
391
+
392
+ /**
393
+ * Gets a license related option
394
+ *
395
+ * @param string $name The option name
396
+ * @return mixed The option value
397
+ */
398
+ protected function get_option( $name ) {
399
+ $options = $this->get_options();
400
+ return $options[ $name ];
401
+ }
402
+
403
+ /**
404
+ * Set a license related option
405
+ *
406
+ * @param string $name The option name
407
+ * @param mixed $value The option value
408
+ */
409
+ protected function set_option( $name, $value ) {
410
+ // get options
411
+ $options = $this->get_options();
412
+
413
+ // update option
414
+ $options[ $name ] = $value;
415
+
416
+ // save options
417
+ $this->set_options( $options );
418
+ }
419
+
420
+ public function show_license_form_heading() {
421
+ ?>
422
+ <h3>
423
+ <?php printf( __( "%s: License Settings", $this->product->get_text_domain() ), $this->product->get_item_name() ); ?>&nbsp; &nbsp;
424
+ </h3>
425
+ <?php
426
+ }
427
+
428
+ /**
429
+ * Show a form where users can enter their license key
430
+ *
431
+ * @param boolean $embedded Boolean indicating whether this form is embedded in another form?
432
+ */
433
+ public function show_license_form( $embedded = true ) {
434
+
435
+ $key_name = $this->prefix . 'license_key';
436
+ $nonce_name = $this->prefix . 'license_nonce';
437
+ $action_name = $this->prefix . 'license_action';
438
+
439
+
440
+ $visible_license_key = $this->get_license_key();
441
+
442
+ // obfuscate license key
443
+ $obfuscate = ( strlen( $this->get_license_key() ) > 5 && ( $this->license_is_valid() || ! $this->remote_license_activation_failed ) );
444
+
445
+ if($obfuscate) {
446
+ $visible_license_key = str_repeat('*', strlen( $this->get_license_key() ) - 4) . substr( $this->get_license_key(), -4 );
447
+ }
448
+
449
+ // make license key readonly when license key is valid or license is defined with a constant
450
+ $readonly = ( $this->license_is_valid() || $this->license_constant_is_defined );
451
+
452
+ require dirname( __FILE__ ) . '/views/form.php';
453
+
454
+ // enqueue script in the footer
455
+ add_action( 'admin_footer', array( $this, 'output_script'), 99 );
456
+ }
457
+
458
+ /**
459
+ * Check if the license form has been submitted
460
+ */
461
+ public function catch_post_request() {
462
+
463
+ $name = $this->prefix . 'license_key';
464
+
465
+ // check if license key was posted and not empty
466
+ if( ! isset( $_POST[$name] ) ) {
467
+ return;
468
+ }
469
+
470
+ // run a quick security check
471
+ $nonce_name = $this->prefix . 'license_nonce';
472
+
473
+ if ( ! check_admin_referer( $nonce_name, $nonce_name ) ) {
474
+ return;
475
+ }
476
+
477
+ // @TODO: check for user cap?
478
+
479
+ // get key from posted value
480
+ $license_key = $_POST[$name];
481
+
482
+ // check if license key doesn't accidentally contain asterisks
483
+ if( strstr($license_key, '*') === false ) {
484
+
485
+ // sanitize key
486
+ $license_key = trim( sanitize_key( $_POST[$name] ) );
487
+
488
+ // save license key
489
+ $this->set_license_key( $license_key );
490
+ }
491
+
492
+ // does user have an activated valid license
493
+ if( ! $this->license_is_valid() ) {
494
+
495
+ // try to auto-activate license
496
+ return $this->activate_license();
497
+
498
+ }
499
+
500
+ $action_name = $this->prefix . 'license_action';
501
+
502
+ // was one of the action buttons clicked?
503
+ if( isset( $_POST[ $action_name ] ) ) {
504
+
505
+ $action = trim( $_POST[ $action_name ] );
506
+
507
+ switch($action) {
508
+
509
+ case 'activate':
510
+ return $this->activate_license();
511
+ break;
512
+
513
+ case 'deactivate':
514
+ return $this->deactivate_license();
515
+ break;
516
+ }
517
+
518
+ }
519
+
520
+ }
521
+
522
+ /**
523
+ * Output the script containing the YoastLicenseManager JS Object
524
+ *
525
+ * This takes care of disabling the 'activate' and 'deactivate' buttons
526
+ */
527
+ public function output_script() {
528
+ require_once dirname( __FILE__ ) . '/views/script.php';
529
+ }
530
+
531
+ /**
532
+ * Set the constant used to define the license
533
+ *
534
+ * @param string $license_constant_name The license constant name
535
+ */
536
+ public function set_license_constant_name( $license_constant_name ) {
537
+ $this->license_constant_name = trim( $license_constant_name );
538
+ $this->maybe_set_license_key_from_constant();
539
+ }
540
+
541
+ /**
542
+ * Maybe set license key from a defined constant
543
+ */
544
+ private function maybe_set_license_key_from_constant( ) {
545
+
546
+ if( empty( $this->license_constant_name ) ) {
547
+ // generate license constant name
548
+ $this->set_license_constant_name( strtoupper( str_replace( array(' ', '-' ), '', sanitize_key( $this->product->get_item_name() ) ) ) . '_LICENSE');
549
+ }
550
+
551
+ // set license key from constant
552
+ if( defined( $this->license_constant_name ) ) {
553
+
554
+ $license_constant_value = constant( $this->license_constant_name );
555
+
556
+ // update license key value with value of constant
557
+ if( $this->get_license_key() !== $license_constant_value ) {
558
+ $this->set_license_key( $license_constant_value );
559
+ }
560
+
561
+ $this->license_constant_is_defined = true;
562
+ }
563
+ }
564
+
565
+
566
+ }
567
+
568
+ }
admin/license-manager/class-plugin-license-manager.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( class_exists( 'Yoast_License_Manager' ) && ! class_exists( "Yoast_Plugin_License_Manager", false ) ) {
4
+
5
+ class Yoast_Plugin_License_Manager extends Yoast_License_Manager {
6
+
7
+ /**
8
+ * Constructor
9
+ *
10
+ * @param Yoast_Product $product
11
+ */
12
+ public function __construct( Yoast_Product $product ) {
13
+
14
+ parent::__construct( $product );
15
+
16
+ // Check if plugin is network activated. We should use site(wide) options in that case.
17
+ if( is_admin() && is_multisite() ) {
18
+
19
+ if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
20
+ require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
21
+ }
22
+
23
+ $this->is_network_activated = is_plugin_active_for_network( $product->get_slug() );
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Setup auto updater for plugins
29
+ */
30
+ public function setup_auto_updater() {
31
+ if ( $this->license_is_valid() ) {
32
+ // setup auto updater
33
+ require_once( dirname( __FILE__ ) . '/class-update-manager.php' );
34
+ require_once( dirname( __FILE__ ) . '/class-plugin-update-manager.php' );
35
+ new Yoast_Plugin_Update_Manager( $this->product, $this );
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Setup hooks
41
+ */
42
+ public function specific_hooks() {
43
+
44
+ // deactivate the license remotely on plugin deactivation
45
+ register_deactivation_hook( $this->product->get_slug(), array( $this, 'deactivate_license' ) );
46
+ }
47
+
48
+ /**
49
+ * Show a form where users can enter their license key
50
+ * Takes Multisites into account
51
+ *
52
+ * @param bool $embedded
53
+ * @return null
54
+ */
55
+ public function show_license_form( $embedded = true ) {
56
+
57
+ // For non-multisites, always show the license form
58
+ if( ! is_multisite() ) {
59
+ parent::show_license_form( $embedded );
60
+ return;
61
+ }
62
+
63
+ // Plugin is network activated
64
+ if( $this->is_network_activated ) {
65
+
66
+ // We're on the network admin
67
+ if( is_network_admin() ) {
68
+ parent::show_license_form( $embedded );
69
+ } else {
70
+ // We're not in the network admin area, show a notice
71
+ parent::show_license_form_heading();
72
+ if ( is_super_admin() ) {
73
+ echo "<p>" . sprintf( __( '%s is network activated, you can manage your license in the <a href="%s">network admin license page</a>.', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->product->get_license_page_url() ) . "</p>";
74
+ } else {
75
+ echo "<p>" . sprintf( __( '%s is network activated, please contact your site administrator to manage the license.', $this->product->get_text_domain() ), $this->product->get_item_name() ) . "</p>";
76
+ }
77
+
78
+ }
79
+
80
+ } else {
81
+
82
+ if( false == is_network_admin() ) {
83
+ parent::show_license_form( $embedded );
84
+ }
85
+
86
+ }
87
+ }
88
+ }
89
+ }
90
+
admin/license-manager/class-plugin-update-manager.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ //set_site_transient( 'update_plugins', null );
4
+
5
+ if( class_exists( 'Yoast_Update_Manager' ) && ! class_exists( "Yoast_Plugin_Update_Manager", false ) ) {
6
+
7
+ class Yoast_Plugin_Update_Manager extends Yoast_Update_Manager {
8
+
9
+ /**
10
+ * Constructor
11
+ *
12
+ * @param string $api_url
13
+ * @param string $item_name
14
+ * @param string $license_key
15
+ * @param string $slug The path to the main plugin file, relative to plugins dir
16
+ * @param string $version
17
+ * @param string $author (optional)
18
+ * @param string $text_domain
19
+ */
20
+ public function __construct( Yoast_Product $product, $license_key ) {
21
+ parent::__construct( $product, $license_key );
22
+
23
+ // setup hooks
24
+ $this->setup_hooks();
25
+
26
+ }
27
+
28
+ /**
29
+ * Setup hooks
30
+ */
31
+ private function setup_hooks() {
32
+
33
+ // check for updates
34
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'set_updates_available_data' ) );
35
+
36
+ // get correct plugin information (when viewing details)
37
+ add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
38
+ }
39
+
40
+ /**
41
+ * Check for updates and if so, add to "updates available" data
42
+ *
43
+ * @param object $data
44
+ * @return object $data
45
+ */
46
+ public function set_updates_available_data( $data ) {
47
+
48
+ if ( empty( $data ) ) {
49
+ return $data;
50
+ }
51
+
52
+ // send of API request to check for updates
53
+ $remote_data = $this->get_remote_data();
54
+
55
+ // did we get a response?
56
+ if( $remote_data === false ) {
57
+ return $data;
58
+ }
59
+
60
+ // compare local version with remote version
61
+ if ( version_compare( $this->product->get_version(), $remote_data->new_version, '<' ) ) {
62
+
63
+ // remote version is newer, add to data
64
+ $data->response[ $this->product->get_slug() ] = $remote_data;
65
+
66
+ }
67
+
68
+ return $data;
69
+ }
70
+
71
+ /**
72
+ * Gets new plugin version details (view version x.x.x details)
73
+ *
74
+ * @uses api_request()
75
+ *
76
+ * @param object $data
77
+ * @param string $action
78
+ * @param object $args (optional)
79
+ *
80
+ * @return object $data
81
+ */
82
+ public function plugins_api_filter( $data, $action = '', $args = null ) {
83
+
84
+ // only do something if we're checking for our plugin
85
+ if ( $action !== 'plugin_information' || ! isset( $args->slug ) || $args->slug !== $this->product->get_slug() ) {
86
+ return $data;
87
+ }
88
+
89
+ $api_response = $this->get_remote_data();
90
+
91
+ // did we get a response?
92
+ if ( $api_response === false ) {
93
+ return $data;
94
+ }
95
+
96
+ // return api response
97
+ return $api_response;
98
+ }
99
+
100
+ }
101
+
102
+ }
admin/license-manager/class-product.php ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! class_exists( "Yoast_Product", false ) ) {
4
+
5
+ /**
6
+ * Class Yoast_Product
7
+ *
8
+ * @todo create a license class and store an object of it in this class
9
+ */
10
+ class Yoast_Product {
11
+
12
+ /**
13
+ * @var string The URL of the shop running the EDD API.
14
+ */
15
+ protected $api_url;
16
+
17
+ /**
18
+ * @var string The item name in the EDD shop.
19
+ */
20
+ protected $item_name;
21
+
22
+ /**
23
+ * @var string The theme slug or plugin file
24
+ */
25
+ protected $slug;
26
+
27
+ /**
28
+ * @var string The version number of the item
29
+ */
30
+ protected $version;
31
+
32
+ /**
33
+ * @var string The absolute url on which users can purchase a license
34
+ */
35
+ protected $item_url;
36
+
37
+ /**
38
+ * @var string Absolute admin URL on which users can enter their license key.
39
+ */
40
+ protected $license_page_url;
41
+
42
+ /**
43
+ * @var string The text domain used for translating strings
44
+ */
45
+ protected $text_domain;
46
+
47
+ /**
48
+ * @var string The item author
49
+ */
50
+ protected $author;
51
+
52
+ public function __construct( $api_url, $item_name, $slug, $version, $item_url = '', $license_page_url = '#', $text_domain = 'yoast', $author = 'Yoast' ) {
53
+ $this->api_url = $api_url;
54
+ $this->item_name = $item_name;
55
+ $this->slug = $slug;
56
+ $this->version = $version;
57
+ $this->item_url = $item_url;
58
+ $this->license_page_url = admin_url( $license_page_url );
59
+ $this->text_domain = $text_domain;
60
+ $this->author = $author;
61
+
62
+ // Fix possible empty item url
63
+ if ( $this->item_url === '' ) {
64
+ $this->item_url = $this->api_url;
65
+ }
66
+
67
+ if( is_admin() && is_multisite() ) {
68
+
69
+ if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
70
+ require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
71
+ }
72
+
73
+ if( is_plugin_active_for_network( $slug ) ) {
74
+ $this->license_page_url = network_admin_url( $license_page_url );
75
+ }
76
+ }
77
+ }
78
+
79
+
80
+ /**
81
+ * @param string $api_url
82
+ */
83
+ public function set_api_url( $api_url ) {
84
+ $this->api_url = $api_url;
85
+ }
86
+
87
+ /**
88
+ * @return string
89
+ */
90
+ public function get_api_url() {
91
+ return $this->api_url;
92
+ }
93
+
94
+ /**
95
+ * @param string $author
96
+ */
97
+ public function set_author( $author ) {
98
+ $this->author = $author;
99
+ }
100
+
101
+ /**
102
+ * @return string
103
+ */
104
+ public function get_author() {
105
+ return $this->author;
106
+ }
107
+
108
+ /**
109
+ * @param string $item_name
110
+ */
111
+ public function set_item_name( $item_name ) {
112
+ $this->item_name = $item_name;
113
+ }
114
+
115
+ /**
116
+ * @return string
117
+ */
118
+ public function get_item_name() {
119
+ return $this->item_name;
120
+ }
121
+
122
+ /**
123
+ * @param string $item_url
124
+ */
125
+ public function set_item_url( $item_url ) {
126
+ $this->item_url = $item_url;
127
+ }
128
+
129
+ /**
130
+ * @return string
131
+ */
132
+ public function get_item_url() {
133
+ return $this->item_url;
134
+ }
135
+
136
+ /**
137
+ * @param string $license_page_url
138
+ */
139
+ public function set_license_page_url( $license_page_url ) {
140
+ $this->license_page_url = admin_page( $license_page_url );
141
+ }
142
+
143
+ /**
144
+ * @return string
145
+ */
146
+ public function get_license_page_url() {
147
+ return $this->license_page_url;
148
+ }
149
+
150
+ /**
151
+ * @param string $slug
152
+ */
153
+ public function set_slug( $slug ) {
154
+ $this->slug = $slug;
155
+ }
156
+
157
+ /**
158
+ * @return string
159
+ */
160
+ public function get_slug() {
161
+ return $this->slug;
162
+ }
163
+
164
+ /**
165
+ * Returns the dirname of the slug and limits it to 15 chars
166
+ *
167
+ * @return string
168
+ */
169
+ public function get_transient_prefix() {
170
+ return substr( dirname( $this->slug ), 0, 15 );
171
+ }
172
+
173
+ /**
174
+ * @param string $text_domain
175
+ */
176
+ public function set_text_domain( $text_domain ) {
177
+ $this->text_domain = $text_domain;
178
+ }
179
+
180
+ /**
181
+ * @return string
182
+ */
183
+ public function get_text_domain() {
184
+ return $this->text_domain;
185
+ }
186
+
187
+ /**
188
+ * @param string $version
189
+ */
190
+ public function set_version( $version ) {
191
+ $this->version = $version;
192
+ }
193
+
194
+ /**
195
+ * @return string
196
+ */
197
+ public function get_version() {
198
+ return $this->version;
199
+ }
200
+
201
+ /**
202
+ * Gets a Google Analytics Campaign url for this product
203
+ *
204
+ * @param string $link_identifier
205
+ * @return string The full URL
206
+ */
207
+ public function get_tracking_url( $link_identifier = '' ) {
208
+
209
+ $tracking_vars = array(
210
+ 'utm_campaign' => $this->get_item_name() . ' licensing',
211
+ 'utm_medium' => 'link',
212
+ 'utm_source' => $this->get_item_name(),
213
+ 'utm_content' => $link_identifier
214
+ );
215
+
216
+ // url encode tracking vars
217
+ $tracking_vars = urlencode_deep( $tracking_vars );
218
+
219
+ $query_string = build_query( $tracking_vars );
220
+
221
+
222
+ return $this->get_item_url() . '#' . $query_string;
223
+ }
224
+
225
+ }
226
+
227
+ }
228
+
admin/license-manager/class-theme-license-manager.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( class_exists( 'Yoast_License_Manager' ) && ! class_exists( "Yoast_Theme_License_Manager", false ) ) {
4
+
5
+ class Yoast_Theme_License_Manager extends Yoast_License_Manager {
6
+
7
+ /**
8
+ * Setup auto updater for themes
9
+ */
10
+ public function setup_auto_updater() {
11
+ if ( $this->license_is_valid() ) {
12
+ // setup auto updater
13
+ require_once dirname( __FILE__ ) . '/class-update-manager.php';
14
+ require_once dirname( __FILE__ ) . '/class-theme-update-manager.php'; // @TODO: Autoload?
15
+ new Yoast_Theme_Update_Manager( $this->product, $this );
16
+ }
17
+ }
18
+
19
+ /**
20
+ * Setup hooks
21
+ */
22
+ public function specific_hooks() {
23
+ // remotely deactivate license upon switching away from this theme
24
+ add_action( 'switch_theme', array( $this, 'deactivate_license' ) );
25
+
26
+ // Add the license menu
27
+ add_action( 'admin_menu', array( $this, 'add_license_menu' ) );
28
+ }
29
+
30
+ /**
31
+ * Add license page and add it to Themes menu
32
+ */
33
+ public function add_license_menu() {
34
+ $theme_page = add_theme_page( sprintf( __( '%s License', $this->product->get_text_domain() ), $this->product->get_item_name() ), __( 'Theme License', $this->product->get_text_domain() ), 'manage_options', 'theme-license', array( $this, 'show_license_page' ) );
35
+ }
36
+
37
+ /**
38
+ * Shows license page
39
+ */
40
+ public function show_license_page() {
41
+ ?>
42
+ <div class="wrap">
43
+ <?php settings_errors(); ?>
44
+
45
+ <?php $this->show_license_form( false ); ?>
46
+ </div>
47
+ <?php
48
+ }
49
+
50
+
51
+ }
52
+
53
+ }
admin/license-manager/class-theme-update-manager.php ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( class_exists( 'Yoast_Update_Manager' ) && ! class_exists( "Yoast_Theme_Update_Manager", false ) ) {
4
+
5
+ class Yoast_Theme_Update_Manager extends Yoast_Update_Manager {
6
+
7
+ /**
8
+ * Constructor
9
+ *
10
+ * @param string $api_url
11
+ * @param string $item_name
12
+ * @param string $license_key
13
+ * @param string $slug
14
+ * @param string $theme_version
15
+ * @param string $author (optional)
16
+ */
17
+ public function __construct( Yoast_Product $product, $license_key ) {
18
+
19
+ parent::__construct( $product, $license_key );
20
+
21
+ // setup hooks
22
+ $this->setup_hooks();
23
+ }
24
+
25
+ /**
26
+ * Get the current theme version
27
+ *
28
+ * @return string The version number
29
+ */
30
+ private function get_theme_version() {
31
+
32
+ // if version was not set, get it from the Theme stylesheet
33
+ if( $this->product->get_version() === '' ) {
34
+ $theme = wp_get_theme( $this->product->get_slug() );
35
+ return $theme->get( 'Version' );
36
+ }
37
+
38
+ return $this->product->get_version();
39
+ }
40
+
41
+ /**
42
+ * Setup hooks
43
+ */
44
+ private function setup_hooks() {
45
+ add_filter( 'site_transient_update_themes', array( $this, 'set_theme_update_transient' ) );
46
+ add_action( 'load-themes.php', array( $this, 'load_themes_screen' ) );
47
+ }
48
+
49
+ /**
50
+ * Set "updates available" transient
51
+ */
52
+ public function set_theme_update_transient( $value ) {
53
+
54
+ $update_data = $this->get_update_data();
55
+
56
+ if( $update_data === false ) {
57
+ return $value;
58
+ }
59
+
60
+ // add update data to "updates available" array. convert object to array.
61
+ $value->response[ $this->product->get_slug() ] = (array) $update_data;
62
+
63
+ return $value;
64
+ }
65
+
66
+ /**
67
+ * Add hooks and scripts to the Appearance > Themes screen
68
+ */
69
+ public function load_themes_screen() {
70
+
71
+ $update_data = $this->get_update_data();
72
+
73
+ // only do if an update is available
74
+ if( $update_data === false ) {
75
+ return;
76
+ }
77
+
78
+ add_thickbox();
79
+ add_action( 'admin_notices', array( $this, 'show_update_details' ) );
80
+ }
81
+
82
+ /**
83
+ * Show update link.
84
+ * Opens Thickbox with Changelog.
85
+ */
86
+ public function show_update_details() {
87
+
88
+ $update_data = $this->get_update_data();
89
+
90
+ // only show if an update is available
91
+ if( $update_data === false ) {
92
+ return;
93
+ }
94
+
95
+ $update_url = wp_nonce_url( 'update.php?action=upgrade-theme&amp;theme=' . urlencode( $this->product->get_slug() ), 'upgrade-theme_' . $this->product->get_slug() );
96
+ $update_onclick = ' onclick="if ( confirm(\'' . esc_js( __( "Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update." ) ) . '\') ) {return true;}return false;"';
97
+ ?>
98
+ <div id="update-nag">
99
+ <?php
100
+ printf(
101
+ __( '<strong>%s version %s</strong> is available. <a href="%s" class="thickbox" title="%s">Check out what\'s new</a> or <a href="%s" %s>update now</a>.' ),
102
+ $this->product->get_item_name(),
103
+ $update_data->new_version,
104
+ '#TB_inline?width=640&amp;inlineId=' . $this->product->get_slug() . '_changelog',
105
+ $this->get_item_name(),
106
+ $update_url,
107
+ $update_onclick
108
+ );
109
+ ?>
110
+ </div>
111
+ <div id="<?php echo $this->product->get_slug(); ?>_changelog" style="display: none;">
112
+ <?php echo wpautop( $update_data->sections['changelog'] ); ?>
113
+ </div>
114
+ <?php
115
+ }
116
+
117
+
118
+ /**
119
+ * Get update data
120
+ *
121
+ * This gets the update data from a transient (12 hours), if set.
122
+ * If not, it will make a remote request and get the update data.
123
+ *
124
+ * @return object $update_data Object containing the update data
125
+ */
126
+ public function get_update_data() {
127
+
128
+ $api_response = $this->get_remote_data();
129
+
130
+ if( false === $api_response ) {
131
+ return false;
132
+ }
133
+
134
+ $update_data = $api_response;
135
+
136
+ // check if a new version is available.
137
+ if ( version_compare( $this->get_theme_version(), $update_data->new_version, '>=' ) ) {
138
+ return false;
139
+ }
140
+
141
+
142
+ // an update is available
143
+ return $update_data;
144
+ }
145
+
146
+
147
+ }
148
+
149
+ }
admin/license-manager/class-update-manager.php ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! class_exists( "Yoast_Update_Manager", false ) ) {
4
+
5
+ class Yoast_Update_Manager {
6
+
7
+ /**
8
+ * @var Yoast_Product
9
+ */
10
+ protected $product;
11
+
12
+ /**
13
+ * @var Yoast_License_Manager
14
+ */
15
+ protected $license_manager;
16
+
17
+ /**
18
+ * @var string
19
+ */
20
+ protected $error_message = '';
21
+
22
+ /**
23
+ * @var object
24
+ */
25
+ protected $update_response = null;
26
+
27
+ /**
28
+ * @var string The transient name storing the API response
29
+ */
30
+ private $response_transient_key = '';
31
+
32
+ /**
33
+ * @var string The transient name that stores failed request tries
34
+ */
35
+ private $request_failed_transient_key = '';
36
+
37
+ /**
38
+ * Constructor
39
+ *
40
+ * @param string $api_url The url to the EDD shop
41
+ * @param string $item_name The item name in the EDD shop
42
+ * @param string $license_key The (valid) license key
43
+ * @param string $slug The slug. This is either the plugin main file path or the theme slug.
44
+ * @param string $version The current plugin or theme version
45
+ * @param string $author (optional) The item author.
46
+ */
47
+ public function __construct( Yoast_Product $product, $license_manager ) {
48
+ $this->product = $product;
49
+ $this->license_manager = $license_manager;
50
+
51
+ // generate transient names
52
+ $this->response_transient_key = $this->product->get_transient_prefix() . '-update-response';
53
+ $this->request_failed_transient_key = $this->product->get_transient_prefix() . '-update-request-failed';
54
+
55
+ // maybe delete transient
56
+ $this->maybe_delete_transients();
57
+ }
58
+
59
+ /**
60
+ * Deletes the various transients
61
+ * If we're on the update-core.php?force-check=1 page
62
+ */
63
+ private function maybe_delete_transients() {
64
+ global $pagenow;
65
+
66
+ if( $pagenow === 'update-core.php' && isset( $_GET['force-check'] ) ) {
67
+ delete_transient( $this->response_transient_key );
68
+ delete_transient( $this->request_failed_transient_key );
69
+ }
70
+ }
71
+
72
+ /**
73
+ * If the update check returned a WP_Error, show it to the user
74
+ */
75
+ public function show_update_error() {
76
+
77
+ if ( $this->error_message === '' ) {
78
+ return;
79
+ }
80
+
81
+ ?>
82
+ <div class="error">
83
+ <p><?php printf( __( '%s failed to check for updates because of the following error: <em>%s</em>', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->error_message ); ?></p>
84
+ </div>
85
+ <?php
86
+ }
87
+
88
+ /**
89
+ * Calls the API and, if successfull, returns the object delivered by the API.
90
+ *
91
+ * @uses get_bloginfo()
92
+ * @uses wp_remote_post()
93
+ * @uses is_wp_error()
94
+ *
95
+ * @return false||object
96
+ */
97
+ private function call_remote_api() {
98
+
99
+ // only check if the failed transient is not set (or if it's expired)
100
+ if( get_transient( $this->request_failed_transient_key ) !== false ) {
101
+ return false;
102
+ }
103
+
104
+ // start request process
105
+ global $wp_version;
106
+
107
+ // set a transient to prevent failed update checks on every page load
108
+ // this transient will be removed if a request succeeds
109
+ set_transient( $this->request_failed_transient_key, 'failed', 10800 );
110
+
111
+ // setup api parameters
112
+ $api_params = array(
113
+ 'edd_action' => 'get_version',
114
+ 'license' => $this->license_manager->get_license_key(),
115
+ 'item_name' => $this->product->get_item_name(),
116
+ 'wp_version' => $wp_version,
117
+ 'item_version' => $this->product->get_version(),
118
+ 'url' => home_url(),
119
+ 'slug' => $this->product->get_slug()
120
+ );
121
+
122
+ // setup request parameters
123
+ $request_params = array(
124
+ 'method' => 'POST',
125
+ 'body' => $api_params
126
+ );
127
+
128
+ require_once dirname( __FILE__ ) . '/class-api-request.php';
129
+ $request = new Yoast_API_Request( $this->product->get_api_url(), $request_params );
130
+
131
+ if( $request->is_valid() !== true ) {
132
+
133
+ // show error message
134
+ $this->error_message = $request->get_error_message();
135
+ add_action( 'admin_notices', array( $this, 'show_update_error' ) );
136
+
137
+ return false;
138
+ }
139
+
140
+ // request succeeded, delete transient indicating a request failed
141
+ delete_transient( $this->request_failed_transient_key );
142
+
143
+ // decode response
144
+ $response = $request->get_response();
145
+
146
+ // check if response returned that a given site was inactive
147
+ if( isset( $response->license_check ) && ! empty( $response->license_check ) && $response->license_check != 'valid' ) {
148
+
149
+ // deactivate local license
150
+ $this->license_manager->set_license_status( 'invalid' );
151
+
152
+ // show notice to let the user know we deactivated his/her license
153
+ $this->error_message = __( "This site has not been activated properly on yoast.com and thus cannot check for future updates. Please activate your site with a valid license key.", $this->product->get_text_domain() );
154
+ add_action( 'admin_notices', array( $this, 'show_update_error' ) );
155
+ }
156
+
157
+ $response->sections = maybe_unserialize( $response->sections );
158
+
159
+ // store response
160
+ set_transient( $this->response_transient_key, $response, 10800 );
161
+
162
+ return $response;
163
+ }
164
+
165
+ /**
166
+ * Gets the remote product data (from the EDD API)
167
+ *
168
+ * - If it was previously fetched in the current requests, this gets it from the instance property
169
+ * - Next, it tries the 3-hour transient
170
+ * - Next, it calls the remote API and stores the result
171
+ *
172
+ * @return object
173
+ */
174
+ protected function get_remote_data() {
175
+
176
+ // always use property if it's set
177
+ if( null !== $this->update_response ) {
178
+ return $this->update_response;
179
+ }
180
+
181
+ // get cached remote data
182
+ $data = $this->get_cached_remote_data();
183
+
184
+ // if cache is empty or expired, call remote api
185
+ if( $data === false ) {
186
+ $data = $this->call_remote_api();
187
+ }
188
+
189
+ $this->update_response = $data;
190
+ return $data;
191
+ }
192
+
193
+ /**
194
+ * Gets the remote product data from a 3-hour transient
195
+ *
196
+ * @return bool|mixed
197
+ */
198
+ private function get_cached_remote_data() {
199
+
200
+ $data = get_transient( $this->response_transient_key );
201
+
202
+ if( $data ) {
203
+ return $data;
204
+ }
205
+
206
+ return false;
207
+ }
208
+
209
+ }
210
+
211
+ }
admin/license-manager/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ //Nothing to see here
admin/license-manager/samples/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ //Nothing to see here
admin/license-manager/samples/sample-plugin.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ Plugin Name: Sample Plugin
5
+ Version: 1.0
6
+ Plugin URI: https://yoast.com/
7
+ Description: A sample plugin to test the License Manager
8
+ Author: Yoast, DvanKooten
9
+ Author URI: http://yoast.com/
10
+ Text Domain: sample-plugin
11
+ */
12
+
13
+ /**
14
+ * Class Sample_Plugin
15
+ *
16
+ */
17
+ class Sample_Plugin {
18
+
19
+ public function __construct() {
20
+
21
+ // we only need license stuff inside the admin area
22
+ if ( is_admin() ) {
23
+
24
+ // add menu item
25
+ add_action( 'admin_menu', array( $this, 'add_license_menu' ) );
26
+
27
+ // load license class
28
+ $this->load_license_manager();
29
+ }
30
+
31
+
32
+ }
33
+
34
+ /**
35
+ * Loads the License_Plugin_Manager class
36
+ *
37
+ * The class will take care of the rest: notices, license (de)activations, updates, etc..
38
+ */
39
+ public function load_license_manager() {
40
+
41
+ // Instantiate license class
42
+ $license_manager = new Yoast_Plugin_License_Manager( new Sample_Product() );
43
+
44
+ // Setup the required hooks
45
+ $license_manager->setup_hooks();
46
+
47
+ }
48
+
49
+ /**
50
+ * Add license page and add it to Themes menu
51
+ */
52
+ public function add_license_menu() {
53
+ $theme_page = add_options_page( sprintf( __( '%s License', $this->text_domain ), $this->item_name ), sprintf( __( '%s License', $this->text_domain ), $this->item_name ), 'manage_options', $this->text_domain . '-license', array( $this, 'show_license_page' ) );
54
+ }
55
+
56
+ /**
57
+ * Shows license page
58
+ */
59
+ public function show_license_page() {
60
+
61
+ // Instantiate license class
62
+ $license_manager = new Yoast_Plugin_License_Manager( new Sample_Product() );
63
+
64
+ ?>
65
+ <div class="wrap">
66
+ <?php //settings_errors(); ?>
67
+
68
+ <?php $license_manager->show_license_form( false ); ?>
69
+ </div>
70
+ <?php
71
+ }
72
+ }
73
+
74
+ new Sample_Plugin();
admin/license-manager/samples/sample-product.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class Sample_Product
5
+ *
6
+ * Our sample product class
7
+ */
8
+ class Sample_Product extends Yoast_Product {
9
+
10
+ public function __construct() {
11
+ parent::__construct(
12
+ 'https://yoast.com',
13
+ 'Sample Product',
14
+ 'sample-product',
15
+ '1.0',
16
+ 'https://yoast.com/wordpress/plugins/sample-product/',
17
+ 'admin.php?page=sample-product',
18
+ 'sample-product',
19
+ 'Yoast'
20
+ );
21
+ }
22
+
23
+ }
admin/license-manager/samples/sample-theme-functions.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( is_admin() ) {
4
+
5
+ // Instantiate license class
6
+ $license_manager = new Yoast_Theme_License_Manager( new Sample_Product() );
7
+
8
+ // Setup the required hooks
9
+ $license_manager->setup_hooks();
10
+
11
+ }
admin/license-manager/views/form.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ header( 'HTTP/1.0 403 Forbidden' );
4
+ die;
5
+ }
6
+
7
+ /**
8
+ * @var Yoast_Product $product
9
+ */
10
+ $product = $this->product;
11
+
12
+ $this->show_license_form_heading();
13
+
14
+ // Output form tags if we're not embedded in another form
15
+ if( ! $embedded ) {
16
+ echo '<form method="post" action="">';
17
+ }
18
+
19
+ wp_nonce_field( $nonce_name, $nonce_name ); ?>
20
+ <table class="form-table yoast-license-form">
21
+ <tbody>
22
+ <tr valign="top">
23
+ <th scope="row" valign="top"><?php _e( 'License status', $product->get_text_domain() ); ?></th>
24
+ <td>
25
+ <?php if( $this->license_is_valid() ) { ?>
26
+ <span style="color: white; background: limegreen; padding:3px 6px;">ACTIVE</span> &nbsp; - &nbsp; you are receiving updates.
27
+ <?php } else { ?>
28
+ <span style="color:white; background: red; padding: 3px 6px;">INACTIVE</span> &nbsp; - &nbsp; you are <strong>not</strong> receiving updates.
29
+ <?php } ?>
30
+ </td>
31
+ </tr>
32
+ <tr valign="top">
33
+ <th scope="row" valign="top"><?php _e('Toggle license status', $product->get_text_domain() ); ?></th>
34
+ <td class="yoast-license-toggler">
35
+
36
+ <?php if( $this->license_is_valid() ) { ?>
37
+ <button name="<?php echo esc_attr( $action_name ); ?>" type="submit" class="button-secondary yoast-license-deactivate" value="deactivate"><?php echo esc_html_e( 'Deactivate License', $product->get_text_domain() ); ?></button> &nbsp;
38
+ <small><?php _e( '(deactivate your license so you can activate it on another WordPress site)', $product->get_text_domain() ); ?></small>
39
+ <?php } else {
40
+
41
+ if( $this->get_license_key() !== '') { ?>
42
+ <button name="<?php echo esc_attr( $action_name ); ?>" type="submit" class="button-secondary yoast-license-activate" value="activate" /><?php echo esc_html_e('Activate License', $product->get_text_domain() ); ?></button> &nbsp;
43
+ <?php } else {
44
+ _e( 'Please enter a license key in the field below first.', $product->get_text_domain() );
45
+ }
46
+
47
+ } ?>
48
+
49
+ </td>
50
+ </tr>
51
+ <tr valign="top">
52
+ <th scope="row" valign="top"><?php _e( 'License Key', $product->get_text_domain() ); ?></th>
53
+ <td>
54
+ <input name="<?php echo esc_attr( $key_name ); ?>" type="text" class="regular-text yoast-license-key-field <?php if( $obfuscate ) { ?>yoast-license-obfuscate<?php } ?>" value="<?php echo esc_attr( $visible_license_key ); ?>" placeholder="<?php echo esc_attr( sprintf( __( 'Paste your %s license key here..', $product->get_text_domain() ), $product->get_item_name() ) ); ?>" <?php if( $readonly ) { echo 'readonly="readonly"'; } ?> />
55
+ <?php if( $this->license_constant_is_defined ) { ?>
56
+ <p class="help"><?php printf( __( "You defined your license key using the %s PHP constant.", $product->get_text_domain() ), '<code>' . $this->license_constant_name . '</code>' ); ?></p>
57
+ <?php } ?>
58
+ </td>
59
+ </tr>
60
+
61
+ </tbody>
62
+ </table>
63
+
64
+ <?php
65
+
66
+ if( $this->license_is_valid() ) {
67
+
68
+ $expiry_date = strtotime( $this->get_license_expiry_date() );
69
+
70
+ if( $expiry_date !== false ) {
71
+ echo '<p>';
72
+
73
+ printf( __( 'Your %s license will expire on %s.', $product->get_text_domain() ), $product->get_item_name(), date('F jS Y', $expiry_date ) );
74
+
75
+ if( strtotime( '+3 months' ) > $expiry_date ) {
76
+ printf( ' ' . __('%sRenew your license now%s.', $product->get_text_domain() ), '<a href="'. $this->product->get_tracking_url( 'renewal' ) .'">', '</a>' );
77
+ }
78
+
79
+ echo '</p>';
80
+ }
81
+ }
82
+
83
+ // Only show a "Save Changes" button and end form if we're not embedded in another form.
84
+ if( ! $embedded ) {
85
+
86
+ // only show "Save Changes" button if license is not activated and not defined with a constant
87
+ if( $readonly === false ) {
88
+ submit_button();
89
+ }
90
+
91
+ echo '</form>';
92
+ }
93
+
94
+ $product = null;
admin/license-manager/views/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ //Nothing to see here
admin/license-manager/views/script.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ header( 'HTTP/1.0 403 Forbidden' );
4
+ die;
5
+ }
6
+ ?><script type="text/javascript">
7
+ (function($) {
8
+
9
+ if( typeof YoastLicenseManager !== "undefined" ) {
10
+ return;
11
+ }
12
+
13
+ window.YoastLicenseManager = (function () {
14
+
15
+ function init() {
16
+ var $keyInputs = $(".yoast-license-key-field.yoast-license-obfuscate");
17
+ var $actionButtons = $('.yoast-license-toggler button');
18
+ var $submitButtons = $('input[type="submit"], button[type="submit"]');
19
+
20
+ $submitButtons.click( addDisableEvent );
21
+ $actionButtons.click( actOnLicense );
22
+ $keyInputs.click( setEmptyValue );
23
+ }
24
+
25
+ function setEmptyValue() {
26
+ if( ! $(this).is('[readonly]') ) {
27
+ $(this).val('');
28
+ }
29
+ }
30
+
31
+ function actOnLicense() {
32
+ var $formScope = $(this).closest('form');
33
+ var $actionButton = $formScope.find('.yoast-license-toggler button');
34
+
35
+ // fake input field with exact same name => value
36
+ $("<input />")
37
+ .attr('type', 'hidden')
38
+ .attr( 'name', $(this).attr('name') )
39
+ .val( $(this).val() )
40
+ .appendTo( $formScope );
41
+
42
+ // change button text to show we're working..
43
+ var text = ( $actionButton.hasClass('yoast-license-activate') ) ? "Activating..." : "Deactivating...";
44
+ $actionButton.text( text );
45
+ }
46
+
47
+ function addDisableEvent() {
48
+ var $formScope = $(this).closest('form');
49
+ $formScope.submit(disableButtons);
50
+ }
51
+
52
+ function disableButtons() {
53
+ var $formScope = $(this).closest('form');
54
+ var $submitButton = $formScope.find('input[type="submit"], button[type="submit"]');
55
+ $submitButton.prop( 'disabled', true );
56
+ }
57
+
58
+ return {
59
+ init: init
60
+ }
61
+
62
+ })();
63
+
64
+ YoastLicenseManager.init();
65
+
66
+ })(jQuery);
67
+ </script>
admin/pages/dashboard.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ global $yoast_ga_admin;
3
+
4
+ echo $yoast_ga_admin->content_head();
5
+ ?>
6
+ <h2 id="yoast_ga_title"><?php echo __( 'Yoast Google Analytics: Dashboard', 'google-analytics-for-wordpress' ); ?></h2>
7
+
8
+ <div id="ga-promote">
9
+ <p>This feature <a href="https://yoast.com/google-analytics-5/#utm_medium=textlink&utm_source=gawp-config&utm_campaign=wpgaplugin">will be coming soon</a>. For now, you can <a href="https://yoast.com/cat/analytics/#utm_medium=textlink&utm_source=gawp-config&utm_campaign=wpgaplugin">read our posts on Analytics</a>, or, of course, <a href="http://www.google.com/analytics/">log into Google Analytics</a> yourself.</p>
10
+
11
+ <p align="center"><img src="<?php echo GAWP_URL . 'img/'; ?>yoast_avatar_joost.png" width="250"></p>
12
+ </div>
13
+
14
+ <?php
15
+ echo $yoast_ga_admin->content_footer();
16
+ ?>
admin/pages/extensions.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ global $yoast_ga_admin;
3
+
4
+ echo $yoast_ga_admin->content_head();
5
+ ?>
6
+ <h2 id="yoast_ga_title"><?php echo __( 'Yoast Google Analytics: Extensions', 'google-analytics-for-wordpress' ); ?></h2>
7
+
8
+ <div id="extensions" class="wpseotab">
9
+ <div class="extension ecommerce">
10
+ <a target="_blank" href="https://yoast.com/wordpress/plugins/seo-premium/#utm_medium=banner&utm_source=gawp-config&utm_campaign=extension-page-banners">
11
+ <h3>Google Analytics<br />E-Commerce tracking</h3>
12
+ </a>
13
+ <p>Track your E-Commerce data and transactions with this E-Commerce extension for Google Analytics.</p>
14
+ <p><a target="_blank" href="https://yoast.com/wordpress/plugins/ga-ecommerce-edd/#utm_medium=banner&utm_source=gawp-config&utm_campaign=extension-page-banners" class="button-primary">
15
+ Get this extension </a></p>
16
+ </div>
17
+ </div>
18
+ <div class="clear"></div>
19
+ <?php
20
+ echo $yoast_ga_admin->content_footer();
21
+ ?>
admin/pages/settings.php ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ global $yoast_ga_admin;
3
+
4
+ echo $yoast_ga_admin->content_head();
5
+ ?>
6
+ <h2 id="yoast_ga_title"><?php echo __( 'Yoast Google Analytics: Settings', 'google-analytics-for-wordpress' ); ?></h2>
7
+
8
+ <?php
9
+ settings_errors('yoast_google_analytics');
10
+ ?>
11
+
12
+ <h2 class="nav-tab-wrapper" id="ga-tabs">
13
+ <a class="nav-tab" id="general-tab" href="#top#general"><?php _e( 'General', 'google-analytics-for-wordpress' ); ?></a>
14
+ <a class="nav-tab" id="universal-tab" href="#top#universal"><?php _e( 'Universal', 'google-analytics-for-wordpress' ); ?></a>
15
+ <a class="nav-tab" id="advanced-tab" href="#top#advanced"><?php _e( 'Advanced', 'google-analytics-for-wordpress' ); ?></a>
16
+ <a class="nav-tab" id="debugmode-tab" href="#top#debugmode"><?php _e( 'Debug mode', 'google-analytics-for-wordpress' ); ?></a>
17
+ </h2>
18
+
19
+ <?php
20
+ echo $yoast_ga_admin->create_form( 'settings' );
21
+ ?>
22
+ <div class="tabwrapper">
23
+ <div id="general" class="gatab">
24
+ <?php
25
+ echo '<h2>' . __( 'General settings', 'google-analytics-for-wordpress' ) . '</h2>';
26
+ echo '<div id="ga-promote">';
27
+
28
+ $profiles = $yoast_ga_admin->get_profiles();
29
+ $ga_url = $_SERVER['PHP_SELF'];
30
+ if ( isset( $_GET['page'] ) ) {
31
+ $ga_url .= '?page=' . $_GET['page'];
32
+ }
33
+ $ga_url .= '&reauth=true';
34
+
35
+ echo "<div id='google_ua_code_field'>";
36
+ if ( count( $profiles ) == 0 ) {
37
+ echo '<div class="ga-form ga-form-input">';
38
+ echo '<label class="ga-form ga-form-text-label ga-form-label-left" id="yoast-ga-form-label-text-ga-authwithgoogle" />' . __( 'Google profile', 'google-analytics-for-wordpress' ) . ':</label>';
39
+ echo '<a class="button" href="' . $ga_url . '">' . __('Authenticate with your Google account', 'google-analytics-for-wordpress') . '</a>';
40
+ echo '</div>';
41
+ echo '<div class="ga-form ga-form-input">';
42
+ echo '<label class="ga-form ga-form-text-label ga-form-label-left" id="yoast-ga-form-label-text-ga-authwithgoogle" />' . __('Current UA-profile', 'google-analytics-for-wordpress') . '</label>';
43
+ echo $yoast_ga_admin->get_setting('analytics_profile');
44
+ echo '</div>';
45
+ } else {
46
+ echo $yoast_ga_admin->select( 'Analytics profile', 'analytics_profile', $profiles );
47
+
48
+ echo '<div class="ga-form ga-form-input">';
49
+ echo '<label class="ga-form ga-form-text-label ga-form-label-left" id="yoast-ga-form-label-text-ga-authwithgoogle" />&nbsp;</label>';
50
+ echo '<a class="button" href="' . $ga_url . '">' . __('Re-authenticate with your Google account', 'google-analytics-for-wordpress') . '</a>';
51
+ echo '</div>';
52
+ }
53
+ echo "</div>";
54
+
55
+ echo '<label class="ga-form ga-form-checkbox-label ga-form-label-left">';
56
+ echo $yoast_ga_admin->input( 'checkbox', NULL, 'manual_ua_code', __('Manually enter your UA code', 'google-analytics-for-wordpress' ) );
57
+ echo '</label>';
58
+ echo '<div id="enter_ua">';
59
+ echo $yoast_ga_admin->input( 'text', NULL, 'manual_ua_code_field');
60
+ echo '</div>';
61
+ echo '<div class="clear"></div></div>';
62
+ ?>
63
+ <div class="clear"><br /></div>
64
+ <?php
65
+ echo $yoast_ga_admin->input( 'checkbox', __('Track outbound click & downloads', 'google-analytics-for-wordpress' ), 'track_outbound', NULL, __( 'Clicks &amp; downloads will be tracked as events, you can find these under Content &raquo; Event Tracking in your Google Analytics reports.', 'google-analytics-for-wordpress' ) );
66
+ echo $yoast_ga_admin->input( 'checkbox', __('Allow tracking of anonymous data', 'google-analytics-for-wordpress' ), 'anonymous_data', NULL, __( 'By allowing us to track anonymous data we can better help you, because we know with which WordPress configurations, themes and plugins we should test. No personal data will be submitted.', 'google-analytics-for-wordpress' ) );
67
+ echo $yoast_ga_admin->input( 'checkbox', __('Anonymize IP\'s', 'google-analytics-for-wordpress' ), 'anonymize_ips', NULL, __( 'This adds <code><a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_gat._anonymizeIp" target="_blank">_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.', 'google-analytics-for-wordpress' ) );
68
+ echo $yoast_ga_admin->select( 'Ignore users', 'ignore_users', $yoast_ga_admin->get_userroles(), __('Hint: Select multiple roles by using CTRL or CMD.', 'google-analytics-for-wordpress' ) . '<br />' . __( 'Users of the role you select and higher will be ignored, so if you select Editor, all Editors and Administrators will be ignored.', 'google-analytics-for-wordpress' ), true );
69
+ ?>
70
+ </div>
71
+ <div id="universal" class="gatab">
72
+ <?php
73
+ echo '<h2>' . __( 'Universal settings', 'google-analytics-for-wordpress' ) . '</h2>';
74
+ echo $yoast_ga_admin->input( 'checkbox', __('Enable Universal tracking', 'google-analytics-for-wordpress' ), 'enable_universal', NULL, __('First enable Universal tracking in your Google Analytics account. How to do that, please read <a href="https://developers.google.com/analytics/devguides/collection/upgrade/guide" target="_blank">this guide</a> to learn how to do that.', 'google-analytics-for-wordpress') );
75
+ echo $yoast_ga_admin->input( 'checkbox', __('Enable Demographics and Interest Reports', 'google-analytics-for-wordpress' ), 'demographics', NULL, __('You have to enable the Demographics in Google Analytics before you can see the tracking data. We have a doc in our <a href="http://kb.yoast.com/article/154-enable-demographics-and-interests-report-in-google-analytics//#utm_medium=kb-link&utm_source=gawp-config&utm_campaign=wpgaplugin" target="_blank">knowlegde base</a> about this feature.', 'google-analytics-for-wordpress') );
76
+ ?>
77
+ </div>
78
+ <div id="advanced" class="gatab">
79
+ <?php
80
+ echo '<h2>' . __( 'Advanced settings', 'google-analytics-for-wordpress' ) . '</h2>';
81
+ echo $yoast_ga_admin->select( __('Track downloads as', 'google-analytics-for-wordpress' ), 'track_download_as', $yoast_ga_admin->track_download_types(), __( 'Not recommended, as this would skew your statistics, but it does make it possible to track downloads as goals.', 'google-analytics-for-wordpress' ) );
82
+ echo $yoast_ga_admin->input( 'text', __('Extensions of files to track as downloads', 'google-analytics-for-wordpress' ), 'extensions_of_files', NULL, 'Please separate extensions using commas' );
83
+ echo $yoast_ga_admin->select( __('Track full URL of outbound clicks or just the domain', 'google-analytics-for-wordpress' ), 'track_full_url', $yoast_ga_admin->get_track_full_url() );
84
+ echo $yoast_ga_admin->input( 'text', __('Subdomain tracking', 'google-analytics-for-wordpress' ), 'subdomain_tracking', NULL, __('This allows you to set the domain that\'s set by <code>setDomainName</code> for tracking subdomains, if empty this will not be set.', 'google-analytics-for-wordpress' ) );
85
+
86
+ echo $yoast_ga_admin->input( 'text', __('Set path for internal links to track as outbound links', 'google-analytics-for-wordpress' ), 'track_internal_as_outbound', NULL, '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>' );
87
+ echo $yoast_ga_admin->input( 'text', __('Label for those links', 'google-analytics-for-wordpress' ), 'track_internal_as_label', NULL, "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\"." );
88
+
89
+ echo $yoast_ga_admin->input( 'checkbox', __('Tag links in RSS feed with campaign variables', 'google-analytics-for-wordpress' ), 'tag_links_in_rss', NULL, __( '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" target="_blank">this help page</a> for info on how to enable this feature in FeedBurner.', 'google-analytics-for-wordpress' ) );
90
+ echo $yoast_ga_admin->input( 'checkbox', __('Allow anchor', 'google-analytics-for-wordpress' ), 'allow_anchor', NULL, __( 'This adds a <code><a href="http://code.google.com/apis/analytics/docs/gaJSApiCampaignTracking.html#_gat.GA_Tracker_._setAllowAnchor" target="_blank">_setAllowAnchor</a></code> call to your tracking code, and makes RSS link tagging use a # as well.', 'google-analytics-for-wordpress' ) );
91
+ echo $yoast_ga_admin->input( 'checkbox', __('Add <code>_setAllowLinker</code>', 'google-analytics-for-wordpress' ), 'add_allow_linker', NULL, __( 'This adds a <code><a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setAllowLinker" target="_blank">_setAllowLinker</a></code> call to your tracking code, allowing you to use <code>_link</code> and related functions.', 'google-analytics-for-wordpress' ) );
92
+ echo $yoast_ga_admin->textarea( 'Custom code', 'custom_code', __( 'Not for the average user: this allows you to add a line of code, to be added before the <code>trackPageview</code> call.', 'google-analytics-for-wordpress' ) );
93
+ ?>
94
+ </div>
95
+ <div id="debugmode" class="gatab">
96
+ <?php
97
+ echo '<h2>' . __( 'Debug settings', 'google-analytics-for-wordpress' ) . '</h2>';
98
+
99
+ echo '<div id="ga-promote">';
100
+ echo '<p class="ga-topdescription">' . __( 'If you want to confirm that tracking on your blog is working as it should, enable these options and check the console in Firebug (for Firefox), Firebug Lite (for other browsers) or Chrome & Safari\'s Web Inspector. Be absolutely sure to disable debugging afterwards, as it is slower than normal tracking.', 'google-analytics-for-wordpress' ) . '</p>';
101
+ echo '<p class="ga-topdescription"><strong>' . __( 'Note', 'google-analytics-for-wordpress' ) . ':</strong> ' . __( 'the debugging and firebug scripts are only loaded for admins.', 'google-analytics-for-wordpress' ) . '</p>';
102
+ echo '</div>';
103
+ echo $yoast_ga_admin->input( 'checkbox', __('Enable debug mode', 'google-analytics-for-wordpress' ), 'debug_mode' );
104
+ echo $yoast_ga_admin->input( 'checkbox', __('Enable Firebug Lite', 'google-analytics-for-wordpress' ), 'firebug_lite' );
105
+ ?>
106
+ </div>
107
+ </div>
108
+ <?php
109
+ echo $yoast_ga_admin->end_form( 'Save changes', 'settings' );
110
+ echo $yoast_ga_admin->content_footer();
111
+ ?>
112
+ <script type="text/javascript">
113
+ jQuery(document).ready(
114
+ function() {
115
+ jQuery('#yoast-ga-form-select-settings-analytics_profile').chosen();
116
+ jQuery('#yoast-ga-form-select-settings-ignore_users').chosen( { placeholder_text_multiple : '<?php echo __( 'Select the users to ignore', 'google-analytics-for-wordpress' ); ?>' });
117
+ }
118
+ );
119
+ </script>
admin/views/content_footer.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ </div>
2
+ <div class="yoast-ga-banners">
3
+ <?php foreach ( $banners as $item ): ?>
4
+ <p><a href="<?php echo $item['url']; ?>" target="_blank">
5
+ <img src="<?php echo $item['banner']; ?>" alt="<?php echo $item['title']; ?>" class="yoast-banner" border="0" width="250" />
6
+ </a></p>
7
+ <?php endforeach; ?>
8
+ </div>
9
+ </div>
admin/views/content_head.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <div id="yoast-ga-wrapper">
2
+ <div class="yoast-ga-content">
admin/wp-gdata/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ //Nothing to see here
admin/xmlparser.php DELETED
@@ -1,129 +0,0 @@
1
- <?php
2
- function yoast_xml2array($contents, $get_attributes = 1, $priority = 'tag') {
3
- if (!function_exists('xml_parser_create'))
4
- {
5
- return "error";
6
- }
7
- $parser = xml_parser_create('');
8
- xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
9
- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
10
- xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
11
- xml_parse_into_struct($parser, trim($contents), $xml_values);
12
- xml_parser_free($parser);
13
- if (!$xml_values)
14
- return; //Hmm...
15
- $xml_array = array ();
16
- $parents = array ();
17
- $opened_tags = array ();
18
- $arr = array ();
19
- $current = & $xml_array;
20
- $repeated_tag_index = array ();
21
- foreach ($xml_values as $data)
22
- {
23
- unset ($attributes, $value);
24
- extract($data);
25
- $result = array ();
26
- $attributes_data = array ();
27
- if (isset ($value))
28
- {
29
- if ($priority == 'tag')
30
- $result = $value;
31
- else
32
- $result['value'] = $value;
33
- }
34
- if (isset ($attributes) and $get_attributes)
35
- {
36
- foreach ($attributes as $attr => $val)
37
- {
38
- if ($priority == 'tag')
39
- $attributes_data[$attr] = $val;
40
- else
41
- $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
42
- }
43
- }
44
- if ($type == "open")
45
- {
46
- $parent[$level -1] = & $current;
47
- if (!is_array($current) or (!in_array($tag, array_keys($current))))
48
- {
49
- $current[$tag] = $result;
50
- if ($attributes_data)
51
- $current[$tag . '_attr'] = $attributes_data;
52
- $repeated_tag_index[$tag . '_' . $level] = 1;
53
- $current = & $current[$tag];
54
- }
55
- else
56
- {
57
- if (isset ($current[$tag][0]))
58
- {
59
- $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
60
- $repeated_tag_index[$tag . '_' . $level]++;
61
- }
62
- else
63
- {
64
- $current[$tag] = array (
65
- $current[$tag],
66
- $result
67
- );
68
- $repeated_tag_index[$tag . '_' . $level] = 2;
69
- if (isset ($current[$tag . '_attr']))
70
- {
71
- $current[$tag]['0_attr'] = $current[$tag . '_attr'];
72
- unset ($current[$tag . '_attr']);
73
- }
74
- }
75
- $last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
76
- $current = & $current[$tag][$last_item_index];
77
- }
78
- }
79
- elseif ($type == "complete")
80
- {
81
- if (!isset ($current[$tag]))
82
- {
83
- $current[$tag] = $result;
84
- $repeated_tag_index[$tag . '_' . $level] = 1;
85
- if ($priority == 'tag' and $attributes_data)
86
- $current[$tag . '_attr'] = $attributes_data;
87
- }
88
- else
89
- {
90
- if (isset ($current[$tag][0]) and is_array($current[$tag]))
91
- {
92
- $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
93
- if ($priority == 'tag' and $get_attributes and $attributes_data)
94
- {
95
- $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
96
- }
97
- $repeated_tag_index[$tag . '_' . $level]++;
98
- }
99
- else
100
- {
101
- $current[$tag] = array (
102
- $current[$tag],
103
- $result
104
- );
105
- $repeated_tag_index[$tag . '_' . $level] = 1;
106
- if ($priority == 'tag' and $get_attributes)
107
- {
108
- if (isset ($current[$tag . '_attr']))
109
- {
110
- $current[$tag]['0_attr'] = $current[$tag . '_attr'];
111
- unset ($current[$tag . '_attr']);
112
- }
113
- if ($attributes_data)
114
- {
115
- $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
116
- }
117
- }
118
- $repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken
119
- }
120
- }
121
- }
122
- elseif ($type == 'close')
123
- {
124
- $current = & $parent[$level -1];
125
- }
126
- }
127
- return ($xml_array);
128
- }
129
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/yst_plugin_tools.css DELETED
@@ -1,68 +0,0 @@
1
- td.yst_desc {
2
- font-weight: normal;
3
- font-size: 13px;
4
- line-height: 14px;
5
- color: #777;
6
- }
7
-
8
- tr.yst_row {
9
- padding: 5px 0 0 0;
10
- margin: 5px 0 0 0;
11
- }
12
-
13
- tr.yst_row.even {
14
- background-color: #f6f6f6;
15
- }
16
-
17
- div.inside ul {
18
- margin-left: 20px;
19
- }
20
-
21
- div.inside ul li {
22
- list-style: square;
23
- line-height: 16px;
24
- }
25
-
26
- div.inside a, div.inside a.rsswidget {
27
- font-family: 'Lucida Grande', Verdana, Arial, 'Bitstream Vera Sans', sans-serif;
28
- text-decoration: none;
29
- }
30
-
31
- div.inside a:hover, div.inside a.rsswidget:hover {
32
- text-decoration: underline;
33
- }
34
-
35
- .text, .select {
36
- width: 250px;
37
- }
38
-
39
- .postbox p {
40
- text-align: left;
41
- margin: 0 10px 10px 10px;
42
- font-size: 13px;
43
- line-height: 150%;
44
- }
45
-
46
- .postbox pre {
47
- margin: 5px 10px;
48
- padding: 4px;
49
- background: lightyellow;
50
- }
51
-
52
- div.inside .button:hover, div.inside .button-primary:hover {
53
- text-decoration: none;
54
- }
55
-
56
- .postbox#spread {
57
- border: green solid 2px;
58
- }
59
-
60
- .postbox#spread strong {
61
- color: green;
62
- font-weight: bold;
63
- font-size: 105%;
64
- }
65
-
66
- .postbox {
67
- margin: 0 10px 10px 0;
68
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/yst_plugin_tools.php DELETED
@@ -1,190 +0,0 @@
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 $optionname = '';
16
- var $accesslvl = 'edit_users';
17
-
18
- function Yoast_GA_Plugin_Admin() {
19
- add_action( 'admin_menu', array( &$this, 'register_settings_page' ) );
20
- add_filter( 'plugin_action_links', array( &$this, 'add_action_link' ), 10, 2 );
21
-
22
- add_action( 'admin_print_scripts', array( &$this, 'config_page_scripts' ) );
23
- add_action( 'admin_print_styles', array( &$this, 'config_page_styles' ) );
24
-
25
- add_action( 'wp_dashboard_setup', array( &$this, 'widget_setup' ) );
26
- }
27
-
28
- function config_page_styles() {
29
- if ( isset( $_GET['page'] ) && $_GET['page'] == $this->hook ) {
30
- wp_enqueue_style( 'dashboard' );
31
- wp_enqueue_style( 'thickbox' );
32
- wp_enqueue_style( 'global' );
33
- wp_enqueue_style( 'wp-admin' );
34
- wp_enqueue_style( 'gawp-css', plugin_dir_url( __FILE__ ) . 'yst_plugin_tools.css' );
35
- }
36
- }
37
-
38
- function register_settings_page() {
39
- add_options_page( $this->longname, $this->shortname, $this->accesslvl, $this->hook, array( &$this, 'config_page' ) );
40
- }
41
-
42
- function plugin_options_url() {
43
- return admin_url( 'options-general.php?page=' . $this->hook );
44
- }
45
-
46
- /**
47
- * Add a link to the settings page to the plugins list
48
- */
49
- function add_action_link( $links, $file ) {
50
- static $this_plugin;
51
- if ( empty( $this_plugin ) )
52
- $this_plugin = 'google-analytics-for-wordpress/googleanalytics.php';
53
- if ( $file == $this_plugin ) {
54
- $settings_link = '<a href="' . $this->plugin_options_url() . '">' . __( 'Settings', 'google-analytics-for-wordpress' ) . '</a>';
55
- array_unshift( $links, $settings_link );
56
- }
57
- return $links;
58
- }
59
-
60
- function config_page() {
61
-
62
- }
63
-
64
- function config_page_scripts() {
65
- if ( isset( $_GET['page'] ) && $_GET['page'] == $this->hook ) {
66
- wp_enqueue_script( 'postbox' );
67
- wp_enqueue_script( 'dashboard' );
68
- wp_enqueue_script( 'thickbox' );
69
- wp_enqueue_script( 'media-upload' );
70
- wp_enqueue_script( 'jquery-chosen', GAWP_URL . 'js/chosen.jquery.min.js', array( 'jquery' ) );
71
- wp_enqueue_style( 'jquery-chosen-css', GAWP_URL . 'js/chosen.css' );
72
- }
73
- }
74
-
75
- /**
76
- * Create a Checkbox input field
77
- */
78
- function checkbox( $id ) {
79
- $options = get_option( $this->optionname );
80
- $checked = false;
81
- if ( isset( $options[$id] ) && $options[$id] == 1 )
82
- $checked = true;
83
- return '<input type="checkbox" id="' . $id . '" name="' . $id . '"' . checked( $checked, true, false ) . '/>';
84
- }
85
-
86
- /**
87
- * Create a Text input field
88
- */
89
- function textinput( $id ) {
90
- $options = get_option( $this->optionname );
91
- $val = '';
92
- if ( isset( $options[$id] ) )
93
- $val = $options[$id];
94
- return '<input class="text" type="text" id="' . $id . '" name="' . $id . '" size="30" value="' . $val . '"/>';
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
-
124
- <div class="inside">
125
- <?php echo $content; ?>
126
- </div>
127
- </div>
128
- <?php
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:', 'google-analytics-for-wordpress' ) . '</p>';
171
- $content .= '<ul>';
172
- $content .= '<li><a href="' . $this->homepage . '">' . __( 'Link to it so other folks can find out about it.', 'google-analytics-for-wordpress' ) . '</a></li>';
173
- $content .= '<li><a href="http://wordpress.org/extend/plugins/' . $hook . '/">' . __( 'Give it a 5 star rating on WordPress.org.', 'google-analytics-for-wordpress' ) . '</a></li>';
174
- $content .= '<li><a href="http://wordpress.org/extend/plugins/' . $hook . '/">' . __( 'Let other people know that it works with your WordPress setup.', 'google-analytics-for-wordpress' ) . '</a></li>';
175
- $content .= '</ul>';
176
- $this->postbox( $hook . 'like', __( 'Like this plugin?', 'google-analytics-for-wordpress' ), $content );
177
- }
178
-
179
- function text_limit( $text, $limit, $finish = ' [&hellip;]' ) {
180
- if ( strlen( $text ) > $limit ) {
181
- $text = substr( $text, 0, $limit );
182
- $text = substr( $text, 0, -( strlen( strrchr( $text, ' ' ) ) ) );
183
- $text .= $finish;
184
- }
185
- return $text;
186
- }
187
-
188
- }
189
- }
190
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
css/yoast_ga_styles.css ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ h2#yoast_ga_title {
2
+ font-size: 23px;
3
+ font-weight: 400;
4
+ padding: 9px 15px 4px 0;
5
+ line-height: 29px;
6
+ }
7
+
8
+ .nav-tab-wrapper {
9
+ margin-bottom: 0px;
10
+ }
11
+
12
+ .gatab {
13
+ display: none;
14
+ }
15
+
16
+ .gatab.active {
17
+ display: block;
18
+ padding: 0.5em 0.9em;
19
+ border: 1px solid #ddd;
20
+ background-color: #fff;
21
+ border-radius: 0 3px 3px 3px;
22
+ }
23
+
24
+ .tabwrapper .gatab {
25
+ background: none;
26
+ border: none;
27
+ padding: 0px;
28
+ }
29
+
30
+ .tabwrapper .gatab h2 {
31
+ font-size: 23px;
32
+ font-weight: 400;
33
+ padding: 9px 15px 4px 0;
34
+ }
35
+
36
+ .ga-form-submit {
37
+ margin-top: 20px;
38
+ }
39
+
40
+ .ga-form-label-left {
41
+ width: 250px;
42
+ float: left;
43
+ margin: 0 0 0 5px;
44
+ font-weight: bold;
45
+ cursor: default;
46
+ font-size: 14px;
47
+ }
48
+
49
+ .ga-form-input {
50
+ margin-top: 10px;
51
+ margin-bottom: 10px;
52
+ }
53
+
54
+ #yoast-ga-wrapper {
55
+ display: table;
56
+ width: auto;
57
+ max-width: 1150px;
58
+ }
59
+
60
+ .yoast-ga-content {
61
+ display: table-cell;
62
+ min-width: 850px;
63
+ height: 500px;
64
+ padding: 0;
65
+ margin: 0;
66
+ vertical-align: top;
67
+ }
68
+
69
+ .yoast-ga-banners {
70
+ display: table-cell;
71
+ width: 261px;
72
+ height: 500px;
73
+ padding: 0;
74
+ margin: 0;
75
+ vertical-align: top;
76
+ padding: 20px;
77
+ }
78
+
79
+ .ga-form-input {
80
+ display: table;
81
+ margin-bottom: 20px;
82
+ }
83
+
84
+ .ga-form-table {
85
+ display: table-cell;
86
+ }
87
+
88
+ .ga-form-description {
89
+ color: #999999;
90
+ max-width: 325px;
91
+ display: block;
92
+ float: right;
93
+ }
94
+
95
+ p.ga-topdescription {
96
+ max-width: 600px;
97
+ }
98
+
99
+ #ga-promote {
100
+ border: 1px solid #ccc;
101
+ background-color: #fff;
102
+ max-width: 600px;
103
+ padding-left: 10px;
104
+ }
105
+
106
+ #yoast-ga-form-settings input[type="text"] {
107
+ width: 325px;
108
+ }
109
+
110
+ #enter_ua {
111
+ margin-top: 10px;
112
+ padding-top: 10px;
113
+ display: none;
114
+ }
115
+
116
+ #yoast-ga-form-text-settings-ga_general-manual_ua_code_field {
117
+ margin-top: -30px;
118
+ }
119
+
120
+ select.ga-multiple {
121
+ width: 300px;
122
+ height: 150px !important;
123
+ }
124
+ .wpseotab .extension {
125
+ box-sizing: border-box;
126
+ width: 350px;
127
+ height: 230px;
128
+ margin: 10px 20px 10px 0;
129
+ float: left;
130
+ border: 1px solid #ccc;
131
+ }
132
+
133
+ .wpseotab .extension p {
134
+ margin: 0;
135
+ padding: 10px;
136
+ }
137
+
138
+ .wpseotab .extension h3 {
139
+ box-sizing: border-box;
140
+ height: 110px;
141
+ margin: 0;
142
+ padding: 20px 10px 0 120px;
143
+ border-bottom: 1px solid #ccc;
144
+ background: #fff no-repeat left 10px;
145
+ background-size: 130px 100px;
146
+ }
147
+
148
+ .extension a {
149
+ text-decoration: none;
150
+ }
151
+
152
+ .ecommerce h3 {
153
+ background-image: url(../img/eComm_130x100.png) !important;
154
+ }
155
+
156
+ #ga-debug-info h3 {
157
+ font-size: 14px;
158
+ padding-left: 16px;
159
+ height: 30px;
160
+ margin-top: 10px;
161
+ }
custom_se_async.js DELETED
@@ -1,141 +0,0 @@
1
- // This JavaScript was developed by GA-Experts (http://www.ga-experts.co.uk) for Google Analytics
2
- // Please use this code to overwrite the default set of Search Engines in the GA tracking code
3
- // Use this code at your own risk. GA Experts takes no responsibility for errors, loss of data or any other complications arising from the use of this code
4
- // Version 2.0 (Mar 2007) - many thanks to Brian Clifton and Tomas Remotigue for help with this
5
- // For enquiries please contact mail@ga-experts.co.uk
6
-
7
- // Dutch Search Engines added by Joost de Valk (http://www.joostdevalk.nl)
8
- // For enquiries specifically about the Dutch SE's please contact joost@joostdevalk.nl
9
-
10
- // Google EMEA Image domains
11
- _gaq.push(
12
- ['_addOrganic','images.google.co.uk','q'],
13
- ['_addOrganic','images.google.es','q'],
14
- ['_addOrganic','images.google.pt','q'],
15
- ['_addOrganic','images.google.it','q'],
16
- ['_addOrganic','images.google.fr','q'],
17
- ['_addOrganic','images.google.nl','q'],
18
- ['_addOrganic','images.google.be','q'],
19
- ['_addOrganic','images.google.de','q'],
20
- ['_addOrganic','images.google.no','q'],
21
- ['_addOrganic','images.google.se','q'],
22
- ['_addOrganic','images.google.dk','q'],
23
- ['_addOrganic','images.google.fi','q'],
24
- ['_addOrganic','images.google.ch','q'],
25
- ['_addOrganic','images.google.at','q'],
26
- ['_addOrganic','images.google.ie','q'],
27
- ['_addOrganic','images.google.ru','q'],
28
- ['_addOrganic','images.google.pl','q']
29
- );
30
-
31
- // Other Google Image search
32
- _gaq.push(
33
- ['_addOrganic','images.google.com','q'],
34
- ['_addOrganic','images.google.ca','q'],
35
- ['_addOrganic','images.google.com.au','q'],
36
- ['_addOrganic','images.google','q']
37
- );
38
-
39
- // Blogsearch
40
- _gaq.push(
41
- ['_addOrganic','blogsearch.google','q']
42
- );
43
-
44
- // Google EMEA Domains
45
- _gaq.push(
46
- ['_addOrganic','google.co.uk','q'],
47
- ['_addOrganic','google.es','q'],
48
- ['_addOrganic','google.pt','q'],
49
- ['_addOrganic','google.it','q'],
50
- ['_addOrganic','google.fr','q'],
51
- ['_addOrganic','google.nl','q'],
52
- ['_addOrganic','google.be','q'],
53
- ['_addOrganic','google.de','q'],
54
- ['_addOrganic','google.no','q'],
55
- ['_addOrganic','google.se','q'],
56
- ['_addOrganic','google.dk','q'],
57
- ['_addOrganic','google.fi','q'],
58
- ['_addOrganic','google.ch','q'],
59
- ['_addOrganic','google.at','q'],
60
- ['_addOrganic','google.ie','q'],
61
- ['_addOrganic','google.ru','q'],
62
- ['_addOrganic','google.pl','q']
63
- );
64
-
65
- // Yahoo EMEA Domains
66
- _gaq.push(
67
- ['_addOrganic','uk.yahoo.com','p'],
68
- ['_addOrganic','es.yahoo.com','p'],
69
- ['_addOrganic','pt.yahoo.com','p'],
70
- ['_addOrganic','it.yahoo.com','p'],
71
- ['_addOrganic','fr.yahoo.com','p'],
72
- ['_addOrganic','nl.yahoo.com','p'],
73
- ['_addOrganic','be.yahoo.com','p'],
74
- ['_addOrganic','de.yahoo.com','p'],
75
- ['_addOrganic','no.yahoo.com','p'],
76
- ['_addOrganic','se.yahoo.com','p'],
77
- ['_addOrganic','dk.yahoo.com','p'],
78
- ['_addOrganic','fi.yahoo.com','p'],
79
- ['_addOrganic','ch.yahoo.com','p'],
80
- ['_addOrganic','at.yahoo.com','p'],
81
- ['_addOrganic','ie.yahoo.com','p'],
82
- ['_addOrganic','ru.yahoo.com','p'],
83
- ['_addOrganic','pl.yahoo.com','p']
84
- );
85
-
86
- // UK specific
87
- _gaq.push(
88
- ['_addOrganic','hotbot.co.uk','query'],
89
- ['_addOrganic','excite.co.uk','q'],
90
- ['_addOrganic','bbc','q'],
91
- ['_addOrganic','tiscali','query'],
92
- ['_addOrganic','uk.ask.com','q'],
93
- ['_addOrganic','blueyonder','q'],
94
- ['_addOrganic','search.aol.co.uk','query'],
95
- ['_addOrganic','ntlworld','q'],
96
- ['_addOrganic','tesco.net','q'],
97
- ['_addOrganic','orange.co.uk','q'],
98
- ['_addOrganic','mywebsearch.com','searchfor'],
99
- ['_addOrganic','uk.myway.com','searchfor'],
100
- ['_addOrganic','searchy.co.uk','search_term'],
101
- ['_addOrganic','msn.co.uk','q'],
102
- ['_addOrganic','uk.altavista.com','q'],
103
- ['_addOrganic','lycos.co.uk','query']
104
- );
105
-
106
- // NL specific
107
- _gaq.push(
108
- ['_addOrganic','chello.nl','q1'],
109
- ['_addOrganic','home.nl','q'],
110
- ['_addOrganic','planet.nl','googleq=q'],
111
- ['_addOrganic','search.ilse.nl','search_for'],
112
- ['_addOrganic','search-dyn.tiscali.nl','key'],
113
- ['_addOrganic','startgoogle.startpagina.nl','q'],
114
- ['_addOrganic','vinden.nl','q'],
115
- ['_addOrganic','vindex.nl','search_for'],
116
- ['_addOrganic','zoeken.nl','query'],
117
- ['_addOrganic','zoeken.track.nl','qr'],
118
- ['_addOrganic','zoeknu.nl','Keywords']
119
- );
120
-
121
- // Extras
122
- _gaq.push(
123
- ['_addOrganic','alltheweb','q'],
124
- ['_addOrganic','ananzi','qt'],
125
- ['_addOrganic','anzwers','search'],
126
- ['_addOrganic','araby.com','q'],
127
- ['_addOrganic','dogpile','q'],
128
- ['_addOrganic','elmundo.es','q'],
129
- ['_addOrganic','ezilon.com','q'],
130
- ['_addOrganic','hotbot','query'],
131
- ['_addOrganic','indiatimes.com','query'],
132
- ['_addOrganic','iafrica.funnel.co.za','q'],
133
- ['_addOrganic','mywebsearch.com','searchfor'],
134
- ['_addOrganic','rambler.ru','words'],
135
- ['_addOrganic','search.aol.com','encquery'],
136
- ['_addOrganic','search.indiatimes.com','query'],
137
- ['_addOrganic','searcheurope.com','query'],
138
- ['_addOrganic','suche.web.de','su'],
139
- ['_addOrganic','terra.es','query'],
140
- ['_addOrganic','voila.fr','kw']
141
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/class-frontend.php CHANGED
@@ -1,663 +1,226 @@
1
  <?php
2
-
3
  /**
4
- * Code that actually inserts stuff into pages.
5
  */
6
- if ( !class_exists( 'GA_Filter' ) ) {
7
- class GA_Filter {
8
-
9
- var $options = array();
10
-
11
- function __construct() {
12
- $this->options = get_option( 'Yoast_Google_Analytics' );
13
-
14
- if ( !is_array( $this->options ) ) {
15
- $this->options = get_option( 'GoogleAnalyticsPP' );
16
- if ( !is_array( $this->options ) )
17
- return;
18
- }
19
-
20
- if ( !isset( $this->options['uastring'] ) || $this->options['uastring'] == '' ) {
21
- add_action( 'wp_head', array( $this, 'not_shown_error' ) );
22
- } else {
23
- if ( isset( $this->options['allowanchor'] ) && $this->options['allowanchor'] ) {
24
- add_action( 'init', array( $this, 'utm_hashtag_redirect' ), 1 );
25
- }
26
-
27
- if ( ( isset( $this->options['trackoutbound'] ) && $this->options['trackoutbound'] ) ||
28
- ( isset( $this->options['trackcrossdomain'] ) && $this->options['trackcrossdomain'] )
29
- ) {
30
- // filters alter the existing content
31
- add_filter( 'the_content', array( $this, 'the_content' ), 99 );
32
- add_filter( 'widget_text', array( $this, 'widget_content' ), 99 );
33
- add_filter( 'the_excerpt', array( $this, 'the_content' ), 99 );
34
- add_filter( 'comment_text', array( $this, 'comment_text' ), 99 );
35
- add_filter( 'get_bookmarks', array( $this, 'bookmarks' ), 99 );
36
- add_filter( 'get_comment_author_link', array( $this, 'comment_author_link' ), 99 );
37
- add_filter( 'wp_nav_menu', array( $this, 'nav_menu' ), 99 );
38
- }
39
-
40
- if ( $this->options["trackcommentform"] ) {
41
- global $comment_form_id;
42
- $comment_form_id = 'commentform';
43
 
44
- add_action( 'comment_form_after', array( $this, 'track_comment_form' ) );
45
- add_action( 'wp_print_scripts', array( $this, 'track_comment_form_head' ) );
46
- add_filter( 'comment_form_defaults', array( $this, 'get_comment_form_id' ), 99, 1 );
47
- }
48
 
49
- if ( isset( $this->options['trackadsense'] ) && $this->options['trackadsense'] )
50
- add_action( 'wp_head', array( $this, 'spool_adsense' ), 1 );
51
 
52
- if ( !isset( $this->options['position'] ) )
53
- $this->options['position'] = 'header';
54
 
55
- switch ( $this->options['position'] ) {
56
- case 'manual':
57
- // No need to insert here, bail NOW.
58
- break;
59
- case 'header':
60
- default:
61
- add_action( 'wp_head', array( $this, 'spool_analytics' ), 2 );
62
- break;
63
- }
64
 
65
- if ( isset( $this->options['trackregistration'] ) && $this->options['trackregistration'] )
66
- add_action( 'login_head', array( $this, 'spool_analytics' ), 20 );
 
67
 
68
- if ( isset( $this->options['rsslinktagging'] ) && $this->options['rsslinktagging'] )
69
- add_filter( 'the_permalink_rss', array( $this, 'rsslinktagger' ), 99 );
 
 
 
70
  }
71
  }
72
 
73
- function not_shown_error() {
74
- if ( current_user_can( 'manage_options' ) )
75
- echo "<!-- " . __( "Google Analytics tracking code not shown because you haven't setup Google Analytics for WordPress yet.", "gawp" ) . " -->\n";
76
  }
77
 
78
- function do_tracking() {
 
 
 
 
79
  global $current_user;
 
80
 
81
  get_currentuserinfo();
82
 
83
- if ( 0 == $current_user->ID )
84
  return true;
85
-
86
- if ( ( $current_user->user_level >= $this->options["ignore_userlevel"] ) )
87
- return false;
88
- else
89
- return true;
90
- }
91
-
92
- /**
93
- * If setAllowAnchor is set to true, GA ignores all links tagged "normally", so we redirect all "normally" tagged URL's
94
- * to one tagged with a hash.
95
- */
96
- function utm_hashtag_redirect() {
97
- if ( isset( $_SERVER['REQUEST_URI'] ) ) {
98
- if ( strpos( $_SERVER['REQUEST_URI'], "utm_" ) !== false ) {
99
- $url = 'http://';
100
- if ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] != "" ) {
101
- $url = 'https://';
102
- }
103
- $url .= $_SERVER['SERVER_NAME'];
104
- if ( strpos( $_SERVER['REQUEST_URI'], "?utm_" ) !== false ) {
105
- $url .= str_replace( "?utm_", "#utm_", $_SERVER['REQUEST_URI'] );
106
- } else if ( strpos( $_SERVER['REQUEST_URI'], "&utm_" ) !== false ) {
107
- $url .= substr_replace( $_SERVER['REQUEST_URI'], "#utm_", strpos( $_SERVER['REQUEST_URI'], "&utm_" ), 5 );
108
- }
109
- wp_redirect( $url, 301 );
110
- exit;
111
- }
112
  }
113
- }
114
-
115
- /**
116
- * Cleans the variable to make it ready for storing in Google Analytics
117
- */
118
- function str_clean( $val ) {
119
- return remove_accents( str_replace( '---', '-', str_replace( ' ', '-', strtolower( html_entity_decode( $val ) ) ) ) );
120
- }
121
-
122
- /*
123
- * Insert the tracking code into the page
124
- */
125
- function spool_analytics() {
126
- global $wp_query, $current_user;
127
-
128
- // Make sure $current_user is filled.
129
- get_currentuserinfo();
130
-
131
- /**
132
- * The order of custom variables is very, very important: custom vars should always take up the same slot to make analysis easy.
133
- */
134
- $customvarslot = 1;
135
- if ( $this->do_tracking() && !is_preview() ) {
136
- $push = array();
137
-
138
- if ( $this->options['allowanchor'] )
139
- $push[] = "'_setAllowAnchor',true";
140
-
141
- if ( $this->options['allowlinker'] )
142
- $push[] = "'_setAllowLinker',true";
143
-
144
- if ( $this->options['anonymizeip'] )
145
- $push[] = "'_gat._anonymizeIp'";
146
-
147
- if ( isset( $this->options['domain'] ) && $this->options['domain'] != "" )
148
- $push[] = "'_setDomainName','" . $this->options['domain'] . "'";
149
-
150
- if ( isset( $this->options['trackcrossdomain'] ) && $this->options['trackcrossdomain'] )
151
- $push[] = "'_setDomainName','" . $this->options['primarycrossdomain'] . "'";
152
-
153
- if ( isset( $this->options['allowhash'] ) && $this->options['allowhash'] )
154
- $push[] = "'_setAllowHash',false";
155
-
156
- if ( $this->options['cv_loggedin'] ) {
157
- if ( $current_user && $current_user->ID != 0 )
158
- $push[] = "'_setCustomVar',$customvarslot,'logged-in','" . $current_user->roles[0] . "',1";
159
- // 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.
160
- $customvarslot++;
161
- }
162
 
163
- if ( function_exists( 'is_post_type_archive' ) && is_post_type_archive() ) {
164
- if ( $this->options['cv_post_type'] ) {
165
- $post_type = get_post_type();
166
- if ( $post_type ) {
167
- $push[] = "'_setCustomVar'," . $customvarslot . ",'post_type','" . $post_type . "',3";
168
- $customvarslot++;
169
- }
170
- }
171
- } else if ( is_singular() && !is_home() ) {
172
- if ( $this->options['cv_post_type'] ) {
173
- $post_type = get_post_type();
174
- if ( $post_type ) {
175
- $push[] = "'_setCustomVar'," . $customvarslot . ",'post_type','" . $post_type . "',3";
176
- $customvarslot++;
177
- }
178
- }
179
- if ( $this->options['cv_authorname'] ) {
180
- $push[] = "'_setCustomVar',$customvarslot,'author','" . $this->str_clean( get_the_author_meta( 'display_name', $wp_query->post->post_author ) ) . "',3";
181
- $customvarslot++;
182
- }
183
- if ( $this->options['cv_tags'] ) {
184
- $i = 0;
185
- if ( get_the_tags() ) {
186
- $tagsstr = '';
187
- foreach ( get_the_tags() as $tag ) {
188
- if ( $i > 0 )
189
- $tagsstr .= ' ';
190
- $tagsstr .= $tag->slug;
191
- $i++;
192
- }
193
- // Max 64 chars for value and label combined, hence 64 - 4
194
- $tagsstr = substr( $tagsstr, 0, 60 );
195
- $push[] = "'_setCustomVar',$customvarslot,'tags','" . $tagsstr . "',3";
196
- }
197
- $customvarslot++;
198
- }
199
- if ( is_singular() ) {
200
- if ( $this->options['cv_year'] ) {
201
- $push[] = "'_setCustomVar',$customvarslot,'year','" . get_the_time( 'Y' ) . "',3";
202
- $customvarslot++;
203
- }
204
- if ( $this->options['cv_category'] && is_single() ) {
205
- $cats = get_the_category();
206
- if ( is_array( $cats ) && isset( $cats[0] ) )
207
- $push[] = "'_setCustomVar',$customvarslot,'category','" . $cats[0]->slug . "',3";
208
- $customvarslot++;
209
- }
210
- if ( $this->options['cv_all_categories'] && is_single() ) {
211
- $i = 0;
212
- $catsstr = '';
213
- foreach ( (array) get_the_category() as $cat ) {
214
- if ( $i > 0 )
215
- $catsstr .= ' ';
216
- $catsstr .= $cat->slug;
217
- $i++;
218
- }
219
- // Max 64 chars for value and label combined, hence 64 - 10
220
- $catsstr = substr( $catsstr, 0, 54 );
221
- $push[] = "'_setCustomVar',$customvarslot,'categories','" . $catsstr . "',3";
222
- $customvarslot++;
223
- }
224
- }
225
- }
226
-
227
- $push = apply_filters( 'yoast-ga-custom-vars', $push, $customvarslot );
228
-
229
- $push = apply_filters( 'yoast-ga-push-before-pageview', $push );
230
-
231
- if ( is_404() ) {
232
- $push[] = "'_trackPageview','/404.html?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer";
233
- } else if ( $wp_query->is_search ) {
234
- $pushstr = "'_trackPageview','" . get_bloginfo( 'url' ) . "/?s=";
235
- if ( $wp_query->found_posts == 0 ) {
236
- $push[] = $pushstr . "no-results:" . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=no-results'";
237
- } else if ( $wp_query->found_posts == 1 ) {
238
- $push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=1-result'";
239
- } else if ( $wp_query->found_posts > 1 && $wp_query->found_posts < 6 ) {
240
- $push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=2-5-results'";
241
- } else {
242
- $push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=plus-5-results'";
243
- }
244
  } else {
245
- $push[] = "'_trackPageview'";
246
- }
247
-
248
- $push = apply_filters( 'yoast-ga-push-after-pageview', $push );
249
-
250
- if ( defined( 'WPSC_VERSION' ) && $this->options['wpec_tracking'] )
251
- $push = $this->wpec_transaction_tracking( $push );
252
-
253
- if ( $this->options['shopp_tracking'] ) {
254
- global $Shopp;
255
- if ( isset( $Shopp ) )
256
- $push = $this->shopp_transaction_tracking( $push );
257
  }
258
-
259
- $pushstr = "";
260
- foreach ( $push as $key ) {
261
- if ( !empty( $pushstr ) )
262
- $pushstr .= ",";
263
-
264
- $pushstr .= "[" . $key . "]";
265
- }
266
-
267
- if ( current_user_can( 'manage_options' ) && $this->options['firebuglite'] && $this->options['debug'] )
268
- echo '<script src="https://getfirebug.com/firebug-lite.js" type="text/javascript"></script>';
269
- ?>
270
-
271
- <script type="text/javascript">//<![CDATA[
272
- // Google Analytics for WordPress by Yoast v<?php echo GAWP_VERSION; ?> | http://yoast.com/wordpress/google-analytics/
273
- var _gaq = _gaq || [];
274
- _gaq.push(['_setAccount', '<?php echo trim( $this->options["uastring"] ); ?>']);
275
- <?php
276
- if ( $this->options["extrase"] ) {
277
- if ( !empty( $this->options["extraseurl"] ) ) {
278
- $url = $this->options["extraseurl"];
279
- } else {
280
- $url = GAWP_URL . 'custom_se_async.js';
281
- }
282
- echo '</script><script src="' . $url . '" type="text/javascript"></script>' . "\n" . '<script type="text/javascript">';
283
- }
284
-
285
- if ( ! empty( $this->options['customcode'] ) && trim( $this->options['customcode'] ) != '' )
286
- echo "\t" . stripslashes( $this->options['customcode'] ) . "\n";
287
- ?>
288
- _gaq.push(<?php echo $pushstr; ?>);
289
- (function () {
290
- var ga = document.createElement('script');
291
- ga.type = 'text/javascript';
292
- ga.async = true;
293
- ga.src = <?php
294
- if ( $this->options['gajslocalhosting'] && !empty( $this->options['gajsurl'] ) ) {
295
- echo "'" . $this->options['gajsurl'] . "'";
296
- } else {
297
- $script = 'ga.js';
298
- if ( current_user_can( 'manage_options' ) && $this->options['debug'] )
299
- $script = 'u/ga_debug.js';
300
- echo "('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/" . $script . "'";
301
- }
302
- ?>;
303
-
304
- var s = document.getElementsByTagName('script')[0];
305
- s.parentNode.insertBefore(ga, s);
306
- })();
307
- //]]></script>
308
- <?php
309
- } else if ( $this->options["uastring"] != "" ) {
310
- echo "<!-- " . sprintf( __( "Google Analytics tracking code not shown because users over level %s are ignored.", "gawp" ), $this->options["ignore_userlevel"] ) . " -->\n";
311
  }
312
  }
313
 
314
- /*
315
- * Insert the AdSense parameter code into the page. This'll go into the header per Google's instructions.
316
  */
317
- function spool_adsense() {
318
- if ( $this->do_tracking() && !is_preview() ) {
319
- echo '<script type="text/javascript">' . "\n";
320
- echo "\t" . 'window.google_analytics_uacct = "' . $this->options["uastring"] . '";' . "\n";
321
- echo '</script>' . "\n";
322
- }
323
- }
324
-
325
- function get_tracking_prefix() {
326
- return ( empty( $this->options['trackprefix'] ) ) ? '/yoast-ga/' : $this->options['trackprefix'];
327
  }
328
 
329
- function get_tracking_link( $prefix, $target, $jsprefix = 'javascript:' ) {
330
- if (
331
- ( $prefix == 'download' && $this->options['downloadspageview'] ) ||
332
- ( $prefix != 'download' && $this->options['outboundpageview'] )
333
- ) {
334
- $prefix = $this->get_tracking_prefix() . $prefix;
335
- $pushstr = "['_trackPageview','" . $prefix . "/" . esc_js( esc_url( $target ) ) . "']";
 
 
 
 
 
 
 
 
 
336
  } else {
337
- $pushstr = "['_trackEvent','" . $prefix . "','" . esc_js( esc_url( $target ) ) . "']";
338
  }
339
- return $jsprefix . "_gaq.push(" . $pushstr . ");";
340
- }
341
 
342
- function parse_link( $category, $matches ) {
343
- $origin = yoast_ga_get_domain( $_SERVER["HTTP_HOST"] );
344
-
345
- // Break out immediately if the link is not an http or https link.
346
- if ( strpos( $matches[2], "http" ) !== 0 ) {
347
- $target = false;
348
- } else if ( ( strpos( $matches[2], "mailto" ) === 0 ) ) {
349
- $target = 'email';
350
  } else {
351
- $target = yoast_ga_get_domain( $matches[3] );
352
- }
353
- $trackBit = "";
354
- $extension = substr( strrchr( $matches[3], '.' ), 1 );
355
- $dlextensions = explode( ",", str_replace( '.', '', $this->options['dlextensions'] ) );
356
- if ( $target ) {
357
- if ( $target == 'email' ) {
358
- $trackBit = $this->get_tracking_link( 'mailto', str_replace( 'mailto:', '', $matches[3] ), '' );
359
- } else if ( in_array( $extension, $dlextensions ) ) {
360
- $trackBit = $this->get_tracking_link( 'download', $matches[3], '' );
361
- } else if ( $target["domain"] != $origin["domain"] ) {
362
- $crossdomains = array();
363
- if ( isset( $this->options['othercrossdomains'] ) && !empty( $this->options['othercrossdomains'] ) )
364
- $crossdomains = explode( ',', str_replace( ' ', '', $this->options['othercrossdomains'] ) );
365
-
366
- if ( isset( $this->options['trackcrossdomain'] ) && $this->options['trackcrossdomain'] && in_array( $target["host"], $crossdomains ) ) {
367
- $trackBit = '_gaq.push([\'_link\', \'' . $matches[2] . '//' . $matches[3] . '\']); return false;"';
368
- } else if ( $this->options['trackoutbound'] && in_array( $this->options['domainorurl'], array( 'domain', 'url' ) ) ) {
369
- $url = $this->options['domainorurl'] == 'domain' ? $target["host"] : $matches[3];
370
- $trackBit = $this->get_tracking_link( $category, $url, '' );
371
- }
372
- } else if ( $target["domain"] == $origin["domain"] && isset( $this->options['internallink'] ) && $this->options['internallink'] != '' ) {
373
- $url = preg_replace( '|' . $origin["host"] . '|', '', $matches[3] );
374
- $extintlinks = explode( ',', $this->options['internallink'] );
375
- foreach ( $extintlinks as $link ) {
376
- if ( preg_match( '|^' . trim( $link ) . '|', $url, $match ) ) {
377
- $label = $this->options['internallinklabel'];
378
- if ( $label == '' )
379
- $label = 'int';
380
- $trackBit = $this->get_tracking_link( $category . '-' . $label, $url, '' );
381
- }
382
- }
383
- }
384
- }
385
- if ( $trackBit != "" ) {
386
- if ( preg_match( '/onclick=[\'\"](.*?)[\'\"]/i', $matches[4] ) > 0 ) {
387
- // Check for manually tagged outbound clicks, and replace them with the tracking of choice.
388
- if ( preg_match( '/.*_track(Pageview|Event).*/i', $matches[4] ) > 0 ) {
389
- $matches[4] = preg_replace( '/onclick=[\'\"](javascript:)?(.*;)?[a-zA-Z0-9]+\._track(Pageview|Event)\([^\)]+\)(;)?(.*)?[\'\"]/i', 'onclick="javascript:' . $trackBit . '$2$5"', $matches[4] );
390
- } else {
391
- $matches[4] = preg_replace( '/onclick=[\'\"](javascript:)?(.*?)[\'\"]/i', 'onclick="javascript:' . $trackBit . '$2"', $matches[4] );
392
- }
393
- } else {
394
- $matches[4] = 'onclick="javascript:' . $trackBit . '"' . $matches[4];
395
- }
396
- }
397
- return '<a ' . $matches[1] . 'href="' . $matches[2] . '//' . $matches[3] . '"' . ' ' . $matches[4] . '>' . $matches[5] . '</a>';
398
- }
399
-
400
- function parse_article_link( $matches ) {
401
- return $this->parse_link( 'outbound-article', $matches );
402
- }
403
-
404
- function parse_comment_link( $matches ) {
405
- return $this->parse_link( 'outbound-comment', $matches );
406
- }
407
-
408
- function parse_widget_link( $matches ) {
409
- return $this->parse_link( 'outbound-widget', $matches );
410
- }
411
-
412
- function parse_nav_menu( $matches ) {
413
- return $this->parse_link( 'outbound-menu', $matches );
414
- }
415
-
416
- function widget_content( $text ) {
417
- if ( !$this->do_tracking() )
418
- return $text;
419
- static $anchorPattern = '/<a (.*?)href=[\'\"](.*?)\/\/([^\'\"]+?)[\'\"](.*?)>(.*?)<\/a>/i';
420
- $text = preg_replace_callback( $anchorPattern, array( $this, 'parse_widget_link' ), $text );
421
- return $text;
422
- }
423
-
424
- function the_content( $text ) {
425
- if ( !$this->do_tracking() )
426
- return $text;
427
-
428
- if ( !is_feed() ) {
429
- static $anchorPattern = '/<a (.*?)href=[\'\"](.*?)\/\/([^\'\"]+?)[\'\"](.*?)>(.*?)<\/a>/i';
430
- $text = preg_replace_callback( $anchorPattern, array( $this, 'parse_article_link' ), $text );
431
- }
432
- return $text;
433
- }
434
-
435
- function nav_menu( $text ) {
436
- if ( !$this->do_tracking() )
437
- return $text;
438
-
439
- if ( !is_feed() ) {
440
- static $anchorPattern = '/<a (.*?)href=[\'\"](.*?)\/\/([^\'\"]+?)[\'\"](.*?)>(.*?)<\/a>/i';
441
- $text = preg_replace_callback( $anchorPattern, array( $this, 'parse_nav_menu' ), $text );
442
- }
443
- return $text;
444
- }
445
-
446
- function comment_text( $text ) {
447
- if ( !$this->do_tracking() )
448
- return $text;
449
-
450
- if ( !is_feed() ) {
451
- static $anchorPattern = '/<a (.*?)href="(.*?)\/\/(.*?)"(.*?)>(.*?)<\/a>/i';
452
- $text = preg_replace_callback( $anchorPattern, array( $this, 'parse_comment_link' ), $text );
453
- }
454
- return $text;
455
- }
456
-
457
- function comment_author_link( $text ) {
458
- if ( !$this->do_tracking() )
459
- return $text;
460
-
461
- static $anchorPattern = '/(.*\s+.*?href\s*=\s*)["\'](.*?)["\'](.*)/';
462
- preg_match( $anchorPattern, $text, $matches );
463
- if ( !isset( $matches[2] ) || $matches[2] == "" ) return $text;
464
-
465
- $trackBit = '';
466
- $target = yoast_ga_get_domain( $matches[2] );
467
- $origin = yoast_ga_get_domain( $_SERVER["HTTP_HOST"] );
468
- if ( $target["domain"] != $origin["domain"] ) {
469
- if ( isset( $this->options['domainorurl'] ) && $this->options['domainorurl'] == "domain" )
470
- $url = $target["host"];
471
- else
472
- $url = $matches[2];
473
- $trackBit = 'onclick="' . $this->get_tracking_link( 'outbound-commentauthor', $url ) . '"';
474
- }
475
- return $matches[1] . "\"" . $matches[2] . "\" " . $trackBit . " " . $matches[3];
476
- }
477
-
478
- function bookmarks( $bookmarks ) {
479
- if ( !$this->do_tracking() )
480
- return $bookmarks;
481
-
482
- $i = 0;
483
- while ( $i < count( $bookmarks ) ) {
484
- $target = yoast_ga_get_domain( $bookmarks[$i]->link_url );
485
- $sitedomain = yoast_ga_get_domain( get_bloginfo( 'url' ) );
486
- if ( $target['host'] == $sitedomain['host'] ) {
487
- $i++;
488
- continue;
489
- }
490
- if ( isset( $this->options['domainorurl'] ) && $this->options['domainorurl'] == "domain" )
491
- $url = $target["host"];
492
- else
493
- $url = $bookmarks[$i]->link_url;
494
- $trackBit = '" onclick="' . $this->get_tracking_link( 'outbound-blogroll', $url );
495
- $bookmarks[$i]->link_target .= $trackBit;
496
- $i++;
497
  }
498
- return $bookmarks;
499
  }
500
 
 
 
 
 
 
 
 
501
  function rsslinktagger( $guid ) {
502
  global $post;
503
  if ( is_feed() ) {
504
- if ( $this->options['allowanchor'] ) {
505
  $delimiter = '#';
506
  } else {
507
  $delimiter = '?';
508
- if ( strpos( $guid, $delimiter ) > 0 )
509
  $delimiter = '&amp;';
 
510
  }
 
511
  return $guid . $delimiter . 'utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=' . urlencode( $post->post_name );
512
  }
 
513
  return $guid;
514
  }
515
 
516
- function wpec_transaction_tracking( $push ) {
517
- global $wpdb, $purchlogs, $cart_log_id;
518
- if ( !isset( $cart_log_id ) || empty( $cart_log_id ) )
519
- return $push;
520
-
521
- $city = $wpdb->get_var( $wpdb->prepare( "SELECT tf.value
522
- FROM " . WPSC_TABLE_SUBMITED_FORM_DATA . " AS tf
523
- LEFT JOIN " . WPSC_TABLE_CHECKOUT_FORMS . " AS cf
524
- ON cf.id = tf.form_id
525
- WHERE cf.type = 'city'
526
- AND log_id = %s", $cart_log_id ) );
527
-
528
- $country = $wpdb->get_var( $wpdb->prepare( "SELECT tf.value
529
- FROM " . WPSC_TABLE_SUBMITED_FORM_DATA . " AS tf
530
- LEFT JOIN " . WPSC_TABLE_CHECKOUT_FORMS . " AS cf
531
- ON cf.id = tf.form_id
532
- WHERE cf.type = 'country'
533
- AND log_id = %s", $cart_log_id ) );
534
-
535
- $cart_items = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM " . WPSC_TABLE_CART_CONTENTS . " WHERE purchaseid = %s", $cart_log_id ), ARRAY_A );
536
-
537
- $total_shipping = $purchlogs->allpurchaselogs[0]->base_shipping;
538
- $total_tax = 0;
539
- foreach ( $cart_items as $item ) {
540
- $total_shipping += $item['pnp'];
541
- $total_tax += $item['tax_charged'];
542
- }
543
-
544
- $push[] = "'_addTrans','" . $cart_log_id . "'," // Order ID
545
- . "'" . $this->str_clean( get_bloginfo( 'name' ) ) . "'," // Store name
546
- . "'" . nzshpcrt_currency_display( $purchlogs->allpurchaselogs[0]->totalprice, 1, true, false, true ) . "'," // Total price
547
- . "'" . nzshpcrt_currency_display( $total_tax, 1, true, false, true ) . "'," // Tax
548
- . "'" . nzshpcrt_currency_display( $total_shipping, 1, true, false, true ) . "'," // Shipping
549
- . "'" . $city . "'," // City
550
- . "''," // State
551
- . "'" . $country . "'"; // Country
552
 
553
- foreach ( $cart_items as $item ) {
554
- $item['sku'] = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM " . WPSC_TABLE_PRODUCTMETA . " WHERE meta_key = 'sku' AND product_id = %s LIMIT 1", $item['prodid'] ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
555
 
556
- $item['category'] = $wpdb->get_var( $wpdb->prepare( "SELECT pc.name FROM " . WPSC_TABLE_PRODUCT_CATEGORIES . " AS pc LEFT JOIN " . WPSC_TABLE_ITEM_CATEGORY_ASSOC . " AS ca ON pc.id = ca.category_id WHERE pc.group_id = '1' AND ca.product_id = %s", $item['prodid'] ) );
557
- $push[] = "'_addItem',"
558
- . "'" . $cart_log_id . "'," // Order ID
559
- . "'" . $item['sku'] . "'," // Item SKU
560
- . "'" . str_replace( "'", "", $item['name'] ) . "'," // Item Name
561
- . "'" . $item['category'] . "'," // Item Category
562
- . "'" . $item['price'] . "'," // Item Price
563
- . "'" . $item['quantity'] . "'"; // Item Quantity
564
  }
565
- $push[] = "'_trackTrans'";
566
 
567
- return $push;
 
 
 
 
 
 
 
 
 
 
 
 
568
  }
569
 
570
- function shopp_transaction_tracking( $push ) {
571
- global $Shopp;
 
 
 
 
 
 
 
 
 
 
572
 
573
- // Only process if we're in the checkout process (receipt page)
574
- if ( version_compare( substr( SHOPP_VERSION, 0, 3 ), '1.1' ) >= 0 ) {
575
- // Only process if we're in the checkout process (receipt page)
576
- if ( function_exists( 'is_shopp_page' ) && !is_shopp_page( 'checkout' ) ) return $push;
577
- if ( empty( $Shopp->Order->purchase ) ) return $push;
578
 
579
- $Purchase = new Purchase( $Shopp->Order->purchase );
580
- $Purchase->load_purchased();
581
  } else {
582
- // For 1.0.x
583
- // Only process if we're in the checkout process (receipt page)
584
- if ( function_exists( 'is_shopp_page' ) && !is_shopp_page( 'checkout' ) ) return $push;
585
- // Only process if we have valid order data
586
- if ( !isset( $Shopp->Cart->data->Purchase ) ) return $push;
587
- if ( empty( $Shopp->Cart->data->Purchase->id ) ) return $push;
588
-
589
- $Purchase = $Shopp->Cart->data->Purchase;
590
- }
591
-
592
- $push[] = "'_addTrans',"
593
- . "'" . $Purchase->id . "'," // Order ID
594
- . "'" . $this->str_clean( get_bloginfo( 'name' ) ) . "'," // Store
595
- . "'" . number_format( $Purchase->total, 2 ) . "'," // Total price
596
- . "'" . number_format( $Purchase->tax, 2 ) . "'," // Tax
597
- . "'" . number_format( $Purchase->shipping, 2 ) . "'," // Shipping
598
- . "'" . $Purchase->city . "'," // City
599
- . "'" . $Purchase->state . "'," // State
600
- . "'.$Purchase->country.'"; // Country
601
-
602
- foreach ( $Purchase->purchased as $item ) {
603
- $sku = empty( $item->sku ) ? 'PID-' . $item->product . str_pad( $item->price, 4, '0', STR_PAD_LEFT ) : $item->sku;
604
- $push[] = "'_addItem',"
605
- . "'" . $Purchase->id . "',"
606
- . "'" . $sku . "',"
607
- . "'" . str_replace( "'", "", $item->name ) . "',"
608
- . "'" . $item->optionlabel . "',"
609
- . "'" . number_format( $item->unitprice, 2 ) . "',"
610
- . "'" . $item->quantity . "'";
611
  }
612
- $push[] = "'_trackTrans'";
613
- return $push;
614
  }
615
 
616
- function track_comment_form() {
617
- if ( !is_singular() )
618
- return;
619
-
620
- global $comment_form_id;
621
- ?>
622
- <script type="text/javascript">
623
- jQuery(document).ready(function () {
624
- jQuery('#<?php echo $comment_form_id; ?>').submit(function () {
625
- _gaq.push(
626
- ['_setAccount', '<?php echo $this->options["uastring"]; ?>'],
627
- ['_trackEvent', 'comment', 'submit']
628
- );
629
- });
630
- });
631
- </script>
632
- <?php
633
- }
634
-
635
- function track_comment_form_head() {
636
- if ( !is_singular() )
637
- return;
638
-
639
- global $post;
640
- if ( 'open' == $post->comment_status )
641
- wp_enqueue_script( 'jquery' );
642
- }
643
-
644
- function get_comment_form_id( $args ) {
645
- global $comment_form_id;
646
- $comment_form_id = $args['id_form'];
647
- return $args;
648
- }
649
-
650
- } // class GA_Filter
651
- } // endif
652
-
653
- $yoast_ga = new GA_Filter();
654
-
655
- function yoast_analytics() {
656
- global $yoast_ga;
657
- $options = get_option( 'Yoast_Google_Analytics' );
658
- if ( $options['position'] == 'manual' )
659
- $yoast_ga->spool_analytics();
660
- else
661
- echo '<!-- ' . __( 'Please set Google Analytics position to "manual" in the settings, or remove this call to yoast_analytics();', 'google-analytics-for-wordpress' ) . ' -->';
662
- }
663
-
1
  <?php
 
2
  /**
3
+ * The basic frontend class for the GA plugin, extendable for the children
4
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
+ if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
 
 
 
7
 
8
+ class Yoast_GA_Frontend {
 
9
 
10
+ public static $options = array();
 
11
 
12
+ public function __construct() {
13
+ self::$options = get_option( 'yst_ga' );
 
 
 
 
 
 
 
14
 
15
+ if ( isset( self::$options['ga_general']['tag_links_in_rss'] ) && self::$options['ga_general']['tag_links_in_rss'] == 1 ) {
16
+ add_filter( 'the_permalink_rss', array( $this, 'rsslinktagger' ), 99 );
17
+ }
18
 
19
+ // Check if the customer is running Universal or not (Enable in GA Settings -> Universal)
20
+ if ( isset( self::$options['ga_general']['enable_universal'] ) && self::$options['ga_general']['enable_universal'] == 1 ) {
21
+ require_once GAWP_PATH . 'frontend/class-universal.php';
22
+ } else {
23
+ require_once GAWP_PATH . 'frontend/class-ga-js.php';
24
  }
25
  }
26
 
27
+ public function get_options() {
28
+ return self::$options;
 
29
  }
30
 
31
+ /**
32
+ * Check if we need to show an actual tracking code
33
+ * @return bool
34
+ */
35
+ public static function do_tracking() {
36
  global $current_user;
37
+ $options = self::$options['ga_general'];
38
 
39
  get_currentuserinfo();
40
 
41
+ if ( 0 == $current_user->ID ) {
42
  return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
+ if ( isset( $options['ignore_users'] ) ) {
46
+ if ( in_array( $current_user->roles[0], $options['ignore_users'] ) ) {
47
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  } else {
49
+ return true;
 
 
 
 
 
 
 
 
 
 
 
50
  }
51
+ } else {
52
+ return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  }
54
  }
55
 
56
+ /**
57
+ * Hook a Google Analytics Javascript to track downloads and outbound links
58
  */
59
+ public function add_ga_javascript() {
60
+ wp_enqueue_script( 'yst_ga', GAWP_URL . 'frontend/js/yst_ga.js', array(), false, true );
 
 
 
 
 
 
 
 
61
  }
62
 
63
+ /**
64
+ * Parse the domain
65
+ *
66
+ * @param $uri
67
+ *
68
+ * @return array|bool
69
+ */
70
+ public function yoast_ga_get_domain( $uri ) {
71
+ $hostPattern = "/^(http:\/\/)?([^\/]+)/i";
72
+ $domainPatternUS = "/[^\.\/]+\.[^\.\/]+$/";
73
+ $domainPatternUK = "/[^\.\/]+\.[^\.\/]+\.[^\.\/]+$/";
74
+
75
+ preg_match( $hostPattern, $uri, $matches );
76
+ $host = $matches[2];
77
+ if ( preg_match( "/.*\..*\..*\..*$/", $host ) ) {
78
+ preg_match( $domainPatternUK, $host, $matches );
79
  } else {
80
+ preg_match( $domainPatternUS, $host, $matches );
81
  }
 
 
82
 
83
+ if ( isset( $matches[0] ) ) {
84
+ return array( "domain" => $matches[0], "host" => $host );
 
 
 
 
 
 
85
  } else {
86
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  }
 
88
  }
89
 
90
+ /**
91
+ * Add the UTM source parameters in the RSS feeds to track traffic
92
+ *
93
+ * @param $guid
94
+ *
95
+ * @return string
96
+ */
97
  function rsslinktagger( $guid ) {
98
  global $post;
99
  if ( is_feed() ) {
100
+ if ( self::$options['ga_general']['allow_anchor'] ) {
101
  $delimiter = '#';
102
  } else {
103
  $delimiter = '?';
104
+ if ( strpos( $guid, $delimiter ) > 0 ) {
105
  $delimiter = '&amp;';
106
+ }
107
  }
108
+
109
  return $guid . $delimiter . 'utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=' . urlencode( $post->post_name );
110
  }
111
+
112
  return $guid;
113
  }
114
 
115
+ /**
116
+ * Return the target with a lot of parameters
117
+ *
118
+ * @param $category
119
+ * @param $matches
120
+ *
121
+ * @return array
122
+ */
123
+ public function get_target( $category, $matches ) {
124
+ $protocol = $matches[2];
125
+ $original_url = $matches[3];
126
+ $domain = $this->yoast_ga_get_domain( $matches[3] );
127
+ $origin = $this->yoast_ga_get_domain( $_SERVER['HTTP_HOST'] );
128
+ $options = self::$options['ga_general'];
129
+ $download_extensions = explode( ",", str_replace( '.', '', $options['extensions_of_files'] ) );
130
+ $extension = substr( strrchr( $original_url, '.' ), 1 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
+ // Break out immediately if the link is not an http or https link.
133
+ if ( $protocol != 'http' && $protocol != 'https' && $protocol != 'mailto' ) {
134
+ $type = NULL;
135
+ } else {
136
+ if ( ( $protocol == 'mailto' ) ) {
137
+ $type = 'email';
138
+ } elseif ( in_array( $extension, $download_extensions ) ) {
139
+ $type = 'download';
140
+ } else {
141
+ if ( $domain['domain'] == $origin['domain'] ) {
142
+ $outlinks = explode( ',', $options['track_internal_as_outbound'] );
143
+
144
+ if ( count( $outlinks ) >= 1 ) {
145
+ foreach ( $outlinks as $out ) {
146
+ if ( strpos( $original_url, $domain['domain'] . $out ) !== false ) {
147
+ $type = 'internal-as-outbound';
148
+ }
149
+ }
150
+ }
151
 
152
+ if ( ! isset( $type ) ) {
153
+ $type = 'internal';
154
+ }
155
+ } elseif ( $domain['domain'] != $origin['domain'] ) {
156
+ $type = 'outbound';
157
+ }
158
+ }
 
159
  }
 
160
 
161
+ return array(
162
+ 'category' => $category,
163
+ 'type' => $type,
164
+ 'protocol' => $protocol,
165
+ 'domain' => $domain['domain'],
166
+ 'host' => $domain['host'],
167
+ 'origin_domain' => $origin['domain'],
168
+ 'origin_host' => $origin['host'],
169
+ 'extension' => $extension,
170
+ 'link_attributes' => rtrim( $matches[1] . ' ' . $matches[4] ),
171
+ 'link_text' => $matches[5],
172
+ 'original_url' => $original_url
173
+ );
174
  }
175
 
176
+ /**
177
+ * Merge the existing onclick with a new one and append it
178
+ *
179
+ * @param $link_attribute
180
+ * @param $onclick
181
+ *
182
+ * @return string
183
+ */
184
+ public function output_add_onclick( $link_attribute, $onclick ) {
185
+ if ( preg_match( '/onclick=[\'\"](.*?;)[\'\"]/i', $link_attribute, $matches ) > 0 ) {
186
+ $js_snippet_single = "onclick='" . $matches[1] . " " . $onclick . "'";
187
+ $js_snippet_double = 'onclick="' . $matches[1] . ' ' . $onclick . '"';
188
 
189
+ $link_attribute = str_replace( 'onclick="' . $matches[1] . '"', $js_snippet_double, $link_attribute );
190
+ $link_attribute = str_replace( "onclick='" . $matches[1] . "'", $js_snippet_single, $link_attribute );
 
 
 
191
 
192
+ return $link_attribute;
 
193
  } else {
194
+ if ( ! is_null( $onclick ) ) {
195
+ return 'onclick="' . $onclick . '"';
196
+ } else {
197
+ return "";
198
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  }
 
 
200
  }
201
 
202
+ /**
203
+ * Generate the full URL
204
+ *
205
+ * @param $link
206
+ *
207
+ * @return string
208
+ */
209
+ public function make_full_url( $link ) {
210
+ switch ( $link['type'] ) {
211
+ case "download":
212
+ case "internal":
213
+ case "internal-as-outbound":
214
+ case "outbound":
215
+ return $link['protocol'] . '://' . $link['original_url'];
216
+ break;
217
+ case "email":
218
+ return 'mailto:' . $link['original_url'];
219
+ break;
220
+ }
221
+ }
222
+ }
223
+
224
+ global $yoast_ga_frontend;
225
+ $yoast_ga_frontend = new Yoast_GA_Frontend;
226
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/class-ga-js.php ADDED
@@ -0,0 +1,306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The frontend JS class
4
+ */
5
+
6
+ if ( ! class_exists( 'Yoast_GA_JS' ) ) {
7
+
8
+ class Yoast_GA_JS extends Yoast_GA_Frontend {
9
+ public $link_regex;
10
+
11
+ public function __construct() {
12
+ $this->link_regex = '/<a (.*?)href=[\'\"](.*?):\/*([^\'\"]+?)[\'\"](.*?)>(.*?)<\/a>/i';
13
+
14
+ add_action( 'wp_head', array( $this, 'tracking' ), 8 );
15
+
16
+ // Check for outbound
17
+ add_filter( 'the_content', array( $this, 'the_content' ), 99 );
18
+ add_filter( 'widget_text', array( $this, 'widget_content' ), 99 );
19
+ add_filter( 'the_excerpt', array( $this, 'the_content' ), 99 );
20
+ add_filter( 'comment_text', array( $this, 'comment_text' ), 99 );
21
+ }
22
+
23
+ /**
24
+ * Function to output the GA Tracking code in the wp_head()
25
+ *
26
+ * @todo, add the tracking code and remove this test output
27
+ */
28
+ public function tracking() {
29
+ global $wp_query, $current_user;
30
+
31
+ // Make sure $current_user is filled.
32
+ get_currentuserinfo();
33
+
34
+ $options = parent::$options['ga_general'];
35
+ $gaq_push = array();
36
+
37
+ /**
38
+ * The order of custom variables is very, very important: custom vars should always take up the same slot to make analysis easy.
39
+ */
40
+ $customvarslot = 1;
41
+ if ( parent::do_tracking() && ! is_preview() ) {
42
+ $gaq_push = array();
43
+
44
+ if ( isset( $options['subdomain_tracking'] ) && $options['subdomain_tracking'] != "" ) {
45
+ $domain = $options['subdomain_tracking'];
46
+ } else {
47
+ $domain = NULL; // Default domain value
48
+ }
49
+
50
+ if ( ! isset( $options['allowanchor'] ) ) {
51
+ $options['allowanchor'] = false;
52
+ }
53
+
54
+ $ua_code = '';
55
+ if ( ! empty( $options['analytics_profile'] ) ) {
56
+ $ua_code = $options['analytics_profile'];
57
+ }
58
+
59
+ if ( ! empty( $options['manual_ua_code_field'] ) && ! empty( $options['manual_ua_code'] ) ) {
60
+ $ua_code = $options['manual_ua_code_field'];
61
+ }
62
+
63
+ $gaq_push[] = "'_setAccount', '" . $ua_code . "'";
64
+
65
+ if ( ! is_null( $domain ) ) {
66
+ $gaq_push[] = "'_setDomainName', '" . $domain . "'";
67
+ }
68
+
69
+ if ( $options['add_allow_linker'] && ! $options['allowanchor'] ) {
70
+ $gaq_push[] = "'_setAllowAnchor', true";
71
+ }
72
+
73
+ // @todo, check for AllowLinker in GA.js? Universal only?
74
+
75
+ // SSL data
76
+ $gaq_push[] = "'_gat._forceSSL'";
77
+
78
+ // Anonymous data
79
+ if ( $options['anonymize_ips'] == 1 ) {
80
+ $gaq_push[] = "'_gat._anonymizeIp'";
81
+ }
82
+
83
+ if ( isset( $options['allowhash'] ) && $options['allowhash'] ) {
84
+ $gaq_push[] = "'_gat._anonymizeIp',true";
85
+ }
86
+
87
+ if ( is_404() ) {
88
+ $gaq_push[] = "'send','pageview','/404.html?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer";
89
+ } else {
90
+ if ( $wp_query->is_search ) {
91
+ $pushstr = "'send','pageview','/?s=";
92
+ if ( $wp_query->found_posts == 0 ) {
93
+ $gaq_push[] = $pushstr . "no-results:" . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=no-results'";
94
+ } else {
95
+ if ( $wp_query->found_posts == 1 ) {
96
+ $gaq_push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=1-result'";
97
+ } else {
98
+ if ( $wp_query->found_posts > 1 && $wp_query->found_posts < 6 ) {
99
+ $gaq_push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=2-5-results'";
100
+ } else {
101
+ $gaq_push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=plus-5-results'";
102
+ }
103
+ }
104
+ }
105
+ } else {
106
+ $gaq_push[] = "'send','pageview'";
107
+ }
108
+ }
109
+
110
+ //$push = apply_filters( 'yoast-ga-push-after-pageview', $push );
111
+ $ga_settings = $options; // Assign the settings to the javascript include view
112
+
113
+ // Include the tracking view
114
+ if ( $options['debug_mode'] == 1 ) {
115
+ require( GAWP_PATH . 'frontend/views/tracking_debug.php' );
116
+ } else {
117
+ require( GAWP_PATH . 'frontend/views/tracking_ga_js.php' );
118
+ }
119
+ }
120
+ else{
121
+ require( GAWP_PATH . 'frontend/views/tracking_usergroup.php' );
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Get tracking prefix
127
+ *
128
+ * @return string
129
+ */
130
+ public function get_tracking_prefix() {
131
+ return ( empty( $this->options['trackprefix'] ) ) ? '/yoast-ga/' : $this->options['trackprefix'];
132
+ }
133
+
134
+ /**
135
+ * Ouput tracking link
136
+ *
137
+ * @param $link
138
+ *
139
+ * @return mixed
140
+ */
141
+ private function output_parse_link( $link ) {
142
+ $onclick = NULL;
143
+ $options = $this->get_options();
144
+ $options = $options['ga_general'];
145
+ $full_url = $this->make_full_url( $link );
146
+
147
+ switch ( $link['type'] ) {
148
+ case 'download':
149
+ if ( $options['track_download_as'] == 'pageview' ) {
150
+ $onclick = "_gaq.push(['_trackPageview','download/" . esc_js( $full_url ) . "']);";
151
+ } else {
152
+ $onclick = "_gaq.push(['_trackEvent','download/" . esc_js( $full_url ) . "']);";
153
+ }
154
+
155
+ break;
156
+ case 'email':
157
+ $onclick = "_gaq.push(['_trackEvent','mailto','" . esc_js( $link['original_url'] ) . "']);";
158
+
159
+ break;
160
+ case 'internal-as-outbound':
161
+ if ( ! is_null( $options['track_internal_as_label'] ) ) {
162
+ $label = $options['track_internal_as_label'];
163
+ } else {
164
+ $label = 'int';
165
+ }
166
+
167
+ $onclick = "_gaq.push(['_trackEvent', '" . $link['category'] . "-" . $label . "', '" . $full_url . "', '" . $link['link_text'] . "']);";
168
+
169
+ break;
170
+ case 'internal':
171
+ $onclick = NULL;
172
+
173
+ break;
174
+ case 'outbound':
175
+ if ( $options['track_outbound'] == 1 ) {
176
+ $onclick = "_gaq.push(['_trackEvent', '" . $link['category'] . "', '" . $full_url . "', '" . $link['link_text'] . "']);";
177
+ }
178
+
179
+ break;
180
+ }
181
+
182
+ $link['link_attributes'] = $this->output_add_onclick( $link['link_attributes'], $onclick );
183
+
184
+ return '<a href="' . $full_url . '" ' . $link['link_attributes'] . '>' . $link['link_text'] . '</a>';
185
+ }
186
+
187
+ /**
188
+ * Parse article link
189
+ *
190
+ * @param $matches
191
+ *
192
+ * @return mixed
193
+ */
194
+ public function parse_article_link( $matches ) {
195
+ return $this->output_parse_link( $this->get_target( 'outbound-article', $matches ) );
196
+ }
197
+
198
+ /**
199
+ * Parse comment link
200
+ *
201
+ * @param $matches
202
+ *
203
+ * @return mixed
204
+ */
205
+ public function parse_comment_link( $matches ) {
206
+ return $this->output_parse_link( $this->get_target( 'outbound-comment', $matches ) );
207
+ }
208
+
209
+ /**
210
+ * Parse widget link
211
+ *
212
+ * @param $matches
213
+ *
214
+ * @return mixed
215
+ */
216
+ public function parse_widget_link( $matches ) {
217
+ return $this->output_parse_link( $this->get_target( 'outbound-widget', $matches ) );
218
+ }
219
+
220
+ /**
221
+ * Parse menu link
222
+ *
223
+ * @param $matches
224
+ *
225
+ * @return mixed
226
+ */
227
+ public function parse_nav_menu( $matches ) {
228
+ return $this->output_parse_link( $this->get_target( 'outbound-menu', $matches ) );
229
+ }
230
+
231
+ /**
232
+ * Parse the_content or the_excerpt for links
233
+ *
234
+ * @param $text
235
+ *
236
+ * @return mixed
237
+ */
238
+ public function the_content( $text ) {
239
+ if ( false == $this->do_tracking() ) {
240
+ return $text;
241
+ }
242
+
243
+ if ( ! is_feed() ) {
244
+ $text = preg_replace_callback( $this->link_regex, array( $this, 'parse_article_link' ), $text );
245
+ }
246
+
247
+ return $text;
248
+ }
249
+
250
+ /**
251
+ * Parse the widget content for links
252
+ *
253
+ * @param $text
254
+ *
255
+ * @return mixed
256
+ */
257
+ public function widget_content( $text ) {
258
+ if ( ! $this->do_tracking() ) {
259
+ return $text;
260
+ }
261
+ $text = preg_replace_callback( $this->link_regex, array( $this, 'parse_widget_link' ), $text );
262
+
263
+ return $text;
264
+ }
265
+
266
+ /**
267
+ * Parse the nav menu for links
268
+ *
269
+ * @param $text
270
+ *
271
+ * @return mixed
272
+ */
273
+ public function nav_menu( $text ) {
274
+ if ( ! $this->do_tracking() )
275
+ return $text;
276
+
277
+ if ( ! is_feed() ) {
278
+ $text = preg_replace_callback( $this->link_regex, array( $this, 'parse_nav_menu' ), $text );
279
+ }
280
+
281
+ return $text;
282
+ }
283
+
284
+ /**
285
+ * Parse comment text for links
286
+ *
287
+ * @param $text
288
+ *
289
+ * @return mixed
290
+ */
291
+ public function comment_text( $text ) {
292
+ if ( ! $this->do_tracking() )
293
+ return $text;
294
+
295
+ if ( ! is_feed() ) {
296
+ $text = preg_replace_callback( $this->link_regex, array( $this, 'parse_comment_link' ), $text );
297
+ }
298
+
299
+ return $text;
300
+ }
301
+
302
+ }
303
+
304
+ global $yoast_ga_js;
305
+ $yoast_ga_js = new Yoast_GA_JS;
306
+ }
frontend/class-universal.php ADDED
@@ -0,0 +1,306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is the frontend class for the GA Universal code
4
+ */
5
+
6
+ if ( ! class_exists( 'Yoast_GA_Universal' ) ) {
7
+
8
+ class Yoast_GA_Universal extends Yoast_GA_Frontend {
9
+ public $link_regex;
10
+
11
+ public function __construct() {
12
+ $this->link_regex = '/<a (.*?)href=[\'\"](.*?):\/*([^\'\"]+?)[\'\"](.*?)>(.*?)<\/a>/i';
13
+
14
+ add_action( 'wp_head', array( $this, 'tracking' ), 8 );
15
+
16
+ // Check for outbound option
17
+ add_filter( 'the_content', array( $this, 'the_content' ), 99 );
18
+ add_filter( 'widget_text', array( $this, 'widget_content' ), 99 );
19
+ add_filter( 'the_excerpt', array( $this, 'the_content' ), 99 );
20
+ add_filter( 'comment_text', array( $this, 'comment_text' ), 99 );
21
+ }
22
+
23
+ /**
24
+ * Function to output the GA Tracking code in the wp_head()
25
+ *
26
+ * @todo, add the tracking code and remove this test output
27
+ */
28
+ public function tracking() {
29
+ global $wp_query, $current_user;
30
+
31
+ // Make sure $current_user is filled.
32
+ get_currentuserinfo();
33
+
34
+ $options = parent::$options['ga_general'];
35
+ $gaq_push = array();
36
+
37
+ /**
38
+ * The order of custom variables is very, very important: custom vars should always take up the same slot to make analysis easy.
39
+ */
40
+ $customvarslot = 1;
41
+ if ( $this->do_tracking() && ! is_preview() ) {
42
+ $gaq_push = array();
43
+
44
+ if ( isset( $options['subdomain_tracking'] ) && $options['subdomain_tracking'] != "" ) {
45
+ $domain = $options['subdomain_tracking'];
46
+ } else {
47
+ $domain = 'auto'; // Default domain value
48
+ }
49
+
50
+ if ( ! isset( $options['allowanchor'] ) ) {
51
+ $options['allowanchor'] = false;
52
+ }
53
+
54
+ $ua_code = '';
55
+ if ( ! empty( $options['analytics_profile'] ) ) {
56
+ $ua_code = $options['analytics_profile'];
57
+ }
58
+
59
+ if ( ! empty( $options['manual_ua_code_field'] ) && ! empty( $options['manual_ua_code'] ) ) {
60
+ $ua_code = $options['manual_ua_code_field'];
61
+ }
62
+
63
+ // Set tracking code here
64
+ if ( ! empty( $ua_code ) ) {
65
+ if ( $options['add_allow_linker'] && ! $options['allowanchor'] ) {
66
+ $gaq_push[] = "'create', '" . $ua_code . "', '" . $domain . "', {'allowLinker': true}";
67
+ } else {
68
+ if ( $options['allowanchor'] && ! $options['add_allow_linker'] ) {
69
+ $gaq_push[] = "'create', '" . $ua_code . "', '" . $domain . "', {'allowAnchor': true}";
70
+ } else {
71
+ if ( $options['allowanchor'] && $options['add_allow_linker'] ) {
72
+ $gaq_push[] = "'create', '" . $ua_code . "', '" . $domain . "', {'allowAnchor': true, 'allowLinker': true}";
73
+ } else {
74
+ $gaq_push[] = "'create', '" . $ua_code . "', '" . $domain . "'";
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ $gaq_push[] = "'set', 'forceSSL', true";
81
+
82
+ // Anonymous data
83
+ if ( $options['anonymize_ips'] == 1 ) {
84
+ $gaq_push[] = "'set', 'anonymizeIp', true";
85
+ }
86
+
87
+ // add demographics
88
+ if ( $options['demographics'] ) {
89
+ $gaq_push[] = "'require', 'displayfeatures'";
90
+ }
91
+
92
+ if ( isset( $options['allowhash'] ) && $options['allowhash'] ) {
93
+ $gaq_push[] = "'_setAllowHash',false";
94
+ }
95
+
96
+ if ( is_404() ) {
97
+ $gaq_push[] = "'send','pageview','/404.html?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer";
98
+ } else {
99
+ if ( $wp_query->is_search ) {
100
+ $pushstr = "'send','pageview','/?s=";
101
+ if ( $wp_query->found_posts == 0 ) {
102
+ $gaq_push[] = $pushstr . "no-results:" . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=no-results'";
103
+ } else {
104
+ if ( $wp_query->found_posts == 1 ) {
105
+ $gaq_push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=1-result'";
106
+ } else {
107
+ if ( $wp_query->found_posts > 1 && $wp_query->found_posts < 6 ) {
108
+ $gaq_push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=2-5-results'";
109
+ } else {
110
+ $gaq_push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=plus-5-results'";
111
+ }
112
+ }
113
+ }
114
+ } else {
115
+ $gaq_push[] = "'send','pageview'";
116
+ }
117
+ }
118
+
119
+ //$push = apply_filters( 'yoast-ga-push-after-pageview', $push );
120
+ $ga_settings = $options; // Assign the settings to the javascript include view
121
+
122
+ // Include the tracking view
123
+ if ( $options['debug_mode'] == 1 ) {
124
+ require( GAWP_PATH . 'frontend/views/tracking_debug.php' );
125
+ } else {
126
+ require( GAWP_PATH . 'frontend/views/tracking_universal.php' );
127
+ }
128
+ }
129
+ else{
130
+ require( GAWP_PATH . 'frontend/views/tracking_usergroup.php' );
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Ouput tracking link
136
+ *
137
+ * @param $link
138
+ *
139
+ * @return mixed
140
+ */
141
+ private function output_parse_link( $link ) {
142
+ $onclick = NULL;
143
+ $options = $this->get_options();
144
+ $options = $options['ga_general'];
145
+ $full_url = $this->make_full_url( $link );
146
+
147
+ switch ( $link['type'] ) {
148
+ case 'download':
149
+ if ( $options['track_download_as'] == 'pageview' ) {
150
+ $onclick = "ga('send', 'pageview', '" . esc_js( $full_url ) . "');";
151
+ } else {
152
+ $onclick = "ga('send', 'event', 'download', '" . esc_js( $full_url ) . "');";
153
+ }
154
+
155
+ break;
156
+ case 'email':
157
+ $onclick = "ga('send', 'event', 'mailto', '" . esc_js( $link['original_url'] ) . "');";
158
+
159
+ break;
160
+ case 'internal-as-outbound':
161
+ if ( ! is_null( $options['track_internal_as_label'] ) ) {
162
+ $label = $options['track_internal_as_label'];
163
+ } else {
164
+ $label = 'int';
165
+ }
166
+
167
+ $onclick = "ga('send', 'event', '" . $link['category'] . "-" . $label . "', '" . esc_js( $full_url ) . "', '" . esc_js( $link['link_text'] ) . "');";
168
+
169
+ break;
170
+ case 'internal':
171
+ $onclick = NULL;
172
+
173
+ break;
174
+ case 'outbound':
175
+ if ( $options['track_outbound'] == 1 ) {
176
+ $onclick = "ga('send', 'event', '" . $link['category'] . "', '" . esc_js( $full_url ) . "', '" . esc_js( $link['link_text'] ) . "');";
177
+ }
178
+
179
+ break;
180
+ }
181
+
182
+ $link['link_attributes'] = $this->output_add_onclick( $link['link_attributes'], $onclick );
183
+
184
+ return '<a href="' . $full_url . '" ' . $link['link_attributes'] . '>' . $link['link_text'] . '</a>';
185
+
186
+ }
187
+
188
+ /**
189
+ * Parse article link
190
+ *
191
+ * @param $matches
192
+ *
193
+ * @return mixed
194
+ */
195
+ public function parse_article_link( $matches ) {
196
+ return $this->output_parse_link( $this->get_target( 'outbound-article', $matches ) );
197
+ }
198
+
199
+ /**
200
+ * Parse comment link
201
+ *
202
+ * @param $matches
203
+ *
204
+ * @return mixed
205
+ */
206
+ public function parse_comment_link( $matches ) {
207
+ return $this->output_parse_link( $this->get_target( 'outbound-comment', $matches ) );
208
+ }
209
+
210
+ /**
211
+ * Parse widget link
212
+ *
213
+ * @param $matches
214
+ *
215
+ * @return mixed
216
+ */
217
+ public function parse_widget_link( $matches ) {
218
+ return $this->output_parse_link( $this->get_target( 'outbound-widget', $matches ) );
219
+ }
220
+
221
+ /**
222
+ * Parse menu link
223
+ *
224
+ * @param $matches
225
+ *
226
+ * @return mixed
227
+ */
228
+ public function parse_nav_menu( $matches ) {
229
+ return $this->output_parse_link( $this->get_target( 'outbound-menu', $matches ) );
230
+ }
231
+
232
+ /**
233
+ * Parse the_content or the_excerpt for links
234
+ *
235
+ * @param $text
236
+ *
237
+ * @return mixed
238
+ */
239
+ public function the_content( $text ) {
240
+ if ( false == $this->do_tracking() ) {
241
+ return $text;
242
+ }
243
+
244
+ if ( ! is_feed() ) {
245
+ $text = preg_replace_callback( $this->link_regex, array( $this, 'parse_article_link' ), $text );
246
+ }
247
+
248
+ return $text;
249
+ }
250
+
251
+ /**
252
+ * Parse the widget content for links
253
+ *
254
+ * @param $text
255
+ *
256
+ * @return mixed
257
+ */
258
+ public function widget_content( $text ) {
259
+ if ( ! $this->do_tracking() ) {
260
+ return $text;
261
+ }
262
+ $text = preg_replace_callback( $this->link_regex, array( $this, 'parse_widget_link' ), $text );
263
+
264
+ return $text;
265
+ }
266
+
267
+ /**
268
+ * Parse the nav menu for links
269
+ *
270
+ * @param $text
271
+ *
272
+ * @return mixed
273
+ */
274
+ public function nav_menu( $text ) {
275
+ if ( ! $this->do_tracking() )
276
+ return $text;
277
+
278
+ if ( ! is_feed() ) {
279
+ $text = preg_replace_callback( $this->link_regex, array( $this, 'parse_nav_menu' ), $text );
280
+ }
281
+
282
+ return $text;
283
+ }
284
+
285
+ /**
286
+ * Parse comment text for links
287
+ *
288
+ * @param $text
289
+ *
290
+ * @return mixed
291
+ */
292
+ public function comment_text( $text ) {
293
+ if ( ! $this->do_tracking() )
294
+ return $text;
295
+
296
+ if ( ! is_feed() ) {
297
+ $text = preg_replace_callback( $this->link_regex, array( $this, 'parse_comment_link' ), $text );
298
+ }
299
+
300
+ return $text;
301
+ }
302
+ }
303
+
304
+ global $yoast_ga_universal;
305
+ $yoast_ga_universal = new Yoast_GA_Universal;
306
+ }
frontend/index.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ //Nothing to see here
3
+
4
+ header( 'HTTP/1.0 403 Forbidden' );
frontend/js/yst_ga.js ADDED
File without changes
frontend/views/tracking_debug.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <!-- This site uses the Yoast Google Analytics plugin v<?php echo GAWP_VERSION; ?> - https://yoast.com/wordpress/plugins/google-analytics/ -->
2
+ <!-- @Webmaster, normally you will find the Google Analytics tracking code here, but you have enabled the Debug Mode. Change that in Analytics -> (Tab) Debug mode and disable Debug Mode to enable the tracking of your site. -->
3
+ <!-- / Yoast Google Analytics -->
frontend/views/tracking_ga_js.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!-- This site uses the Yoast Google Analytics plugin v<?php echo GAWP_VERSION; ?> - Universal disabled - https://yoast.com/wordpress/plugins/google-analytics/ -->
2
+ <script type="text/javascript">
3
+
4
+ var _gaq = _gaq || [];
5
+ <?php
6
+ // List the GA elements from the class-ga-js.php
7
+ if( count( $gaq_push )>=1 ){
8
+ foreach($gaq_push as $item){
9
+ echo " _gaq.push([".$item."]);\n";
10
+ }
11
+ }
12
+
13
+ // Output the custom code that could be added in the WP backend
14
+ if( !empty( $ga_settings['custom_code'] ) ){
15
+ echo " " . stripslashes( $ga_settings['custom_code'] ) . "\n";
16
+ }
17
+ ?>
18
+
19
+ (function() {
20
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
21
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
22
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
23
+ })();
24
+
25
+ </script>
26
+ <!-- / Yoast Google Analytics -->
frontend/views/tracking_universal.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!-- This site uses the Yoast Google Analytics plugin v<?php echo GAWP_VERSION; ?> - Universal enabled - https://yoast.com/wordpress/plugins/google-analytics/ -->
2
+ <script type="text/javascript">
3
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
4
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
5
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
6
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
7
+
8
+ <?php
9
+ // List the GA elements from the class-ga-js.php
10
+ if( count( $gaq_push )>=1 ){
11
+ foreach($gaq_push as $item){
12
+ echo " ga(".$item.");\n";
13
+ }
14
+ }
15
+
16
+ // Output the custom code that could be added in the WP backend
17
+ if( !empty( $ga_settings['custom_code'] ) ){
18
+ echo " " . stripslashes( $ga_settings['custom_code'] ) . "\n";
19
+ }
20
+ ?>
21
+
22
+ </script>
23
+ <!-- / Yoast Google Analytics -->
frontend/views/tracking_usergroup.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <!-- This site uses the Yoast Google Analytics plugin v<?php echo GAWP_VERSION; ?> - https://yoast.com/wordpress/plugins/google-analytics/ -->
2
+ <!-- @Webmaster, normally you will find the Google Analytics tracking code here, but you are in the disabled user groups. Change that in Analytics -> Settings (Ignore usergroups) -->
3
+ <!-- / Yoast Google Analytics -->
googleanalytics.php CHANGED
@@ -1,11 +1,11 @@
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=wpgaplugin&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.3.5
8
- Requires at least: 3.0
9
  Author URI: http://yoast.com/
10
  License: GPL v3
11
  Text Domain: google-analytics-for-wordpress
@@ -30,30 +30,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
30
 
31
  // This plugin was originally based on Rich Boakes' Analytics plugin: http://boakes.org/analytics, but has since been rewritten and refactored multiple times.
32
 
33
- define( "GAWP_VERSION", '4.3.5' );
 
 
34
 
35
  define( "GAWP_URL", trailingslashit( plugin_dir_url( __FILE__ ) ) );
36
 
37
  define( "GAWP_PATH", plugin_dir_path( __FILE__ ) );
38
 
39
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
40
-
41
- require_once plugin_dir_path( __FILE__ ) . 'admin/ajax.php';
42
-
43
- } else if ( defined('DOING_CRON') && DOING_CRON ) {
44
 
45
- $options = get_option( 'Yoast_Google_Analytics' );
46
- if ( isset( $options['yoast_tracking'] ) && $options['yoast_tracking'] )
47
- require_once GAWP_PATH . 'inc/class-tracking.php';
48
 
49
  } else {
50
- load_plugin_textdomain( 'google-analytics-for-wordpress', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
51
-
52
- require_once GAWP_PATH . 'inc/functions.php';
53
-
54
- if ( is_admin() ) {
55
- require_once GAWP_PATH . 'admin/class-admin.php';
56
- } else {
57
- require_once GAWP_PATH . 'frontend/class-frontend.php';
58
- }
59
  }
1
  <?php
2
  /*
3
+ Plugin Name: Google Analytics by Yoast
4
+ Plugin URI: http://yoast.com/wordpress/google-analytics/#utm_source=wordpress&utm_medium=plugin&utm_campaign=wpgaplugin&utm_content=v500
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: 5.0.0
8
+ Requires at least: 3.8
9
  Author URI: http://yoast.com/
10
  License: GPL v3
11
  Text Domain: google-analytics-for-wordpress
30
 
31
  // This plugin was originally based on Rich Boakes' Analytics plugin: http://boakes.org/analytics, but has since been rewritten and refactored multiple times.
32
 
33
+ define( "GAWP_VERSION", '5.0.0' );
34
+
35
+ define( "GAWP_FILE", __FILE__ );
36
 
37
  define( "GAWP_URL", trailingslashit( plugin_dir_url( __FILE__ ) ) );
38
 
39
  define( "GAWP_PATH", plugin_dir_path( __FILE__ ) );
40
 
41
+ if( !class_exists('Yoast_GA_Options') ){
42
+ require_once GAWP_PATH . 'includes/class-options.php';
43
+ }
 
 
44
 
45
+ // Only require the needed classes
46
+ if ( is_admin() ) {
47
+ require_once GAWP_PATH . 'admin/class-admin.php';
48
 
49
  } else {
50
+ require_once GAWP_PATH . 'frontend/class-frontend.php';
 
 
 
 
 
 
 
 
51
  }
images/banner-conversion-review.png DELETED
Binary file
images/banner-ga-goals.png DELETED
Binary file
images/banner-website-review.png DELETED
Binary file
images/favicon.ico DELETED
Binary file
images/ga-icon-32x32.png DELETED
Binary file
images/ga-logo-532.png DELETED
Binary file
img/banner-local-seo.png ADDED
Binary file
img/banner-premium-seo.png ADDED
Binary file
img/banner-video-seo.png ADDED
Binary file
img/banner-website-review.png ADDED
Binary file
img/eBook_261x130.png ADDED
Binary file
img/eComm_130x100.png ADDED
Binary file
img/yoast-icon.png ADDED
Binary file
img/yoast_avatar_joost.png ADDED
Binary file
inc/class-tracking.php DELETED
@@ -1,158 +0,0 @@
1
- <?php
2
- /**
3
- * @package Admin
4
- */
5
-
6
- if ( !defined( 'GAWP_VERSION' ) ) {
7
- header( 'HTTP/1.0 403 Forbidden' );
8
- die;
9
- }
10
-
11
- /**
12
- * Class that creates the tracking functionality for WP SEO, as the core class might be used in more plugins,
13
- * it's checked for existence first.
14
- *
15
- * NOTE: this functionality is opt-in. Disabling the tracking in the settings or saying no when asked will cause
16
- * this file to not even be loaded.
17
- */
18
- if ( !class_exists( 'Yoast_Tracking' ) ) {
19
- class Yoast_Tracking {
20
-
21
- /**
22
- * Class constructor
23
- */
24
- function __construct() {
25
- // The tracking checks daily, but only sends new data every 7 days.
26
- if ( !wp_next_scheduled( 'yoast_tracking' ) ) {
27
- wp_schedule_event( time(), 'daily', 'yoast_tracking' );
28
- }
29
-
30
- add_action( 'yoast_tracking', array( $this, 'tracking' ) );
31
- }
32
-
33
- /**
34
- * Main tracking function.
35
- */
36
- function tracking() {
37
- // Start of Metrics
38
- global $blog_id, $wpdb;
39
-
40
- $hash = get_option( 'Yoast_Tracking_Hash' );
41
-
42
- if ( !isset( $hash ) || !$hash || empty( $hash ) ) {
43
- $hash = md5( site_url() );
44
- update_option( 'Yoast_Tracking_Hash', $hash );
45
- }
46
-
47
- $data = get_transient( 'yoast_tracking_cache' );
48
- if ( !$data ) {
49
-
50
- $pts = array();
51
- foreach ( get_post_types( array( 'public' => true ) ) as $pt ) {
52
- $count = wp_count_posts( $pt );
53
- $pts[$pt] = $count->publish;
54
- }
55
-
56
- $comments_count = wp_count_comments();
57
-
58
- // wp_get_theme was introduced in 3.4, for compatibility with older versions, let's do a workaround for now.
59
- if ( function_exists( 'wp_get_theme' ) ) {
60
- $theme_data = wp_get_theme();
61
- $theme = array(
62
- 'name' => $theme_data->display( 'Name', false, false ),
63
- 'theme_uri' => $theme_data->display( 'ThemeURI', false, false ),
64
- 'version' => $theme_data->display( 'Version', false, false ),
65
- 'author' => $theme_data->display( 'Author', false, false ),
66
- 'author_uri' => $theme_data->display( 'AuthorURI', false, false ),
67
- );
68
- if ( isset( $theme_data->template ) && !empty( $theme_data->template ) && $theme_data->parent() ) {
69
- $theme['template'] = array(
70
- 'version' => $theme_data->parent()->display( 'Version', false, false ),
71
- 'name' => $theme_data->parent()->display( 'Name', false, false ),
72
- 'theme_uri' => $theme_data->parent()->display( 'ThemeURI', false, false ),
73
- 'author' => $theme_data->parent()->display( 'Author', false, false ),
74
- 'author_uri' => $theme_data->parent()->display( 'AuthorURI', false, false ),
75
- );
76
- } else {
77
- $theme['template'] = '';
78
- }
79
- } else {
80
- $theme_data = (object) get_theme_data( get_stylesheet_directory() . '/style.css' );
81
- $theme = array(
82
- 'version' => $theme_data->Version,
83
- 'name' => $theme_data->Name,
84
- 'author' => $theme_data->Author,
85
- 'template' => $theme_data->Template,
86
- );
87
- }
88
-
89
- $plugins = array();
90
- foreach ( get_option( 'active_plugins' ) as $plugin_path ) {
91
- if ( !function_exists( 'get_plugin_data' ) )
92
- require_once ABSPATH . 'wp-admin/includes/admin.php';
93
-
94
- $plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_path );
95
-
96
- $slug = str_replace( '/' . basename( $plugin_path ), '', $plugin_path );
97
- $plugins[$slug] = array(
98
- 'version' => $plugin_info['Version'],
99
- 'name' => $plugin_info['Name'],
100
- 'plugin_uri' => $plugin_info['PluginURI'],
101
- 'author' => $plugin_info['AuthorName'],
102
- 'author_uri' => $plugin_info['AuthorURI'],
103
- );
104
- }
105
-
106
- $data = array(
107
- 'site' => array(
108
- 'hash' => $hash,
109
- 'url' => site_url(),
110
- 'name' => get_bloginfo( 'name' ),
111
- 'version' => get_bloginfo( 'version' ),
112
- 'multisite' => is_multisite(),
113
- 'users' => $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->users INNER JOIN $wpdb->usermeta ON ({$wpdb->users}.ID = {$wpdb->usermeta}.user_id) WHERE 1 = 1 AND ( {$wpdb->usermeta}.meta_key = %s )", $wpdb->prefix . $blog_id . '_capabilities' ) ),
114
-
115
- 'lang' => get_locale(),
116
- ),
117
- 'pts' => $pts,
118
- 'comments' => array(
119
- 'total' => $comments_count->total_comments,
120
- 'approved' => $comments_count->approved,
121
- 'spam' => $comments_count->spam,
122
- 'pings' => $wpdb->get_var( "SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_type = 'pingback'" ),
123
- ),
124
- 'options' => apply_filters( 'yoast_tracking_filters', array() ),
125
- 'theme' => $theme,
126
- 'plugins' => $plugins,
127
- );
128
-
129
- $args = array(
130
- 'body' => $data
131
- );
132
- wp_remote_post( 'https://tracking.yoast.com/', $args );
133
-
134
- // Store for a week, then push data again.
135
- set_transient( 'yoast_tracking_cache', true, 7 * 60 * 60 * 24 );
136
- }
137
- }
138
- }
139
-
140
- $yoast_tracking = new Yoast_Tracking;
141
- }
142
-
143
- /**
144
- * Adds tracking parameters for Google Analytics settings. Outside of the main class as the class could also be in use in other plugins.
145
- *
146
- * @param array $options
147
- * @return array
148
- */
149
- function ystga_tracking_additions( $options ) {
150
- $opt = get_option('Yoast_Google_Analytics');
151
-
152
- $options['google-analytics-for-wordpress'] = array(
153
- 'advanced_settigns' => isset( $opt['advancedsettings'] ) ? 1 : 0,
154
- );
155
- return $options;
156
- }
157
-
158
- add_filter( 'yoast_tracking_filters', 'ystga_tracking_additions' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/functions.php DELETED
@@ -1,20 +0,0 @@
1
- <?php
2
-
3
- function yoast_ga_get_domain( $uri ) {
4
- $hostPattern = "/^(http:\/\/)?([^\/]+)/i";
5
- $domainPatternUS = "/[^\.\/]+\.[^\.\/]+$/";
6
- $domainPatternUK = "/[^\.\/]+\.[^\.\/]+\.[^\.\/]+$/";
7
-
8
- preg_match( $hostPattern, $uri, $matches );
9
- $host = $matches[2];
10
- if ( preg_match( "/.*\..*\..*\..*$/", $host ) )
11
- preg_match( $domainPatternUK, $host, $matches );
12
- else
13
- preg_match( $domainPatternUS, $host, $matches );
14
-
15
- if ( isset( $matches[0] ) ) {
16
- return array( "domain" => $matches[0], "host" => $host );
17
- } else {
18
- return false;
19
- }
20
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/class-options.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! class_exists( 'Yoast_GA_Options' ) ) {
4
+
5
+ class Yoast_GA_Options {
6
+
7
+ private $options;
8
+
9
+ /**
10
+ * Constructor for the options
11
+ */
12
+ public function __construct() {
13
+ $this->options = $this->get_options();
14
+ }
15
+
16
+ /**
17
+ * Return the Google Analytics options
18
+ *
19
+ * @return mixed|void
20
+ */
21
+ public function get_options() {
22
+ return get_option( 'yst_ga' );
23
+ }
24
+
25
+ /**
26
+ * Get the Google Analytics tracking code for this website
27
+ *
28
+ * @return null
29
+ */
30
+ public function get_tracking_code() {
31
+ $tracking_code = NULL;
32
+ $options = $this->options;
33
+ $options = $options['ga_general'];
34
+
35
+ if ( ! empty( $options['analytics_profile'] ) ) {
36
+ $tracking_code = $options['analytics_profile'];
37
+ }
38
+
39
+ if ( ! empty( $options['manual_ua_code_field'] ) && ! empty( $options['manual_ua_code'] ) ) {
40
+ $tracking_code = $options['manual_ua_code_field'];
41
+ }
42
+
43
+ return $tracking_code;
44
+ }
45
+
46
+ }
47
+
48
+ global $Yoast_GA_Options;
49
+ $Yoast_GA_Options = new Yoast_GA_Options();
50
+
51
+ }
index.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ //Nothing to see here
3
+
4
+ header('HTTP/1.0 403 Forbidden');
js/index.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ //Nothing to see here
3
+
4
+ header('HTTP/1.0 403 Forbidden');
js/yoast_ga_admin.js ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function() {
2
+
3
+ jQuery('#ga-tabs').find('a').click(function() {
4
+ jQuery('#ga-tabs').find('a').removeClass('nav-tab-active');
5
+ jQuery('.gatab').removeClass('active');
6
+
7
+ var id = jQuery(this).attr('id').replace('-tab','');
8
+ jQuery('#' + id).addClass('active');
9
+ jQuery(this).addClass('nav-tab-active');
10
+ });
11
+
12
+ // init
13
+ var active_tab = window.location.hash.replace('#top#','');
14
+
15
+ // default to first tab
16
+ if ( active_tab == '' || active_tab == '#_=_') {
17
+ active_tab = jQuery('.gatab').attr('id');
18
+ }
19
+
20
+ jQuery('#' + active_tab).addClass('active');
21
+ jQuery('#' + active_tab + '-tab').addClass('nav-tab-active');
22
+
23
+ // Manually enter a UA code
24
+ jQuery('#yoast-ga-form-checkbox-settings-manual_ua_code').click(function(){
25
+ if(jQuery(this).is(':checked')){
26
+ jQuery('#enter_ua').show();
27
+ }
28
+ else{
29
+ jQuery('#enter_ua').hide();
30
+ jQuery('#yoast-ga-form-text-settings-manual_ua_code_field').attr('value','');
31
+ }
32
+ });
33
+
34
+ if(jQuery("#yoast-ga-form-checkbox-settings-manual_ua_code").is(':checked')){
35
+ jQuery('#enter_ua').show();
36
+ }
37
+ });
languages/google-analytics-for-wordpress.pot CHANGED
@@ -1,31 +1,29 @@
1
- # The Yoast Google Analytics for WordPress Translation Master File
2
- # Copyright (C) 2014
3
- # This file is distributed under the same license as the package.
4
- msgid ""
5
- msgstr ""
6
- "Project-Id-Version: \n"
7
- "Report-Msgid-Bugs-To: http://wordpress.org/tag/google-analytics-for-"
8
- "wordpress\n"
9
- "Report-Msgid-Bugs-To: StudioPress <translations@yoast.com>\n"
10
- "Last-Translator: StudioPress <translations@yoast.com>\n"
11
- "Language-Team: StudioPress <translations@yoast.com>\n"
12
- "POT-Creation-Date: 2014-01-06 10:28:20+00:00\n"
13
  "MIME-Version: 1.0\n"
14
- "Content-Type: text/plain; charset=UTF-8\n"
15
  "Content-Transfer-Encoding: 8bit\n"
16
- "PO-Revision-Date: 2013-MO-DA HO:MI+ZONE\n"
 
 
17
  "Plural-Forms: nplurals=2; plural=n != 1;\n"
18
  "X-Generator: CSL v1.x\n"
19
  "X-Poedit-Basepath: .\n"
20
  "X-Poedit-Language: English\n"
21
  "X-Poedit-Country: UNITED STATES\n"
22
- "X-Poedit-SourceCharset: utf-8\n"
23
- "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
24
- "X-Poedit-Basepath: ../../\n"
 
25
  "X-Poedit-Bookmarks: \n"
26
- "X-Poedit-SearchPath-0: .\n"
27
- "X-Textdomain-Support: yes"
28
- "PO-Revision-Date: 2014-MO-DA HO:MI+ZONE\n"
29
 
30
  #: admin/class-admin.php:30
31
  msgid "Google Analytics Configuration"
@@ -79,8 +77,7 @@ msgid "Google Analytics for WordPress Configuration"
79
  msgstr ""
80
 
81
  #: admin/class-admin.php:266
82
- msgid ""
83
- "Please authenticate with Google Analytics to retrieve your tracking code:"
84
  msgstr ""
85
 
86
  #: admin/class-admin.php:266
@@ -189,8 +186,7 @@ msgid "Show advanced settings"
189
  msgstr ""
190
 
191
  #: admin/class-admin.php:423
192
- msgid ""
193
- "Only adviced for advanced users who know their way around Google Analytics"
194
  msgstr ""
195
 
196
  #: admin/class-admin.php:428
@@ -200,8 +196,8 @@ msgstr ""
200
  #: admin/class-admin.php:429
201
  msgid ""
202
  "By allowing us to track anonymous data we can better help you, because we "
203
- "know with which WordPress configurations, themes and plugins we should test. "
204
- "No personal data will be submitted."
205
  msgstr ""
206
 
207
  #: admin/class-admin.php:432
@@ -228,8 +224,8 @@ msgstr ""
228
 
229
  #: admin/class-admin.php:440
230
  msgid ""
231
- "Allows you to easily remove logged in users from your reports, or to segment "
232
- "by different user roles. The users primary role will be logged."
233
  msgstr ""
234
 
235
  #: admin/class-admin.php:445
@@ -264,8 +260,8 @@ msgstr ""
264
 
265
  #: admin/class-admin.php:464
266
  msgid ""
267
- "Allows you to see pageviews per year of publication, showing you if your old "
268
- "posts still get traffic."
269
  msgstr ""
270
 
271
  #: admin/class-admin.php:469
@@ -360,8 +356,8 @@ msgstr ""
360
  #: admin/class-admin.php:518
361
  msgid ""
362
  "This prefix is used before all pageviews, they are then segmented "
363
- "automatically after that. If nothing is entered here, <code>/yoast-ga/</"
364
- "code> is used."
365
  msgstr ""
366
 
367
  #: admin/class-admin.php:524
@@ -382,8 +378,9 @@ msgstr ""
382
 
383
  #: admin/class-admin.php:534
384
  msgid ""
385
- "This allows you to set the domain that's set by %s<code>setDomainName</code>"
386
- "%s for tracking subdomains, if empty this will not be set."
 
387
  msgstr ""
388
 
389
  #: admin/class-admin.php:539
@@ -403,8 +400,8 @@ msgstr ""
403
  #: admin/class-admin.php:546
404
  msgid ""
405
  "Set the primary domain used in %s<code>setDomainName</code>%s for cross "
406
- "domain tracking (eg. <code>example-petstore.com</code> ), if empty this will "
407
- "default to your configured Home URL."
408
  msgstr ""
409
 
410
  #: admin/class-admin.php:551
@@ -413,11 +410,11 @@ msgstr ""
413
 
414
  #: admin/class-admin.php:552
415
  msgid ""
416
- "All links to these domains will have the <a href=\"http://code.google.com/"
417
- "apis/analytics/docs/tracking/gaTrackingSite.html#multipleDomains"
418
- "\"><code>_link</code></a> code automatically attached. Separate domains/sub-"
419
- "domains with commas (eg. <code>dogs.example-petstore.com, cats.example-"
420
- "petstore.com</code>)"
421
  msgstr ""
422
 
423
  #: admin/class-admin.php:557
@@ -426,8 +423,8 @@ msgstr ""
426
 
427
  #: admin/class-admin.php:558
428
  msgid ""
429
- "Not for the average user: this allows you to add a line of code, to be added "
430
- "before the <code>trackPageview</code> call."
431
  msgstr ""
432
 
433
  #: admin/class-admin.php:563
@@ -437,8 +434,9 @@ msgstr ""
437
  #: admin/class-admin.php:564
438
  msgid ""
439
  "This requires integration of your Analytics and AdSense account, for help, "
440
- "<a href=\"http://google.com/support/analytics/bin/answer.py?"
441
- "answer=92625\">look here</a>."
 
442
  msgstr ""
443
 
444
  #: admin/class-admin.php:569
@@ -461,8 +459,7 @@ msgid "Track extra Search Engines"
461
  msgstr ""
462
 
463
  #: admin/class-admin.php:580
464
- msgid ""
465
- "You can provide a custom URL to the extra search engines file if you want:"
466
  msgstr ""
467
 
468
  #: admin/class-admin.php:586
@@ -472,9 +469,10 @@ msgstr ""
472
  #: admin/class-admin.php:587
473
  msgid ""
474
  "Do not use this feature if you use FeedBurner, as FeedBurner can do this "
475
- "automatically, and better than this plugin can. Check <a href=\"http://www."
476
- "google.com/support/feedburner/bin/answer.py?hl=en&amp;answer=165769\">this "
477
- "help page</a> for info on how to enable this feature in FeedBurner."
 
478
  msgstr ""
479
 
480
  #: admin/class-admin.php:592
@@ -491,10 +489,10 @@ msgstr ""
491
 
492
  #: admin/class-admin.php:603
493
  msgid ""
494
- "This adds a <code><a href=\"http://code.google.com/apis/analytics/docs/"
495
- "gaJSApiCampaignTracking.html#_gat.GA_Tracker_._setAllowAnchor"
496
- "\">_setAllowAnchor</a></code> call to your tracking code, and makes RSS link "
497
- "tagging use a # as well."
498
  msgstr ""
499
 
500
  #: admin/class-admin.php:608
@@ -503,10 +501,11 @@ msgstr ""
503
 
504
  #: admin/class-admin.php:609
505
  msgid ""
506
- "This adds a <code><a href=\"http://code.google.com/apis/analytics/docs/gaJS/"
507
- "gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setAllowLinker"
508
- "\">_setAllowLinker</a></code> call to your tracking code, allowing you to "
509
- "use <code>_link</code> and related functions."
 
510
  msgstr ""
511
 
512
  #: admin/class-admin.php:614
@@ -515,7 +514,8 @@ msgstr ""
515
 
516
  #: admin/class-admin.php:615
517
  msgid ""
518
- "This sets <code><a href=\"http://code.google.com/apis/analytics/docs/gaJS/"
 
519
  "gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setAllowHash\">_setAllowHash</"
520
  "a></code> to false, allowing you to track subdomains etc."
521
  msgstr ""
@@ -526,10 +526,11 @@ msgstr ""
526
 
527
  #: admin/class-admin.php:621
528
  msgid ""
529
- "This adds <code><a href=\"http://code.google.com/apis/analytics/docs/gaJS/"
530
- "gaJSApi_gat.html#_gat._anonymizeIp\">_anonymizeIp</a></code>, telling Google "
531
- "Analytics to anonymize the information sent by the tracker objects by "
532
- "removing the last octet of the IP address prior to its storage."
 
533
  msgstr ""
534
 
535
  #: admin/class-admin.php:625
@@ -543,8 +544,8 @@ msgstr ""
543
  #: admin/class-admin.php:631
544
  msgid ""
545
  "If you want to track all internal links that begin with <code>/out/</code>, "
546
- "enter <code>/out/</code> in the box above. If you have multiple prefixes you "
547
- "can separate them with comma's: <code>/out/,/recommends/</code>"
548
  msgstr ""
549
 
550
  #: admin/class-admin.php:636
@@ -553,9 +554,9 @@ msgstr ""
553
 
554
  #: admin/class-admin.php:637
555
  msgid ""
556
- "The label to use for these links, this will be added to where the click came "
557
- "from, so if the label is \"aff\", the label for a click from the content of "
558
- "an article becomes \"outbound-article-aff\"."
559
  msgstr ""
560
 
561
  #: admin/class-admin.php:641
@@ -565,9 +566,10 @@ msgstr ""
565
  #: admin/class-admin.php:644
566
  msgid ""
567
  "The WordPress e-Commerce plugin has been detected. This plugin can "
568
- "automatically add transaction tracking for you. To do that, <a href=\"http://"
569
- "yoast.com/wordpress/google-analytics/enable-ecommerce/\">enable e-commerce "
570
- "for your reports in Google Analytics</a> and then check the box below."
 
571
  msgstr ""
572
 
573
  #: admin/class-admin.php:648 admin/class-admin.php:661
@@ -580,11 +582,11 @@ msgstr ""
580
 
581
  #: admin/class-admin.php:657
582
  msgid ""
583
- "The Shopp e-Commerce plugin has been detected. This plugin can automatically "
584
- "add transaction tracking for you. To do that, <a href=\"http://www.google."
585
- "com/support/googleanalytics/bin/answer.py?hl=en&amp;answer=55528\">enable e-"
586
- "commerce for your reports in Google Analytics</a> and then check the box "
587
- "below."
588
  msgstr ""
589
 
590
  #: admin/class-admin.php:664
@@ -644,13 +646,12 @@ msgstr ""
644
  msgid "Blog about it & link to the %1$splugin page%2$s"
645
  msgstr ""
646
 
647
- #: admin/class-admin.php:766
648
  msgid "Google Analytics is not active."
649
  msgstr ""
650
 
651
- #: admin/class-admin.php:766
652
- msgid ""
653
- "You must %sselect which Analytics Profile to track%s before it can work."
654
  msgstr ""
655
 
656
  #: admin/class-pointer.php:37
@@ -708,8 +709,33 @@ msgid ""
708
  "ignored."
709
  msgstr ""
710
 
711
- #: frontend/class-frontend.php:663
712
  msgid ""
713
  "Please set Google Analytics position to \"manual\" in the settings, or "
714
  "remove this call to yoast_analytics();"
715
  msgstr ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2014 Google Analytics for WordPress
2
+ # This file is distributed under the same license as the Google Analytics for WordPress package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: Google Analytics for WordPress 4.3.5\n"
6
+ "Report-Msgid-Bugs-To: "
7
+ "http://wordpress.org/support/plugin/google-analytics-for-wordpress\n"
8
+ "POT-Creation-Date: 2014-03-26 15:25:02+00:00\n"
 
 
 
 
9
  "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
+ "PO-Revision-Date: 2014-MO-DA HO:MI+ZONE\n"
13
+ "Last-Translator: Remkus de Vries <translations@yoast.com>\n"
14
+ "Language-Team: Yoast Translate <translations@yoast.com>\n"
15
  "Plural-Forms: nplurals=2; plural=n != 1;\n"
16
  "X-Generator: CSL v1.x\n"
17
  "X-Poedit-Basepath: .\n"
18
  "X-Poedit-Language: English\n"
19
  "X-Poedit-Country: UNITED STATES\n"
20
+ "X-Poedit-Sourcecharset: utf-8\n"
21
+ "X-Poedit-Keywordslist: "
22
+ "__;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_"
23
+ "x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
24
  "X-Poedit-Bookmarks: \n"
25
+ "X-Poedit-Searchpath-0: .\n"
26
+ "X-Textdomain-Support: yes\n"
 
27
 
28
  #: admin/class-admin.php:30
29
  msgid "Google Analytics Configuration"
77
  msgstr ""
78
 
79
  #: admin/class-admin.php:266
80
+ msgid "Please authenticate with Google Analytics to retrieve your tracking code:"
 
81
  msgstr ""
82
 
83
  #: admin/class-admin.php:266
186
  msgstr ""
187
 
188
  #: admin/class-admin.php:423
189
+ msgid "Only adviced for advanced users who know their way around Google Analytics"
 
190
  msgstr ""
191
 
192
  #: admin/class-admin.php:428
196
  #: admin/class-admin.php:429
197
  msgid ""
198
  "By allowing us to track anonymous data we can better help you, because we "
199
+ "know with which WordPress configurations, themes and plugins we should "
200
+ "test. No personal data will be submitted."
201
  msgstr ""
202
 
203
  #: admin/class-admin.php:432
224
 
225
  #: admin/class-admin.php:440
226
  msgid ""
227
+ "Allows you to easily remove logged in users from your reports, or to "
228
+ "segment by different user roles. The users primary role will be logged."
229
  msgstr ""
230
 
231
  #: admin/class-admin.php:445
260
 
261
  #: admin/class-admin.php:464
262
  msgid ""
263
+ "Allows you to see pageviews per year of publication, showing you if your "
264
+ "old posts still get traffic."
265
  msgstr ""
266
 
267
  #: admin/class-admin.php:469
356
  #: admin/class-admin.php:518
357
  msgid ""
358
  "This prefix is used before all pageviews, they are then segmented "
359
+ "automatically after that. If nothing is entered here, "
360
+ "<code>/yoast-ga/</code> is used."
361
  msgstr ""
362
 
363
  #: admin/class-admin.php:524
378
 
379
  #: admin/class-admin.php:534
380
  msgid ""
381
+ "This allows you to set the domain that's set by "
382
+ "%s<code>setDomainName</code>%s for tracking subdomains, if empty this will "
383
+ "not be set."
384
  msgstr ""
385
 
386
  #: admin/class-admin.php:539
400
  #: admin/class-admin.php:546
401
  msgid ""
402
  "Set the primary domain used in %s<code>setDomainName</code>%s for cross "
403
+ "domain tracking (eg. <code>example-petstore.com</code> ), if empty this "
404
+ "will default to your configured Home URL."
405
  msgstr ""
406
 
407
  #: admin/class-admin.php:551
410
 
411
  #: admin/class-admin.php:552
412
  msgid ""
413
+ "All links to these domains will have the <a "
414
+ "href=\"http://code.google.com/apis/analytics/docs/tracking/gaTrackingSite."
415
+ "html#multipleDomains\"><code>_link</code></a> code automatically attached. "
416
+ "Separate domains/sub-domains with commas (eg. "
417
+ "<code>dogs.example-petstore.com, cats.example-petstore.com</code>)"
418
  msgstr ""
419
 
420
  #: admin/class-admin.php:557
423
 
424
  #: admin/class-admin.php:558
425
  msgid ""
426
+ "Not for the average user: this allows you to add a line of code, to be "
427
+ "added before the <code>trackPageview</code> call."
428
  msgstr ""
429
 
430
  #: admin/class-admin.php:563
434
  #: admin/class-admin.php:564
435
  msgid ""
436
  "This requires integration of your Analytics and AdSense account, for help, "
437
+ "<a "
438
+ "href=\"http://google.com/support/analytics/bin/answer.py?answer=92625\">"
439
+ "look here</a>."
440
  msgstr ""
441
 
442
  #: admin/class-admin.php:569
459
  msgstr ""
460
 
461
  #: admin/class-admin.php:580
462
+ msgid "You can provide a custom URL to the extra search engines file if you want:"
 
463
  msgstr ""
464
 
465
  #: admin/class-admin.php:586
469
  #: admin/class-admin.php:587
470
  msgid ""
471
  "Do not use this feature if you use FeedBurner, as FeedBurner can do this "
472
+ "automatically, and better than this plugin can. Check <a "
473
+ "href=\"http://www.google.com/support/feedburner/bin/answer.py?hl=en&amp;"
474
+ "answer=165769\">this help page</a> for info on how to enable this feature "
475
+ "in FeedBurner."
476
  msgstr ""
477
 
478
  #: admin/class-admin.php:592
489
 
490
  #: admin/class-admin.php:603
491
  msgid ""
492
+ "This adds a <code><a "
493
+ "href=\"http://code.google.com/apis/analytics/docs/gaJSApiCampaignTracking."
494
+ "html#_gat.GA_Tracker_._setAllowAnchor\">_setAllowAnchor</a></code> call to "
495
+ "your tracking code, and makes RSS link tagging use a # as well."
496
  msgstr ""
497
 
498
  #: admin/class-admin.php:608
501
 
502
  #: admin/class-admin.php:609
503
  msgid ""
504
+ "This adds a <code><a "
505
+ "href=\"http://code.google.com/apis/analytics/docs/gaJS/"
506
+ "gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setAllowLinker\">_"
507
+ "setAllowLinker</a></code> call to your tracking code, allowing you to use "
508
+ "<code>_link</code> and related functions."
509
  msgstr ""
510
 
511
  #: admin/class-admin.php:614
514
 
515
  #: admin/class-admin.php:615
516
  msgid ""
517
+ "This sets <code><a "
518
+ "href=\"http://code.google.com/apis/analytics/docs/gaJS/"
519
  "gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setAllowHash\">_setAllowHash</"
520
  "a></code> to false, allowing you to track subdomains etc."
521
  msgstr ""
526
 
527
  #: admin/class-admin.php:621
528
  msgid ""
529
+ "This adds <code><a "
530
+ "href=\"http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_"
531
+ "gat._anonymizeIp\">_anonymizeIp</a></code>, telling Google Analytics to "
532
+ "anonymize the information sent by the tracker objects by removing the last "
533
+ "octet of the IP address prior to its storage."
534
  msgstr ""
535
 
536
  #: admin/class-admin.php:625
544
  #: admin/class-admin.php:631
545
  msgid ""
546
  "If you want to track all internal links that begin with <code>/out/</code>, "
547
+ "enter <code>/out/</code> in the box above. If you have multiple prefixes "
548
+ "you can separate them with comma's: <code>/out/,/recommends/</code>"
549
  msgstr ""
550
 
551
  #: admin/class-admin.php:636
554
 
555
  #: admin/class-admin.php:637
556
  msgid ""
557
+ "The label to use for these links, this will be added to where the click "
558
+ "came from, so if the label is \"aff\", the label for a click from the "
559
+ "content of an article becomes \"outbound-article-aff\"."
560
  msgstr ""
561
 
562
  #: admin/class-admin.php:641
566
  #: admin/class-admin.php:644
567
  msgid ""
568
  "The WordPress e-Commerce plugin has been detected. This plugin can "
569
+ "automatically add transaction tracking for you. To do that, <a "
570
+ "href=\"http://yoast.com/wordpress/google-analytics/enable-ecommerce/\">"
571
+ "enable e-commerce for your reports in Google Analytics</a> and then check "
572
+ "the box below."
573
  msgstr ""
574
 
575
  #: admin/class-admin.php:648 admin/class-admin.php:661
582
 
583
  #: admin/class-admin.php:657
584
  msgid ""
585
+ "The Shopp e-Commerce plugin has been detected. This plugin can "
586
+ "automatically add transaction tracking for you. To do that, <a "
587
+ "href=\"http://www.google.com/support/googleanalytics/bin/answer.py?hl=en&"
588
+ "amp;answer=55528\">enable e-commerce for your reports in Google "
589
+ "Analytics</a> and then check the box below."
590
  msgstr ""
591
 
592
  #: admin/class-admin.php:664
646
  msgid "Blog about it & link to the %1$splugin page%2$s"
647
  msgstr ""
648
 
649
+ #: admin/class-admin.php:774
650
  msgid "Google Analytics is not active."
651
  msgstr ""
652
 
653
+ #: admin/class-admin.php:774
654
+ msgid "You must %sselect which Analytics Profile to track%s before it can work."
 
655
  msgstr ""
656
 
657
  #: admin/class-pointer.php:37
709
  "ignored."
710
  msgstr ""
711
 
712
+ #: frontend/class-frontend.php:661
713
  msgid ""
714
  "Please set Google Analytics position to \"manual\" in the settings, or "
715
  "remove this call to yoast_analytics();"
716
  msgstr ""
717
+
718
+ #. Plugin Name of the plugin/theme
719
+ msgid "Google Analytics for WordPress"
720
+ msgstr ""
721
+
722
+ #. Plugin URI of the plugin/theme
723
+ msgid ""
724
+ "http://yoast.com/wordpress/google-analytics/#utm_source=wordpress&utm_"
725
+ "medium=plugin&utm_campaign=wpgaplugin&utm_content=v420"
726
+ msgstr ""
727
+
728
+ #. Description of the plugin/theme
729
+ msgid ""
730
+ "This plugin makes it simple to add Google Analytics to your WordPress blog, "
731
+ "adding lots of features, eg. custom variables and automatic clickout and "
732
+ "download tracking."
733
+ msgstr ""
734
+
735
+ #. Author of the plugin/theme
736
+ msgid "Joost de Valk"
737
+ msgstr ""
738
+
739
+ #. Author URI of the plugin/theme
740
+ msgid "http://yoast.com/"
741
+ msgstr ""
languages/index.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ //Nothing to see here
3
+
4
+ header('HTTP/1.0 403 Forbidden');
lib/languages/google-analytics-for-wordpress.pot ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2014 Joost de Valk
2
+ # This file is distributed under the GPL v3.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: Google Analytics for WordPress 5.0.0\n"
6
+ "Report-Msgid-Bugs-To: "
7
+ "http://wordpress.org/support/plugin/google-analytics-for-wordpress\n"
8
+ "POT-Creation-Date: 2014-06-23 20:33:09+00:00\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=utf-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "PO-Revision-Date: 2014-MO-DA HO:MI+ZONE\n"
13
+ "Last-Translator: Remkus de Vries <translations@yoast.com>\n"
14
+ "Language-Team: Yoast Translate <translations@yoast.com>\n"
15
+ "X-Generator: grunt-wp-i18n 0.4.4\n"
16
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
17
+ "X-Poedit-Basepath: .\n"
18
+ "X-Poedit-Language: English\n"
19
+ "X-Poedit-Country: UNITED STATES\n"
20
+ "X-Poedit-SourceCharset: utf-8\n"
21
+ "X-Poedit-KeywordsList: __;_e;_x:1,2c;_ex:1,2c;_n:1,2; "
22
+ "_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_attr__; esc_html__;esc_attr_e; "
23
+ "esc_html_e;esc_attr_x:1,2c; esc_html_x:1,2c;\n"
24
+ "X-Poedit-Bookmarks: \n"
25
+ "X-Poedit-SearchPath-0: .\n"
26
+ "X-Textdomain-Support: yes\n"
27
+
28
+ #: admin/class-admin.php:21 admin/class-admin.php:30 admin/class-admin.php:39
29
+ #: admin/class-admin.php:48
30
+ msgid "Yoast Google Analytics:"
31
+ msgstr ""
32
+
33
+ #: admin/class-admin.php:21
34
+ msgid "General Settings"
35
+ msgstr ""
36
+
37
+ #: admin/class-admin.php:21
38
+ msgid "Analytics"
39
+ msgstr ""
40
+
41
+ #: admin/class-admin.php:30 admin/class-admin.php:31
42
+ msgid "Dashboard"
43
+ msgstr ""
44
+
45
+ #: admin/class-admin.php:39 admin/class-admin.php:40
46
+ msgid "Settings"
47
+ msgstr ""
48
+
49
+ #: admin/class-admin.php:48
50
+ msgid "Extensions"
51
+ msgstr ""
52
+
53
+ #: frontend/class-frontend.php:80
54
+ msgid ""
55
+ "Google Analytics tracking code not shown because you haven't setup Google "
56
+ "Analytics for WordPress yet."
57
+ msgstr ""
58
+
59
+ #: frontend/class-frontend.php:334
60
+ msgid ""
61
+ "Google Analytics tracking code not shown because users over level %s are "
62
+ "ignored."
63
+ msgstr ""
64
+
65
+ #: frontend/class-frontend.php:728
66
+ msgid ""
67
+ "Please set Google Analytics position to \"manual\" in the settings, or "
68
+ "remove this call to yoast_analytics();"
69
+ msgstr ""
70
+
71
+ #. Plugin Name of the plugin/theme
72
+ msgid "Google Analytics for WordPress"
73
+ msgstr ""
74
+
75
+ #. Plugin URI of the plugin/theme
76
+ msgid ""
77
+ "http://yoast.com/wordpress/google-analytics/#utm_source=wordpress&utm_"
78
+ "medium=plugin&utm_campaign=wpgaplugin&utm_content=v420"
79
+ msgstr ""
80
+
81
+ #. Description of the plugin/theme
82
+ msgid ""
83
+ "This plugin makes it simple to add Google Analytics to your WordPress blog, "
84
+ "adding lots of features, eg. custom variables and automatic clickout and "
85
+ "download tracking."
86
+ msgstr ""
87
+
88
+ #. Author of the plugin/theme
89
+ msgid "Joost de Valk"
90
+ msgstr ""
91
+
92
+ #. Author URI of the plugin/theme
93
+ msgid "http://yoast.com/"
94
+ msgstr ""
readme.txt CHANGED
@@ -1,49 +1,40 @@
1
  === Google Analytics by Yoast ===
2
- Contributors: joostdevalk
3
- Donate link: http://yoast.com/donate/
4
- Tags: analytics, google analytics, statistics, tracking, stats, google, yoast, yoast analytics
5
- Requires at least: 3.3
6
  Tested up to: 4.0
7
- Stable tag: 4.3.5
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 by Yoast plugin for WordPress 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](https://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](https://yoast.com/wordpress/plugins/) by the same author.
47
  * Want to increase traffic to your WordPress blog? Check out the [WordPress SEO](https://yoast.com/articles/wordpress-seo/) Guide!
48
  * Check out the authors [WordPress Hosting](https://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
 
@@ -58,6 +49,17 @@ This section describes how to install the plugin and get it working.
58
 
59
  == Changelog ==
60
 
 
 
 
 
 
 
 
 
 
 
 
61
  = 4.3.5 =
62
 
63
  * Enhancement:
@@ -368,32 +370,10 @@ This section describes how to install the plugin and get it working.
368
 
369
  == Frequently Asked Questions ==
370
 
371
- = Can I run this plugin together with another Google Analytics plugin? =
372
-
373
- No. You can not. It will break tracking.
374
-
375
- = Another profile than the one I selected is showing as selected? =
376
-
377
- 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.
378
-
379
- = I've just installed the new tracking and Google Analytics says it's not receiving data yet? =
380
-
381
- Give it a couple of hours, usually it'll be fixed. It can take up to 24 hours to appear though.
382
-
383
- = Google Analytics says it's receiving data, but I don't see any stats yet? =
384
-
385
- This can take up to 24 hours after the installation of the new tracking code.
386
-
387
- = Why is the tracking code loaded in the head section of the site? =
388
-
389
- 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/).
390
 
391
  == Screenshots ==
392
 
393
- 1. Screenshot of the basic settings panel for this plugin.
394
- 2. Screenshot of the custom variable settings panel.
395
- 3. Screenshot of the link tracking panel.
396
- 4. Screenshot of the advanced settings panel.
397
- 5. Screenshot of the debugging mode in action.
398
-
399
- == Upgrade Notice ==
1
  === Google Analytics by Yoast ===
2
+ Contributors: joostdevalk,PvW_NL
3
+ Donate link: https://yoast.com/donate/
4
+ Tags: analytics, google analytics, statistics, tracking, stats, google, yoast
5
+ Requires at least: 3.8
6
  Tested up to: 4.0
7
+ Stable tag: 5.0
8
 
9
+ Track your WordPress site easily with the latest tracking codes and lots added data for search result pages and error pages.
10
 
11
  == Description ==
12
 
13
+ The Google Analytics by Yoast plugin for WordPress allows you to track your blog easily and always stays up to date with the newest features in Google Analytics.
14
 
15
+ > <strong>Development on GitHub</strong><br>
16
+ > The development of Google Analytics by Yoast [takes place on GitHub](https://github.com/Yoast/google-analytics-for-wordpress). Bugs and pull requests are welcomed there. For support, please refer to the forums. A premium version of Google Analytics by Yoast will be available soon which will give you access to email support.
 
17
 
18
  Full list of features:
19
 
20
  * Simple installation through integration with Google Analytics API: authenticate, select the site you want to track and you're done.
21
+ * This plugin uses the universal or the asynchronous Google Analytics tracking code, the fastest and most reliable tracking code Google Analytics offers.
22
+ * Option to enable demographics and interest reports.
 
23
  * Outbound link & downloads tracking.
24
+ * Configurable options to track outbound links either as pageviews or as events.
25
+ * Option to track just downloads as pageviews or events in Google Analytics.
26
+ * Option to track internal links with a particular format as outbound links, very useful for affiliate links that start with /out/, for instance.
 
 
 
 
 
 
27
  * Possibility to ignore any user level and up, so all editors and higher for instance.
28
+ * Option to anonymize IP's for use in countries with stricter privacy regulations.
29
+ * Tracking of your search result pages and 404 pages.
30
+ * Full [debug mode](http://yoast.com/google-analytics-debug-mode/), including Firebug lite and ga_debug.js for debugging Google Analytics issues.
31
+
32
+ > <strong>Coming soon: dashboards!</strong><br>
33
+ > We're working hard on the next iteration of the plugin which will contain a Dashboard within your WordPress admin with the most important stats from Google Analytics.
 
34
 
35
  Other interesting stuff:
36
 
37
+ * Check out the other [WordPress Plugins](https://yoast.com/wordpress/plugins/) by the same team.
38
  * Want to increase traffic to your WordPress blog? Check out the [WordPress SEO](https://yoast.com/articles/wordpress-seo/) Guide!
39
  * Check out the authors [WordPress Hosting](https://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!
40
 
49
 
50
  == Changelog ==
51
 
52
+ = 5.0.0 =
53
+ Release Date: September 4th, 2014
54
+
55
+ Complete rewrite of the Google Analytics plugin.
56
+
57
+ * Enhancements:
58
+ * Universal tracking added
59
+ * Better link tracking
60
+ * New Universal demographics feature
61
+ * New menu items in the WordPress admin menu
62
+
63
  = 4.3.5 =
64
 
65
  * Enhancement:
370
 
371
  == Frequently Asked Questions ==
372
 
373
+ For all frequently asked questions, and their answers, check the [Yoast Knowledge base](http://kb.yoast.com/category/43-google-analytics-for-wordpress).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
 
375
  == Screenshots ==
376
 
377
+ 1. Screenshot of the general settings panel for this plugin.
378
+ 2. Screenshot of the universal settings panel.
379
+ 3. Screenshot of the advanced settings panel.