| 1 |
<?php |
| 2 |
|
| 3 |
class Meow_MWSEO_Modules_Insights |
| 4 |
{ |
| 5 |
private $core = null; |
| 6 |
private $ready = false; |
| 7 |
private $key = null; |
| 8 |
private $timeout = 120; // Timeout in seconds |
| 9 |
|
| 10 |
private $url = "https://pagespeedonline.googleapis.com/pagespeedonline/v5/runPagespeed"; |
| 11 |
private $crux_url = "https://chromeuxreport.googleapis.com/v1/records:queryRecord"; |
| 12 |
private $transient_name = 'mwseo_last_insights'; |
| 13 |
|
| 14 |
// Constructor to initialize the class |
| 15 |
public function __construct( $core ) |
| 16 |
{ |
| 17 |
$this->core = $core; |
| 18 |
$this->init(); |
| 19 |
} |
| 20 |
|
| 21 |
// Initialize Google Insights settings |
| 22 |
public function init() |
| 23 |
{ |
| 24 |
if ( !$this->check_api_settings() ) { |
| 25 |
return; |
| 26 |
} |
| 27 |
|
| 28 |
$this->ready = true; |
| 29 |
} |
| 30 |
|
| 31 |
function check_api_settings() |
| 32 |
{ |
| 33 |
$this->key = $this->core->get_option( 'google_api_key', '' ); |
| 34 |
|
| 35 |
if ( empty( $this->key ) ) { |
| 36 |
return false; |
| 37 |
} |
| 38 |
|
| 39 |
return true; |
| 40 |
} |
| 41 |
|
| 42 |
function get_insights_for_post( $post_id ) |
| 43 |
{ |
| 44 |
if( $post_id === 'delete' ) { |
| 45 |
$cached = get_transient( $this->transient_name ); |
| 46 |
if ( $cached !== false ) { |
| 47 |
delete_transient( $this->transient_name ); |
| 48 |
$this->core->log( '� |
| 49 |
Google Insights cache cleared.' ); |
| 50 |
return true; |
| 51 |
} |
| 52 |
$this->core->log( '⚠️ No Google Insights cache found to clear.' ); |
| 53 |
return false; |
| 54 |
} |
| 55 |
|
| 56 |
$url = $post_id != 'main' ? get_permalink( $post_id ) : get_home_url(); |
| 57 |
|
| 58 |
if ( empty( $url ) ) { |
| 59 |
return false; |
| 60 |
} |
| 61 |
|
| 62 |
return $this->get_insights( $url ); |
| 63 |
} |
| 64 |
|
| 65 |
function get_insights( $url ) |
| 66 |
{ |
| 67 |
if ( !$this->ready ) { |
| 68 |
$this->core->log( '⚠️ Google Insights not ready.' ); |
| 69 |
return false; |
| 70 |
} |
| 71 |
|
| 72 |
$categories = ['performance', 'accessibility', 'best-practices', 'seo']; |
| 73 |
$categoryQueryString = ''; |
| 74 |
foreach ( $categories as $category ) { |
| 75 |
$categoryQueryString .= '&category=' . urlencode( $category ); |
| 76 |
} |
| 77 |
|
| 78 |
$args = array( |
| 79 |
'url' => $url, |
| 80 |
//'url' => 'https://www.meowapps.com/', //! For testing purposes |
| 81 |
'key' => $this->key, |
| 82 |
); |
| 83 |
|
| 84 |
$queryString = http_build_query( $args ); |
| 85 |
$fullQueryString = $queryString . $categoryQueryString; |
| 86 |
|
| 87 |
$response = wp_remote_get( $this->url . '?' . $fullQueryString, array( |
| 88 |
'timeout' => $this->timeout, |
| 89 |
'headers' => array( |
| 90 |
'referer' => home_url(), |
| 91 |
), |
| 92 |
) ); |
| 93 |
|
| 94 |
$pagespeed_ok = false; |
| 95 |
$result = null; |
| 96 |
|
| 97 |
if ( !is_wp_error( $response ) ) { |
| 98 |
$code = wp_remote_retrieve_response_code( $response ); |
| 99 |
$result = json_decode( wp_remote_retrieve_body( $response ), true ); |
| 100 |
// PageSpeed returned a real result (no API-level error and lighthouse data present). |
| 101 |
if ( $code === 200 && is_array( $result ) && empty( $result['error'] ) && isset( $result['lighthouseResult'] ) ) { |
| 102 |
$result['_source'] = 'pagespeed'; |
| 103 |
$pagespeed_ok = true; |
| 104 |
} |
| 105 |
} |
| 106 |
|
| 107 |
if ( !$pagespeed_ok ) { |
| 108 |
// Fall back to CrUX (real-user Core Web Vitals). Common when the user's |
| 109 |
// GCP project has PageSpeed API disabled but CrUX API enabled. |
| 110 |
$crux = $this->get_crux_data( $url ); |
| 111 |
if ( $crux !== false ) { |
| 112 |
$result = $crux; |
| 113 |
} else if ( !is_array( $result ) ) { |
| 114 |
return false; |
| 115 |
} |
| 116 |
} |
| 117 |
|
| 118 |
set_transient( $this->transient_name, $result ); |
| 119 |
|
| 120 |
return $result; |
| 121 |
} |
| 122 |
|
| 123 |
private function get_crux_data( $url ) |
| 124 |
{ |
| 125 |
$body = wp_json_encode( array( |
| 126 |
'url' => $url, |
| 127 |
'formFactor' => 'PHONE', |
| 128 |
) ); |
| 129 |
|
| 130 |
$response = wp_remote_post( $this->crux_url . '?key=' . urlencode( $this->key ), array( |
| 131 |
'timeout' => $this->timeout, |
| 132 |
'headers' => array( |
| 133 |
'Content-Type' => 'application/json', |
| 134 |
'referer' => home_url(), |
| 135 |
), |
| 136 |
'body' => $body, |
| 137 |
) ); |
| 138 |
|
| 139 |
if ( is_wp_error( $response ) ) { |
| 140 |
return false; |
| 141 |
} |
| 142 |
|
| 143 |
$code = wp_remote_retrieve_response_code( $response ); |
| 144 |
$data = json_decode( wp_remote_retrieve_body( $response ), true ); |
| 145 |
|
| 146 |
if ( $code !== 200 || !is_array( $data ) || !empty( $data['error'] ) || empty( $data['record']['metrics'] ) ) { |
| 147 |
return false; |
| 148 |
} |
| 149 |
|
| 150 |
$data['_source'] = 'crux'; |
| 151 |
return $data; |
| 152 |
} |
| 153 |
|
| 154 |
function get_last_insights() |
| 155 |
{ |
| 156 |
$cached = get_transient( $this->transient_name ); |
| 157 |
|
| 158 |
if ( $cached === false ) { |
| 159 |
return false; |
| 160 |
} |
| 161 |
|
| 162 |
return $cached; |
| 163 |
} |
| 164 |
|
| 165 |
} |