MonsterInsights_GA

The Google Analytics for WordPress by MonsterInsights MonsterInsights GA class.

Defined (1)

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

/includes/admin/google.php  
  1. final class MonsterInsights_GA { 
  2.  
  3. /** 
  4. * Holds the GA client object if using oAuth. 
  5. * @access public 
  6. * @since 6.0.0 
  7. * @var MonsterInsights_GA_Client $client GA client object. 
  8. */ 
  9. public $client; 
  10.  
  11. /** 
  12. * Google Profile ID. 
  13. * @access public 
  14. * @since 6.0.0 
  15. * @var int $profile ID of profile in use. 
  16. */ 
  17. public $profile; 
  18.  
  19. /** 
  20. * Google UA code. 
  21. * @access public 
  22. * @since 6.0.0 
  23. * @var string|false $ua Google UA code for the current profile if valid oAuth in use, else false. 
  24. */ 
  25. public $ua; 
  26.  
  27. /** 
  28. * Google profile name. 
  29. * @access public 
  30. * @since 6.0.0 
  31. * @var string|false $ua Google profile name for the current profile if valid oAuth in use, else false. 
  32. */ 
  33. public $name; 
  34.  
  35. /** 
  36. * Status of Google client object. 
  37. * @access public 
  38. * @since 6.0.0 
  39. * @var string $status Possible values include manual, expired, valid, needs-permissions, blocked and none. 
  40. */ 
  41. public $status; 
  42.  
  43. /** 
  44. * oAuth Permissions Version. 
  45. * @access public 
  46. * @since 6.0.0 
  47. * @var string $oauth_version Version of oAuth permissions granted. 
  48. */ 
  49. public $oauth_version;  
  50.  
  51. /** 
  52. * Holds the base object. 
  53. * @access public 
  54. * @since 6.0.0 
  55. * @var MonsterInsights $base MonsterInsights Base object. 
  56. */ 
  57. public $base; 
  58.  
  59. /** 
  60. * Primary class constructor. 
  61. * @access public 
  62. * @since 6.0.0 
  63. */ 
  64. public function __construct() { 
  65. // Get object  
  66. $this->client = $this->get_client(); 
  67. $this->profile = $this->get_profile(); 
  68. $this->ua = $this->get_ua(); 
  69. $this->name = $this->get_name(); 
  70. $this->oauth_version = $this->get_oauth_version(); 
  71. $this->status = $this->get_status(); 
  72. $this->base = MonsterInsights(); 
  73.  
  74.  
  75. // Show any info/error notices 
  76. $this->get_notices(); 
  77.  
  78. // Authentication Actions 
  79. add_action( 'wp_ajax_monsterinsights_google_view', array( $this, 'google_auth_view' ) ); 
  80. add_action( 'wp_ajax_monsterinsights_google_cancel', array( $this, 'google_cancel' ) ); 
  81.  
  82. add_action( 'admin_init', array( $this, 'deactivate_google' ) ); // Deactivate 
  83.  
  84. private function get_client() { 
  85. return ! empty( $this->client ) ? $this->client : monsterinsights_create_client(); 
  86.  
  87. private function set_test_client() {  
  88. $this->client = monsterinsights_create_test_client(); 
  89.  
  90. private function set_client() {  
  91. $this->client = monsterinsights_create_client(); 
  92.  
  93. /** 
  94. * Get the current GA profile 
  95. * @return null 
  96. */ 
  97. private function get_profile() { 
  98. return monsterinsights_get_option( 'analytics_profile', false ); 
  99.  
  100. private function get_name() { 
  101. return monsterinsights_get_option( 'analytics_profile_name', false ); 
  102.  
  103. private function get_ua() { 
  104. return monsterinsights_get_ua(); 
  105.  
  106. private function get_oauth_version() { 
  107. return monsterinsights_get_option( 'oauth_version', '1.0' ); 
  108.  
  109. private function get_status() { 
  110. $status = 'valid'; 
  111. if ( ! empty( $this->profile ) ) { 
  112. // We are using oAuth 
  113.  
  114. $last_run = monsterinsights_get_option( 'cron_last_run', false ); 
  115. $failed = monsterinsights_get_option( 'cron_failed', false ); 
  116. $dash_dis = monsterinsights_get_option( 'dashboards_disabled', false ); 
  117.  
  118. // See if issue connecting or expired 
  119. if ( ! $dash_dis && $failed && ( $last_run === false || monsterinsights_hours_between( $last_run ) >= 48 ) ) {  
  120. $status = 'blocked'; 
  121.  
  122. $access_token = $this->client->get_access_token(); 
  123.  
  124. // Check to make sure access token is there and not expired 
  125. if ( empty( $access_token ) || empty( $access_token['expires'] ) || current_time( 'timestamp' ) >= $access_token['expires'] ) { 
  126. $status = 'expired'; 
  127. return $status; 
  128.  
  129. // See if needs permissions 
  130. if ( version_compare( $this->oauth_version, '1.0', '<' ) ) {  
  131. $status = 'needs-permissions'; 
  132.  
  133. } else if ( ! empty( $this->ua ) ) { 
  134. // We are using manual 
  135.  
  136. } else { 
  137. // We do not have oAuth or manual active 
  138. $status = 'empty'; 
  139.  
  140. return $status; 
  141.  
  142. private function get_notices() { 
  143. // Notice for no manual or profile GA 
  144. if ( $this->status === 'empty' ) { 
  145. add_action( 'admin_notices', array( $this, 'monsterinsights_show_admin_config_empty_notice' ) ); 
  146.  
  147. $current_page = filter_input( INPUT_GET, 'page' ); 
  148.  
  149. // Only show expired, needs permission, or blocked notices on the MI pages 
  150. // We do this because unlike status empty, these only block reporting, not the frontend 
  151. // tracking from working, and as a result, these are not as urgent. Plus users generally 
  152. // don't like global notices. 
  153. if ( strpos( $current_page, 'monsterinsights' ) === 0 ) { 
  154.  
  155. // Notice for GA Access token expired (needs re-authenticate) 
  156. if ( $this->status === 'expired' ) { 
  157. add_action( 'admin_notices', array( $this, 'monsterinsights_show_admin_config_expired_notice' ) ); 
  158.  
  159. // Notice for Needs Permissions 
  160. if ( $this->status === 'needs-permissions' ) { 
  161. add_action( 'admin_notices', array( $this, 'monsterinsights_show_admin_config_needs_permissions_notice' ) ); 
  162.  
  163. // Notice for trouble connecting to Google 
  164. if ( $this->status === 'blocked' ) { 
  165. add_action( 'admin_notices', array( $this, 'monsterinsights_show_admin_config_blocked_notice' ) ); 
  166.  
  167. /** 
  168. * Used when switching GA profiles, or switching 
  169. * to/from oAuth <--> manual, or when reauthenticating 
  170. * or deleting GA profile. 
  171. * @return null 
  172. */ 
  173. private function reinitialize() {  
  174. // Get object  
  175. $this->client = $this->get_client(); 
  176. $this->profile = $this->get_profile(); 
  177. $this->ua = $this->get_ua(); 
  178. $this->name = $this->get_name(); 
  179. $this->oauth_version = $this->get_oauth_version(); 
  180. $this->status = $this->get_status(); 
  181.  
  182. // Re-get data if possible 
  183. if ( $this->ua === 'valid' ) { 
  184. $this->refresh_dashboard_data(); 
  185.  
  186. public function create_auth_url() { 
  187. return $this->client->createAuthUrl(); 
  188.  
  189. /** 
  190. * Getting the analytics profiles 
  191. * Doing the request to the Google analytics API and if there is a response, parses this response and return its 
  192. * array 
  193. * @return array 
  194. */ 
  195. public function get_profiles() { // @todo: this needs exception handling for a 401 login required  
  196. $accounts = $this->get_profiles_request(); 
  197. if ( is_array( $accounts ) ) { 
  198. return $accounts; 
  199. } else { 
  200. return array(); 
  201.  
  202. public function find_selected_profile( $profile_id ) { 
  203. $profiles = $this->get_profiles(); 
  204. $found = array(); 
  205. foreach ( $profiles as $account ) { 
  206. foreach ( $account['items'] as $profile ) { 
  207. foreach ( $profile['items'] as $subprofile ) { 
  208. if ( isset( $subprofile['id'] ) && $subprofile['id'] == $profile_id ) { 
  209. $found = array( 
  210. 'id' => $profile_id,  
  211. 'ua' => $subprofile['ua_code'],  
  212. 'name' => $subprofile['name'],  
  213.  
  214. ); 
  215. break 3; 
  216. return $found; 
  217.  
  218. public function save_selected_profile( $profile ) { 
  219. monsterinsights_update_option( 'analytics_profile', $profile['id'] ); 
  220. monsterinsights_update_option( 'analytics_profile_code', $profile['ua'] ); 
  221. monsterinsights_update_option( 'analytics_profile_name', $profile['name'] ); 
  222. monsterinsights_set_client_oauth_version(); 
  223.  
  224.  
  225. /** 
  226. * Get accounts request 
  227. * @param array $response 
  228. * @return mixed 
  229. */ 
  230. private function get_profiles_request() { 
  231. global $wp_version; 
  232. $version = str_replace( '-src', '', $wp_version ); 
  233. $accounts = array(); 
  234. $start_index = 1; 
  235. $paginate = false; 
  236. $continue = true; 
  237. while ( $continue ) { 
  238. $body = array( 
  239. 'max-results' => 1000,  
  240. 'start-index' => $paginate ? $start_index + 1000 : $start_index,  
  241. ); 
  242. if ( $paginate ) { 
  243. $start_index = $start_index + 1000; 
  244. $response = $this->client->do_request( 'https://www.googleapis.com/analytics/v3/management/accounts/~all/webproperties/~all/profiles', false, 'GET', $body ); 
  245. if ( ! empty( $response ) ) { 
  246. $response = array( 
  247. 'response' => array( 'code' => $this->client->get_http_response_code() ),  
  248. 'body' => json_decode( $response->getResponseBody(), true ),  
  249. ); 
  250. } else { 
  251. if ( version_compare( $version, '4.6', '<' ) ) { 
  252. return esc_html__( 'MonsterInsights requires WordPress version 4.6 or newer to use oAuth. Please update your WordPress version.', 'google-analytics-for-wordpress' ); 
  253. } else { 
  254. if ( ! empty( $accounts ) ) { 
  255. return $accounts; 
  256. } else { 
  257. return esc_html__( 'Google Analytics had a connection error or your Google account is not signed up for Google Analytics.', 'google-analytics-for-wordpress' ); 
  258.  
  259. if ( isset( $response['response']['code'] ) && $response['response']['code'] == 200 ) { 
  260. if ( ! empty( $response['body']['items'] ) && is_array( $response['body']['items'] ) ) { 
  261. foreach ( $response['body']['items'] as $item ) { 
  262.  
  263. // Only deal with web properties, not apps. 
  264. if ( isset( $item['type'] ) && 'WEB' != $item['type'] ) { 
  265. continue; 
  266.  
  267. if ( empty( $accounts[ $item['accountId'] ] ) ) { 
  268. $accounts[ $item['accountId'] ] = array(  
  269. 'id' => $item['accountId'],  
  270. 'ua_code' => $item['webPropertyId'],  
  271. 'parent_name' => $item['websiteUrl'],  
  272. 'items' => array(),  
  273. ); 
  274.  
  275. if ( empty( $accounts[ $item['accountId'] ]['items'][ $item['internalWebPropertyId'] ] ) ) { 
  276. $accounts[ $item['accountId'] ]['items'][ $item['internalWebPropertyId'] ]= array(  
  277. 'id' => $item['webPropertyId'],  
  278. 'name' => $item['websiteUrl'],  
  279. 'items' => array(),  
  280. ); 
  281.  
  282. if ( empty( $accounts[ $item['accountId'] ]['items'][ $item['internalWebPropertyId'] ]['items'][ $item['id'] ] ) ) { 
  283. $accounts[ $item['accountId'] ]['items'][ $item['internalWebPropertyId'] ]['items'][ $item['id'] ] = array(  
  284. 'name' => $item['name'] . ' (' . $item['webPropertyId'] . ')',  
  285. 'ua_code' => $item['webPropertyId'],  
  286. 'id' => $item['id'],  
  287. ); 
  288. } else if ( isset( $response['response']['code'] ) && $response['response']['code'] !== 200 && ! $paginate ) { 
  289. if ( version_compare( $version, '4.6', '<' ) ) { 
  290. return esc_html__( 'MonsterInsights requires WordPress version 4.6 or newer to use oAuth. Please update your WordPress version.', 'google-analytics-for-wordpress' ); 
  291. } else { 
  292. if ( ! empty( $accounts ) ) { 
  293. return $accounts; 
  294. } else { 
  295. $code = isset( $response['response']['code'] ) ? $response['response']['code'] : 'Unknown'; 
  296. $type = isset( $response['body']['error']['errors'][0]['reason'] ) ? $response['body']['error']['errors'][0]['reason'] : false; 
  297. if ( $type === 'insufficientPermissions' ) { 
  298. return esc_html__( 'Please ensure your Google Account is signed up for Google Analytics.', 'google-analytics-for-wordpress' ); 
  299. } else if ( $type === 'badRequest' ) { 
  300. return esc_html__( 'Bad Request. Please contact support.', 'google-analytics-for-wordpress' ); 
  301. } else if ( $type === 'dailyLimitExceeded' ) { 
  302. return esc_html__( 'Daily Limit Exceeded. Please contact support.', 'google-analytics-for-wordpress' ); 
  303. } else if ( $type === 'userRateLimitExceeded' ) { 
  304. return esc_html__( 'User Rate Limit Exceeded. Wait 2 minutes and then try again.', 'google-analytics-for-wordpress' ); 
  305. } else if ( $type === 'rateLimitExceeded' ) { 
  306. return esc_html__( 'Project Rate Limit Exceeded. Wait 2 minutes and then try again.', 'google-analytics-for-wordpress' ); 
  307. } else if ( $type === 'quotaExceeded' ) { 
  308. return esc_html__( 'Project Rate Limit Quota Exceeded. Wait 2 minutes and then try again.', 'google-analytics-for-wordpress' ); 
  309. } else if ( $type === 'internalServerError' || $type === 'backendError' ) { 
  310. return esc_html__( 'Google Analytics is having API issues on their side. Wait 2 minutes and then try again.', 'google-analytics-for-wordpress' ); 
  311. } else { 
  312. return sprintf( esc_html__( 'Google Analytics had a connection error. Error code: %1$s. Reason: %2$s', 'google-analytics-for-wordpress' ), $code, $type ); 
  313.  
  314. if ( isset( $response['body']['totalResults'] ) && $start_index < $response['body']['totalResults'] && ! empty( $response['body']['nextLink'] ) ) { 
  315. $paginate = true; 
  316. } else { 
  317. $continue = false; 
  318. return $accounts; 
  319.  
  320. private function clear_oauth_data() { 
  321. // Delete the stored profiles 
  322. $options = array( 
  323. 'analytics_profile_code',  
  324. 'analytics_profile',  
  325. 'analytics_profile_name',  
  326. 'oauth_version',  
  327. 'cron_failed',  
  328. 'cron_last_run',  
  329. ); 
  330. monsterinsights_delete_options( $options ); 
  331.  
  332. // Destroy the data 
  333. $this->base->reports->delete_aggregate_data(); 
  334.  
  335. $this->client->clear_data(); 
  336.  
  337. private function clear_manual_data() { 
  338. // Delete the manual ua code 
  339. monsterinsights_delete_option( 'manual_ua_code' ); 
  340.  
  341. public function deactivate_google() { 
  342. // Check if user pressed the deactivate button and nonce is valid 
  343. if ( ! isset( $_POST['monsterinsights-google-deauthenticate-submit'] ) ) { 
  344. return; 
  345.  
  346. if ( ! wp_verify_nonce( $_POST['monsterinsights-google-authenticated-nonce'], 'monsterinsights-google-authenticated-nonce' ) ) { 
  347. return; 
  348.  
  349. if ( ! current_user_can( 'monsterinsights_save_settings' ) ) { 
  350. return; 
  351.  
  352. // Destroy the client 
  353. $this->clear_oauth_data(); 
  354.  
  355. // Refresh the client 
  356. $this->reinitialize(); 
  357.  
  358. public function refresh_dashboard_data( ) { 
  359. // Destroy the data 
  360. $this->base->reports->delete_aggregate_data(); 
  361.  
  362. $this->base->reports->run_cron(); 
  363.  
  364. /** 
  365. * Check if client has a refresh token 
  366. * @return bool 
  367. */ 
  368. public function has_refresh_token() { 
  369. return $this->client->is_authenticated(); 
  370.  
  371. /** 
  372. * Doing request to Google Analytics 
  373. * This method will do a request to google and get the response code and body from content 
  374. * @param string $target_request_url 
  375. * @return array|null 
  376. */ 
  377. public function do_request( $target_request_url ) { 
  378. $response = $this->client->do_request( $target_request_url ); 
  379. if ( ! empty( $response ) ) { 
  380. return array( 
  381. 'response' => array( 'code' => $this->client->get_http_response_code() ),  
  382. 'body' => json_decode( $response->getResponseBody(), true ),  
  383. ); 
  384.  
  385. /** 
  386. * Wrapper for authenticate the client. If authentication code is send it will get and check an access token. 
  387. * @param mixed $authentication_code 
  388. * @return boolean 
  389. */ 
  390. public function authenticate( $authentication_code = null ) { 
  391. // When authentication again we should clean up some stuff 
  392. monsterinsights_delete_options( array( 'cron_last_run', 'cron_failed' ) ); 
  393. return $this->client->authenticate_client( $authentication_code ); 
  394.  
  395. public function google_auth_view() { 
  396. $view = isset( $_POST['view'] ) && in_array( $_POST['view'], array( 'prestart', 'start', 'enterkey', 'selectprofile', 'done' ) ) ? $_POST['view'] : ''; 
  397. $reauth = isset( $_POST['reauth'] ) && $_POST['reauth'] && $_POST['reauth'] !== 'false' ? true : false; 
  398.  
  399. if ( ! current_user_can( 'monsterinsights_save_settings' ) ) { 
  400. echo esc_html__( 'Permission Denied', 'google-analytics-for-wordpress'); 
  401. wp_die(); 
  402.  
  403. // We run the save routines, if required, for a view, and then after that send back the results + next view 
  404. $nextview = array(); 
  405.  
  406. switch ( $view ) { 
  407. case 'start': 
  408. if ( ! $this->is_wp_blocking_google() && ! $this->is_google_on_blacklist() ) { 
  409. $auth_url = $this->create_auth_url(); 
  410. $nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url ); 
  411. } else { 
  412. $error = esc_html__( 'Cannot connect to Google', 'google-analytics-for-wordpress' ); 
  413. $nextview = monsterinsights_google_auth_error_view( $reauth, $error ); 
  414. break; 
  415.  
  416. case 'enterkey': 
  417. $auth_key = ! empty( $_POST['stepdata'] ) ? sanitize_text_field( $_POST['stepdata'] ) : ''; 
  418. if ( $auth_key ) { 
  419. if ( $this->test_authkey( $auth_key ) ) { 
  420. $profiles = $this->get_profiles_request(); 
  421. delete_option( 'monsterinsights_get_profiles' ); 
  422. update_option( 'monsterinsights_get_profiles', $profiles ); 
  423. if ( ! empty( $profiles ) && is_array( $profiles ) ) { 
  424. $select = $this->ga_select( $profiles ); 
  425. $nextview = monsterinsights_google_auth_selectprofile_view( $reauth, $select ); 
  426. } else if ( ! empty( $profiles ) && is_string( $profiles ) ) { 
  427. // Error from Google 
  428. $auth_url = $this->create_auth_url(); 
  429. $this->client->clear_data(); 
  430. $this->set_test_client(); 
  431. $nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url, esc_html( $profiles ) ); 
  432. } else { 
  433. // No profiles or not enough permissions 
  434. $auth_url = $this->create_auth_url(); 
  435. $this->client->clear_data(); 
  436. $this->set_test_client(); 
  437. $nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url, esc_html__( 'No profiles viewable for that account. Please use another account.', 'google-analytics-for-wordpress' ) ); 
  438. } else { 
  439. // if bad authentication error message 
  440. $auth_url = $this->create_auth_url(); 
  441. $this->client->clear_data(); 
  442. $this->set_test_client(); 
  443. $nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url, esc_html__( 'Bad Google Code. Please try again.', 'google-analytics-for-wordpress' ) ); 
  444. } else { 
  445. $auth_url = $this->create_auth_url(); 
  446. $this->client->clear_data(); 
  447. $this->set_test_client(); 
  448. // if no auth key error message 
  449. $nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url, esc_html__( 'Please paste in your Google code.', 'google-analytics-for-wordpress' ) ); 
  450. break; 
  451.  
  452. case 'selectprofile': 
  453. $profile = ! empty( $_POST['stepdata'] ) ? absint( sanitize_text_field( $_POST['stepdata'] ) ) : ''; 
  454. if ( ! empty( $profile ) ) { 
  455. $this->set_test_client(); 
  456. $profile = $this->find_selected_profile( $profile ); 
  457. if ( ! empty( $profile ) ) { 
  458.  
  459. $this->clear_manual_data(); // Just in case we were manual, clear out UA 
  460.  
  461. $this->client->move_test_to_live(); 
  462. $this->save_selected_profile( $profile ); 
  463. $this->set_client(); 
  464. $this->reinitialize(); 
  465.  
  466. // Refresh reporting data 
  467. $this->base->reports->refresh_aggregate_data(); 
  468.  
  469. $nextview = monsterinsights_google_auth_done_view( $reauth ); 
  470. } else { 
  471. // Invalid profile selected 
  472. $profiles = get_option( 'monsterinsights_get_profiles', array() ); 
  473. $select = $this->ga_select( $profiles ); 
  474. $nextview = monsterinsights_google_auth_selectprofile_view( $reauth, $select, esc_html__( 'Invalid profile selected.', 'google-analytics-for-wordpress' ) ); 
  475. } else {  
  476. // No profile selected 
  477. $profiles = get_option( 'monsterinsights_get_profiles', array() ); 
  478. $select = $this->ga_select( $profiles ); 
  479. $nextview = monsterinsights_google_auth_selectprofile_view( $reauth, $select, esc_html__( 'Please select a profile.', 'google-analytics-for-wordpress' ) ); 
  480. break; 
  481.  
  482. case 'done': 
  483. $nextview = monsterinsights_google_auth_done_view( $reauth ); 
  484. break; 
  485.  
  486. case 'prestart': 
  487. default: 
  488. $nextview = monsterinsights_google_auth_start_view( $reauth ); 
  489. break; 
  490. echo $nextview; 
  491. wp_die(); 
  492.  
  493. public function google_cancel() { 
  494. $view = isset( $_POST['view'] ) && in_array( $_POST['view'], array( 'prestart', 'start', 'enterkey', 'selectprofile', 'done' ) ) ? $_POST['view'] : ''; 
  495. $reauth = isset( $_POST['reauth'] ) && $_POST['reauth'] && $_POST['reauth'] !== 'false' ? true : false; 
  496.  
  497. if ( ! current_user_can( 'monsterinsights_save_settings' ) ) { 
  498. echo esc_html__( 'Permission Denied', 'google-analytics-for-wordpress'); 
  499. wp_die(); 
  500.  
  501. // If we cancelled on enterkey or selectprofile, delete the temp access tokens and set client back to normal client 
  502. if ( $view === 'enterkey' || $view === 'selectprofile' ) { 
  503. $this->client->clear_data(); 
  504. delete_option( 'monsterinsights_get_profiles' ); 
  505. $this->set_client(); 
  506.  
  507. private function test_authkey( $authkey ) { 
  508. $this->set_test_client(); 
  509. $result = $this->authenticate( $authkey ); 
  510. return $result; 
  511.  
  512. /** 
  513. * Generates the GA select box 
  514. * @return null|string 
  515. */ 
  516. private function ga_select( $profiles = array() ) { 
  517. if ( empty( $profiles ) || ! is_array( $profiles ) ) {  
  518. $profiles = $this->get_profiles(); 
  519.  
  520. $optgroups = array(); 
  521. foreach ( $profiles as $key => $value ) { 
  522. foreach ( $value['items'] as $subitem ) { 
  523. $optgroups[ $subitem['name'] ]['items'] = $subitem['items']; 
  524.  
  525. $values = $optgroups; 
  526. $select = ''; 
  527. $select .= '<div class="monsterinsights_ga_form">'; 
  528. $select .= '<label for="monsterinsights_step_data" id="monsterinsights_select_ga_profile_label">' . esc_html__( 'Analytics profile', 'google-analytics-for-wordpress' ) . ':</label>'; 
  529. $select .= '<select data-placeholder="' . esc_attr__( 'Select a profile', 'google-analytics-for-wordpress' ) . '" name="monsterinsights_step_data" class="monsterinsights-select300 monsterinsights_select_ga_profile" id="monsterinsights_step_data" style="width:80%;margin-left:10%;margin-right:10%;background-color: #FFF;">'; 
  530. $select .= '<option></option>'; 
  531.  
  532. if ( count( $values ) >= 1 ) { 
  533. foreach ( $values as $optgroup => $value ) { 
  534. if ( ! empty( $value['items'] ) ) { 
  535. $select .= $this->create_optgroup( $optgroup, $value ); 
  536. else { 
  537. $select .= '<option value="' . esc_attr( $value['id'] ) . '">' . esc_attr( stripslashes( $value['name'] ) ) . '</option>'; 
  538. $select .= '</select>'; 
  539. $select .= '</div>'; 
  540. return $select; 
  541.  
  542. /** 
  543. * Creates a optgroup with the items. If items contain items it will create a nested optgroup 
  544. * @param string $optgroup 
  545. * @param array $value 
  546. * @param array $select_value 
  547. * @return string 
  548. */ 
  549. private function create_optgroup( $optgroup, $value ) { 
  550. $optgroup = '<optgroup label="' . esc_attr( $optgroup ) . '" disabled>'; 
  551.  
  552. foreach ( $value['items'] as $option ) { 
  553. if ( ! empty( $option['items'] ) ) { 
  554.  
  555. $optgroup .= $this->create_optgroup( esc_attr( $option['name'] ), $option ); 
  556. else { 
  557. $optgroup .= '<option value="' . esc_attr( $option['id'] ) . '">' . esc_attr( stripslashes( $option['name'] ) ) . '</option>'; 
  558.  
  559. $optgroup .= '</optgroup>'; 
  560.  
  561. return $optgroup; 
  562.  
  563. /** 
  564. * See if Google is on the block_request list. 
  565. * @return bool  
  566. */ 
  567. private function is_wp_blocking_google() { 
  568. if ( defined( 'WP_HTTP_BLOCK_EXTERNAL' ) && WP_HTTP_BLOCK_EXTERNAL ) { // @todo: put this in sysinfo  
  569. if ( defined( 'WP_ACCESSIBLE_HOSTS' ) ) { 
  570. $on_blacklist = $this->is_google_on_blacklist(); 
  571. if ( $on_blacklist ) { 
  572. return true; 
  573. } else { 
  574. $params = array( 
  575. 'sslverify' => false,  
  576. 'timeout' => 60,  
  577. 'user-agent' => 'MonsterInsights/' . MONSTERINSIGHTS_VERSION,  
  578. 'body' => '' 
  579. ); 
  580. $response = wp_remote_get( 'https://www.googleapis.com/discovery/v1/apis/analytics/v3/rest', $params ); 
  581. if( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) { 
  582. return false; 
  583. } else { 
  584. return true; 
  585. } else { 
  586. return true; 
  587. } else { 
  588. $params = array( 
  589. 'sslverify' => false,  
  590. 'timeout' => 60,  
  591. 'user-agent' => 'MonsterInsights/' . MONSTERINSIGHTS_VERSION,  
  592. 'body' => '' 
  593. ); 
  594. $response = wp_remote_get( 'https://www.googleapis.com/discovery/v1/apis/analytics/v3/rest', $params ); 
  595.  
  596. if( !is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) { 
  597. return false; 
  598. } else { 
  599. return true; 
  600.  
  601. /** 
  602. * See if Google is on the block_request list. 
  603. * @return bool  
  604. */ 
  605. private function is_google_on_blacklist() { // @todo: put this in sysinfo 
  606. $wp_http = new WP_Http(); 
  607. if ( $wp_http->block_request( 'https://www.googleapis.com/discovery/v1/apis/analytics/v3/rest' ) ) { 
  608. return true; 
  609.  
  610. return false; 
  611.  
  612. public function monsterinsights_show_admin_config_empty_notice() { 
  613. $screen = get_current_screen();  
  614. if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) !== false ) { 
  615. return; 
  616. echo '<div class="error"><p>' .  
  617. sprintf( esc_html__( 'Please configure your %1$sGoogle Analytics settings%2$s!', 'google-analytics-for-wordpress' ),  
  618. '<a href="' . admin_url( 'admin.php?page=monsterinsights_settings' ) . '">',  
  619. '</a>' 
  620. . '</p></div>'; 
  621.  
  622. /** 
  623. * Throw a warning when the fetching failed 
  624. */ 
  625. public function monsterinsights_show_admin_config_expired_notice() { 
  626. echo '<div class="error"><p>' .  
  627. sprintf( 
  628. esc_html__( 'It seems the authentication for the plugin has expired or the connection to Google Analytics is blocked, please try %1$sre-authenticating%2$s with Google Analytics to allow the plugin to fetch data.', 'google-analytics-for-wordpress' ),  
  629. '<a href="' . admin_url( 'admin.php?page=monsterinsights_settings' ) . '">',  
  630. '</a>' 
  631. . '</p></div>'; 
  632.  
  633. /** 
  634. * Throw a warning when the fetching failed 
  635. */ 
  636. public function monsterinsights_show_admin_config_needs_permissions_notice() { 
  637. echo '<div class="error"><p>' .  
  638. sprintf( 
  639. esc_html__( 'It seems the authentication for the plugin is missing permissions. Please %1$sre-authenticate%2$s with Google Analytics to allow the plugin to fetch data.', 'google-analytics-for-wordpress' ),  
  640. '<a href="' . admin_url( 'admin.php?page=monsterinsights_settings' ) . '">',  
  641. '</a>' 
  642. . '</p></div>'; 
  643.  
  644. /** 
  645. * Throw a warning when the fetching failed 
  646. */ 
  647. public function monsterinsights_show_admin_config_blocked_notice() { 
  648. echo '<div class="error"><p>' .  
  649. sprintf( 
  650. esc_html__( 'Data is not up-to-date, there was an error in retrieving the data from Google Analytics. This error could be caused by several issues. If the error persists, please see %1$sthis page%2$s.', 'google-analytics-for-wordpress' ),  
  651. '<a href="https://www.monsterinsights.com/docs/blocked-connection/">',  
  652. '</a>' 
  653. . '</p></div>';