Yoast_GA_Admin

This class is for the backend, extendable for all child classes.

Defined (1)

The class is defined in the following location(s).

/admin/class-admin.php  
  1. class Yoast_GA_Admin extends Yoast_GA_Options { 
  2.  
  3. /** 
  4. * Constructor 
  5. */ 
  6. public function __construct() { 
  7. parent::__construct(); 
  8.  
  9. add_action( 'plugins_loaded', array( $this, 'init_ga' ) ); 
  10.  
  11. // Only run admin_init when there is a cron jon executed. 
  12. $current_page = filter_input( INPUT_GET, 'page' ); 
  13.  
  14. // Only when current page is not 'wpseo'. 
  15. if ( strpos( $current_page, 'wpseo' ) !== 0 ) { 
  16. if ( ( $this->is_running_cron() || $this->is_running_ajax() ) || strpos( $current_page, 'yst_ga' ) === 0 ) { 
  17. add_action( 'admin_init', array( $this, 'init_settings' ) ); 
  18.  
  19.  
  20. /** 
  21. * Init function when the plugin is loaded 
  22. */ 
  23. public function init_ga() { 
  24.  
  25. new Yoast_GA_Admin_Menu( $this ); 
  26.  
  27. add_filter( 'plugin_action_links_' . plugin_basename( GAWP_FILE ), array( $this, 'add_action_links' ) ); 
  28.  
  29.  
  30. /** 
  31. * Init function for the settings of GA 
  32. */ 
  33. public function init_settings() { 
  34. $this->options = $this->get_options(); 
  35.  
  36. try { 
  37. // Loading Google Api Libs with minimal version 2.0. 
  38. new Yoast_Api_Libs( '2.0' ); 
  39. catch( Exception $exception ) { 
  40. if ( $exception->getMessage() === 'required_version' ) { 
  41. add_action( 'admin_notices', array( $this, 'set_api_libs_error' ) ); 
  42.  
  43. $dashboards = Yoast_GA_Dashboards::get_instance(); 
  44.  
  45. // Listener for reconnecting with google analytics 
  46. $this->google_analytics_listener(); 
  47.  
  48. if ( is_null( $this->get_tracking_code() ) && $this->show_admin_warning() ) { 
  49. add_action( 'admin_notices', array( 'Yoast_Google_Analytics_Notice', 'config_warning' ) ); 
  50.  
  51. // Check if something has went wrong with GA-api calls 
  52. $has_tracking_code = ( ! is_null( $this->get_tracking_code() ) && empty( $this->options['manual_ua_code_field'] ) ); 
  53. if ( $has_tracking_code && $this->show_admin_dashboard_warning() ) { 
  54. Yoast_Google_Analytics::get_instance()->check_for_ga_issues(); 
  55.  
  56.  
  57. if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) { 
  58. $this->handle_ga_post_request( $dashboards ); 
  59.  
  60. /** 
  61. * Show the notifications if we have one 
  62. */ 
  63. $this->show_notification( 'ga_notifications' ); 
  64.  
  65. // Load the Google Analytics Dashboards functionality 
  66. $dashboards->init_dashboards( $this->get_current_profile() ); 
  67.  
  68. /** 
  69. * There is an error with the API libs. So show a notice. 
  70. */ 
  71. public function set_api_libs_error() { 
  72. echo '<div class="error notice"><p>' . __( 'Yoast plugins share some code between them to make your site faster. As a result of that, we need all Yoast plugins to be up to date. We\'ve detected this isn\'t the case, so please update the Yoast plugins that aren\'t up to date yet.', 'google-analytics-for-wordpress' ) . '</p></div>'; 
  73.  
  74. /** 
  75. * This function saves the settings in the option field and returns a wp success message on success 
  76. * @param array $data 
  77. */ 
  78. public function save_settings( $data ) { 
  79.  
  80. unset( $data['google_auth_code'] ); 
  81.  
  82. foreach ( $data as $key => $value ) { 
  83. if ( $key != 'return_tab' ) { 
  84. if ( is_string( $value ) ) { 
  85. if ( $key === 'custom_code' && ! current_user_can( 'unfiltered_html' ) ) { 
  86. continue; 
  87. else { 
  88. $value = strip_tags( $value ); 
  89.  
  90. $this->options[ $key ] = $value; 
  91.  
  92. // Check checkboxes, on a uncheck they won't be posted to this function 
  93. $defaults = $this->default_ga_values(); 
  94. foreach ( $defaults[ $this->option_prefix ] as $option_name => $value ) { 
  95. $this->handle_default_setting( $data, $option_name, $value ); 
  96.  
  97. if ( ! empty( $this->options['analytics_profile'] ) ) { 
  98. $this->options['analytics_profile_code'] = $this->get_ua_code_from_profile( $this->options['analytics_profile'] ); 
  99.  
  100. $this->do_validation( $data['return_tab'] ); 
  101.  
  102. if ( $this->update_option( $this->options ) ) { 
  103. // Success, add a new notification 
  104. $this->add_notification( 'ga_notifications', array( 
  105. 'type' => 'success',  
  106. 'description' => __( 'Settings saved.', 'google-analytics-for-wordpress' ),  
  107. ) ); 
  108. else { 
  109. // Fail, add a new notification 
  110. $this->add_notification( 'ga_notifications', array( 
  111. 'type' => 'error',  
  112. 'description' => __( 'There were no changes to save, please try again.', 'google-analytics-for-wordpress' ),  
  113. ) ); 
  114.  
  115. // redirect 
  116. wp_redirect( admin_url( 'admin.php' ) . '?page=yst_ga_settings#top#' . $data['return_tab'], 301 ); 
  117. exit; 
  118.  
  119. /** 
  120. * Redirect to settings with a validation error if there are validation errors 
  121. * @param string $return_tab The tab to return to when there is a validation error. 
  122. */ 
  123. protected function do_validation( $return_tab ) { 
  124. $validation = $this->validate_settings(); 
  125. if ( is_wp_error( $validation ) ) { 
  126. $this->add_notification( 'ga_notifications', array( 
  127. 'type' => 'error',  
  128. 'description' => $validation->get_error_message(),  
  129. ) ); 
  130.  
  131. wp_redirect( admin_url( 'admin.php' ) . '?page=yst_ga_settings#top#' . $return_tab, 301 ); 
  132. exit; 
  133.  
  134. /** 
  135. * Validates the settings in the `options` attribute, returns an WP_Error object on error 
  136. * @return true|WP_Error true or an error object. 
  137. */ 
  138. protected function validate_settings() { 
  139.  
  140. if ( ! empty( $this->options['manual_ua_code_field'] ) ) { 
  141. $this->options['manual_ua_code_field'] = trim( $this->options['manual_ua_code_field'] ); 
  142. // en dash to minus, prevents issue with code copied from web with "fancy" dash 
  143. $this->options['manual_ua_code_field'] = str_replace( '*', '-', $this->options['manual_ua_code_field'] ); 
  144.  
  145. // Regex to tests if a valid UA code has been set. Valid codes follow: "UA-[4 digits]-[at least 1 digit]". 
  146. if ( ! preg_match( '|^UA-\d{4, }-\d+$|', $this->options['manual_ua_code_field'] ) ) { 
  147.  
  148. return new WP_Error( 
  149. 'ua-code-format',  
  150. __( 'The UA code needs to follow UA-XXXXXXXX-X format.', 'google-analytics-for-wordpress' ) 
  151. ); 
  152.  
  153. /** 
  154. * Filters the validation for the admin options 
  155. * @param true|WP_Error true if the validation is successful, WP_Error on error. 
  156. * @param array $this->options The options that are being saved. 
  157. */ 
  158. return apply_filters( 'yst_ga_admin_validate_settings', true, $this->options ); 
  159.  
  160. /** 
  161. * Run a this deactivation hook on deactivation of GA. When this happens we'll 
  162. * remove the options for the profiles and the refresh token. 
  163. */ 
  164. public static function ga_deactivation_hook() { 
  165. // Remove the refresh token and other API settings 
  166. self::analytics_api_clean_up(); 
  167.  
  168. /** 
  169. * Handle a default setting in GA 
  170. * @param array $data 
  171. * @param string $option_name 
  172. * @param mixed $value 
  173. */ 
  174. private function handle_default_setting( $data, $option_name, $value ) { 
  175. if ( ! isset( $data[ $option_name ] ) ) { 
  176. // If no data was passed in, set it to the default. 
  177. if ( $value === 1 ) { 
  178. // Disable the checkbox for now, use value 0 
  179. $this->options[ $option_name ] = 0; 
  180. else { 
  181. $this->options[ $option_name ] = $value; 
  182.  
  183. /** 
  184. * Handle the post requests in the admin form of the GA plugin 
  185. * @param Yoast_GA_Dashboards $dashboards 
  186. */ 
  187. private function handle_ga_post_request( $dashboards ) { 
  188. if ( ! function_exists( 'wp_verify_nonce' ) ) { 
  189. require_once( ABSPATH . 'wp-includes/pluggable.php' ); 
  190.  
  191. if ( isset( $_POST['ga-form-settings'] ) && wp_verify_nonce( $_POST['yoast_ga_nonce'], 'save_settings' ) ) { 
  192. if ( ! isset ( $_POST['ignore_users'] ) ) { 
  193. $_POST['ignore_users'] = array(); 
  194.  
  195. $dashboards_disabled = Yoast_GA_Settings::get_instance()->dashboards_disabled(); 
  196.  
  197. if ( ( $dashboards_disabled == false && isset( $_POST['dashboards_disabled'] ) ) || $this->ga_profile_changed( $_POST ) ) { 
  198. $dashboards->reset_dashboards_data(); 
  199.  
  200. // Post submitted and verified with our nonce 
  201. $this->save_settings( $_POST ); 
  202.  
  203. /** 
  204. * Is there selected an other property in the settings post? Returns true or false. 
  205. * @param array $post 
  206. * @return bool 
  207. */ 
  208. private function ga_profile_changed( $post ) { 
  209. if ( isset( $post['analytics_profile'] ) && isset( $this->options['analytics_profile'] ) ) { 
  210. if ( $post['analytics_profile'] != $this->options['analytics_profile'] ) { 
  211. return true; 
  212.  
  213. return false; 
  214.  
  215. /** 
  216. * Are we allowed to show a warning message? returns true if it's allowed 
  217. * @return bool 
  218. */ 
  219. private function show_admin_warning() { 
  220. return ( current_user_can( 'manage_options' ) && ( ! isset( $_GET['page'] ) || ( isset( $_GET['page'] ) && $_GET['page'] !== 'yst_ga_settings' ) ) ); 
  221.  
  222. /** 
  223. * Are we allowed to show a warning message? returns true if it's allowed ( this is meant to be only for dashboard ) 
  224. * @return bool 
  225. */ 
  226. private function show_admin_dashboard_warning() { 
  227. return ( current_user_can( 'manage_options' ) && isset( $_GET['page'] ) && $_GET['page'] === 'yst_ga_dashboard' ); 
  228.  
  229. /** 
  230. * Transform the Profile ID into an helpful UA code 
  231. * @param integer $profile_id 
  232. * @return null 
  233. */ 
  234. private function get_ua_code_from_profile( $profile_id ) { 
  235. $profiles = $this->get_profiles(); 
  236. $ua_code = null; 
  237.  
  238. foreach ( $profiles as $account ) { 
  239. foreach ( $account['items'] as $profile ) { 
  240. foreach ( $profile['items'] as $subprofile ) { 
  241. if ( isset( $subprofile['id'] ) && $subprofile['id'] === $profile_id ) { 
  242. return $subprofile['ua_code']; 
  243.  
  244. return $ua_code; 
  245.  
  246. /** 
  247. * Add a link to the settings page to the plugins list 
  248. * @param array $links array of links for the plugins, adapted when the current plugin is found. 
  249. * @return array $links 
  250. */ 
  251. public function add_action_links( $links ) { 
  252. // add link to knowledgebase 
  253. // @todo UTM link fix 
  254. $faq_link = '<a title="Yoast Knowledge Base" href="http://kb.yoast.com/category/43-google-analytics-for-wordpress">' . __( 'FAQ', 'google-analytics-for-wordpress' ) . '</a>'; 
  255. array_unshift( $links, $faq_link ); 
  256.  
  257. $settings_link = '<a href="' . esc_url( admin_url( 'admin.php?page=yst_ga_settings' ) ) . '">' . __( 'Settings', 'google-analytics-for-wordpress' ) . '</a>'; 
  258. array_unshift( $links, $settings_link ); 
  259.  
  260. return $links; 
  261.  
  262. /** 
  263. * Adds some promo text for the premium plugin on the custom dimensions tab. 
  264. */ 
  265. public function premium_promo() { 
  266. echo '<div class="ga-promote">'; 
  267. echo '<p>'; 
  268. printf( __( 'If you want to track custom dimensions like page views per author or post type, you should upgrade to the %1$spremium version of Google Analytics by Yoast%2$s.', 'google-analytics-for-wordpress' ), '<a href="https://yoast.com/wordpress/plugins/google-analytics/#utm_medium=text-link&utm_source=gawp-config&utm_campaign=wpgaplugin&utm_content=custom_dimensions_tab">', '</a>' ); 
  269. echo ' '; 
  270. _e( 'This will also give you email access to the support team at Yoast, who will provide support on the plugin 24/7.', 'google-analytics-for-wordpress' ); 
  271. echo '</p>'; 
  272. echo '</div>'; 
  273.  
  274. /** 
  275. * Initialize the promo class for our translate site 
  276. * @return yoast_i18n 
  277. */ 
  278. public function translate_promo() { 
  279. $yoast_ga_i18n = new yoast_i18n( 
  280. array( 
  281. 'textdomain' => 'google-analytics-for-wordpress',  
  282. 'project_slug' => 'google-analytics-for-wordpress',  
  283. 'plugin_name' => 'Google Analytics by Yoast',  
  284. 'hook' => 'yoast_ga_admin_footer',  
  285. 'glotpress_url' => 'https://translate.yoast.com',  
  286. 'glotpress_name' => 'Yoast Translate',  
  287. 'glotpress_logo' => 'https://cdn.yoast.com/wp-content/uploads/i18n-images/Yoast_Translate.svg',  
  288. 'register_url ' => 'https://translate.yoast.com/projects#utm_source=plugin&utm_medium=promo-box&utm_campaign=yoast-ga-i18n-promo',  
  289. ); 
  290.  
  291. return $yoast_ga_i18n; 
  292.  
  293. /** 
  294. * Load the page of a menu item in the GA plugin 
  295. */ 
  296. public function load_page() { 
  297.  
  298. $this->translate_promo(); 
  299.  
  300. if ( ! has_action( 'yst_ga_custom_dimensions_tab-content' ) ) { 
  301. add_action( 'yst_ga_custom_dimensions_tab-content', array( $this, 'premium_promo' ) ); 
  302.  
  303. if ( ! has_action( 'yst_ga_custom_dimension_add-dashboards-tab' ) ) { 
  304. add_action( 'yst_ga_custom_dimension_add-dashboards-tab', array( $this, 'premium_promo' ) ); 
  305.  
  306. switch ( filter_input( INPUT_GET, 'page' ) ) { 
  307. case 'yst_ga_settings': 
  308. require_once( $this->plugin_path . 'admin/pages/settings.php' ); 
  309. break; 
  310. case 'yst_ga_extensions': 
  311. require_once( $this->plugin_path . 'admin/pages/extensions.php' ); 
  312. break; 
  313. case 'yst_ga_dashboard': 
  314. default: 
  315. require_once( $this->plugin_path . 'admin/pages/dashboard.php' ); 
  316. break; 
  317.  
  318.  
  319. /** 
  320. * Get the Google Analytics profiles which are in this google account 
  321. * @return array 
  322. */ 
  323. public function get_profiles() { 
  324. $return = Yoast_Google_Analytics::get_instance()->get_profiles(); 
  325.  
  326. return $return; 
  327.  
  328. /** 
  329. * Checks if there is a callback to get token from Google Analytics API 
  330. */ 
  331. private function google_analytics_listener() { 
  332. $google_auth_code = filter_input( INPUT_POST, 'google_auth_code' ); 
  333. if ( $google_auth_code && current_user_can( 'manage_options' ) && wp_verify_nonce( filter_input( INPUT_POST, 'yoast_ga_nonce' ), 'save_settings' ) ) { 
  334. self::analytics_api_clean_up(); 
  335.  
  336. Yoast_Google_Analytics::get_instance()->authenticate( trim( $google_auth_code ) ); 
  337.  
  338. /** 
  339. * Clean up the Analytics API settings 
  340. */ 
  341. public static function analytics_api_clean_up() { 
  342. delete_option( 'yoast-ga-refresh_token' ); 
  343. delete_option( 'yst_ga_api_call_fail' ); 
  344. delete_option( 'yst_ga_last_wp_run' ); 
  345. delete_option( 'yst_ga_api' ); 
  346.  
  347. /** 
  348. * Get the current GA profile 
  349. * @return null 
  350. */ 
  351. private function get_current_profile() { 
  352. if ( ! empty( $this->options['analytics_profile'] ) ) { 
  353. return $this->options['analytics_profile']; 
  354.  
  355. return null; 
  356.  
  357. /** 
  358. * Get the user roles of this WordPress blog 
  359. * @return array 
  360. */ 
  361. public function get_userroles() { 
  362. global $wp_roles; 
  363.  
  364. $all_roles = $wp_roles->roles; 
  365. $roles = array(); 
  366.  
  367. /** 
  368. * Filter: 'editable_roles' - Allows filtering of the roles shown within the plugin (and elsewhere in WP as it's a WP filter) 
  369. * @api array $all_roles 
  370. */ 
  371. $editable_roles = apply_filters( 'editable_roles', $all_roles ); 
  372.  
  373. foreach ( $editable_roles as $id => $name ) { 
  374. $roles[] = array( 
  375. 'id' => $id,  
  376. 'name' => translate_user_role( $name['name'] ),  
  377. ); 
  378.  
  379. return $roles; 
  380.  
  381. /** 
  382. * Get types of how we can track downloads 
  383. * @return array 
  384. */ 
  385. public function track_download_types() { 
  386. return array( 
  387. 0 => array( 'id' => 'event', 'name' => __( 'Event', 'google-analytics-for-wordpress' ) ),  
  388. 1 => array( 'id' => 'pageview', 'name' => __( 'Pageview', 'google-analytics-for-wordpress' ) ),  
  389. ); 
  390.  
  391. /** 
  392. * Get options for the track full url or links setting 
  393. * @return array 
  394. */ 
  395. public function get_track_full_url() { 
  396. return array( 
  397. 0 => array( 'id' => 'domain', 'name' => __( 'Just the domain', 'google-analytics-for-wordpress' ) ),  
  398. 1 => array( 'id' => 'full_links', 'name' => __( 'Full links', 'google-analytics-for-wordpress' ) ),  
  399. ); 
  400.  
  401. /** 
  402. * Render the admin page head for the GA Plugin 
  403. */ 
  404. public function content_head() { 
  405. require 'views/content_head.php'; 
  406.  
  407. /** 
  408. * Render the admin page footer with sidebar for the GA Plugin 
  409. */ 
  410. public function content_footer() { 
  411.  
  412. do_action( 'yoast_ga_admin_footer' ); 
  413.  
  414. if ( true == WP_DEBUG ) { 
  415. // Show the debug information if debug is enabled in the wp_config file 
  416. echo '<div id="ga-debug-info" class="postbox"><h3 class="hndle"><span>' . __( 'Debug information', 'google-analytics-for-wordpress' ) . '</span></h3><div class="inside"><pre>'; 
  417. var_dump( $this->options ); 
  418. echo '</pre></div></div>'; 
  419.  
  420. if ( class_exists( 'Yoast_Product_GA_Premium' ) ) { 
  421. $license_manager = new Yoast_Plugin_License_Manager( new Yoast_Product_GA_Premium() ); 
  422. if ( $license_manager->license_is_valid() ) { 
  423. return; 
  424.  
  425. $banners = array(); 
  426. $banners[] = array( 
  427. 'url' => 'https://yoast.com/hire-us/website-review/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',  
  428. 'banner' => $this->plugin_url . 'assets/img/banner-website-review.png',  
  429. 'title' => 'Get a website review by Yoast',  
  430. ); 
  431. $banners[] = array( 
  432. 'url' => 'https://yoast.com/wordpress/plugins/google-analytics/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',  
  433. 'banner' => $this->plugin_url . 'assets/img/banner-premium-ga.png',  
  434. 'title' => 'Get the premium version of Google Analytics by Yoast!',  
  435. ); 
  436. $banners[] = array( 
  437. 'url' => 'https://yoast.com/ebook-optimize-wordpress-site/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',  
  438. 'banner' => $this->plugin_url . 'assets/img/eBook_261x130.png',  
  439. 'title' => 'Get the Yoast ebook!',  
  440. ); 
  441. $banners[] = array( 
  442. 'url' => 'https://yoast.com/wordpress/plugins/ga-ecommerce/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',  
  443. 'banner' => $this->plugin_url . 'assets/img/banner-ga-ecommerce.png',  
  444. 'title' => 'Get advanced eCommerce tracking for WooCommerce and Easy Digital Downloads!',  
  445. ); 
  446.  
  447. shuffle( $banners ); 
  448.  
  449. require 'views/content-footer.php'; 
  450.  
  451.  
  452. /** 
  453. * Returns a list of all available extensions 
  454. * @return array 
  455. */ 
  456. public function get_extensions() { 
  457. $extensions = array( 
  458. 'ga_premium' => (object) array( 
  459. 'url' => 'https://yoast.com/wordpress/plugins/google-analytics/',  
  460. 'title' => __( 'Google Analytics by Yoast Premium', 'google-analytics-for-wordpress' ),  
  461. 'desc' => __( 'The premium version of Google Analytics by Yoast with more features and support.', 'google-analytics-for-wordpress' ),  
  462. 'status' => 'uninstalled',  
  463. ),  
  464. 'ecommerce' => (object) array( 
  465. 'url' => 'https://yoast.com/wordpress/plugins/ga-ecommerce/',  
  466. 'title' => __( 'Google Analytics by Yoast', 'google-analytics-for-wordpress' ) . '<br />' . __( 'eCommerce tracking', 'google-analytics-for-wordpress' ),  
  467. 'desc' => __( 'Track your eCommerce data and transactions with this eCommerce extension for Google Analytics.', 'google-analytics-for-wordpress' ),  
  468. 'status' => 'uninstalled',  
  469. ),  
  470. ); 
  471.  
  472. $extensions = apply_filters( 'yst_ga_extension_status', $extensions ); 
  473.  
  474. return $extensions; 
  475.  
  476. /** 
  477. * Add a notification to the notification transient 
  478. * @param string $transient_name 
  479. * @param array $settings 
  480. */ 
  481. private function add_notification( $transient_name, $settings ) { 
  482. set_transient( $transient_name, $settings, MINUTE_IN_SECONDS ); 
  483.  
  484. /** 
  485. * Show the notification that should be set, after showing the notification this function unset the transient 
  486. * @param string $transient_name The name of the transient which contains the notification 
  487. */ 
  488. public function show_notification( $transient_name ) { 
  489. $transient = get_transient( $transient_name ); 
  490.  
  491. if ( isset( $transient['type'] ) && isset( $transient['description'] ) ) { 
  492. if ( $transient['type'] == 'success' ) { 
  493. add_settings_error( 
  494. 'yoast_google_analytics',  
  495. 'yoast_google_analytics',  
  496. $transient['description'],  
  497. 'updated' 
  498. ); 
  499. else { 
  500. add_settings_error( 
  501. 'yoast_google_analytics',  
  502. 'yoast_google_analytics',  
  503. $transient['description'],  
  504. 'error' 
  505. ); 
  506.  
  507. delete_transient( $transient_name ); 
  508.  
  509. /** 
  510. * Check if there the aggregate data cron is executed 
  511. * @return bool 
  512. */ 
  513. private function is_running_cron() { 
  514. return doing_action( 'yst_ga_aggregate_data' ) && defined( 'DOING_CRON' ) && DOING_CRON; 
  515.  
  516. /** 
  517. * Check if there the aggregate data cron is executed 
  518. * @return bool 
  519. */ 
  520. private function is_running_ajax() { 
  521. return defined( 'DOING_AJAX' ) && DOING_AJAX && strpos( filter_input( INPUT_GET, 'action' ), 'yoast_dashboard' ) === 0; 
  522.