PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.7.1
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.7.1
2.7.1 2.7.2 2.7.0 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 All 141 releases
← All changes | otto/Otto_pixel_class.php +103 -29 2.7.2 → 2.7.1 View file →
@@ -7,24 +7,27 @@
7 7 /**
8 8 * This class handles the Otto Pixel Functions
9 9 */
10 10 Class Metasync_otto_pixel{
11 -
11 +
12 12 #otto html class
13 13 public $o_html;
14 14
15 - # no cache wp pages
15 + # crawl data option
16 + public $option_name = 'metasync_otto_crawldata';
17 +
18 + # no cache wp pages
16 19 public $no_cache_pages = ['wp-login.php'];
17 20
18 21 # OTTO UUID
19 22 private $otto_uuid;
20 23
21 - #
24 + #
22 25 function __construct($otto_uuid){
23 -
26 +
24 27 # store the UUID
25 28 $this->otto_uuid = $otto_uuid;
26 -
29 +
27 30 # load the html class
28 31 $this->o_html = new Metasync_otto_html($otto_uuid);
29 32
30 33 }
@@ -36,8 +39,102 @@
36 39 # All pages are processed in real-time from OTTO API
37 40 return true;
38 41 }
39 42
43 +
44 + # method to save crawl data into
45 + function save_crawl_data($data){
46 +
47 + # get the option name
48 + $option_name = $this->option_name;
49 +
50 + # handle data
51 + $saved = get_option($option_name);
52 +
53 + # log saved
54 +
55 + # if saved false save
56 + if(empty($saved['urls'])){
57 +
58 + # save the option
59 + update_option($option_name, $data);
60 +
61 + return;
62 + }
63 +
64 + # get new unique list of urls
65 + $new_list = array_unique(array_merge($data['urls'], $saved['urls']));
66 +
67 + # set data
68 + $data['urls'] = $new_list;
69 +
70 + # log saved
71 +
72 + # save the option
73 + update_option($option_name, $data);
74 + }
75 +
76 + /**
77 + * Check if a URL has been crawled by Otto
78 + * - Validates domain against saved domain
79 + * - Ignores query strings
80 + * - Does exact path matching as Otto stores paths exactly as they appear
81 + * @param string $url - Full URL to check
82 + * @return bool - True if URL was crawled, false otherwise
83 + */
84 + function is_url_crawled($url) {
85 + # Ensure valid input
86 + if (empty($url) || !is_string($url)) {
87 + return false;
88 + }
89 +
90 + # Get saved crawl data
91 + $saved = get_option($this->option_name);
92 +
93 + if (
94 + empty($saved) ||
95 + !is_array($saved) ||
96 + empty($saved['domain']) ||
97 + empty($saved['urls']) ||
98 + !is_array($saved['urls'])
99 + ) {
100 + return false;
101 + }
102 +
103 + # Parse saved domain + incoming URL
104 + $saved_domain = wp_parse_url($saved['domain'], PHP_URL_HOST);
105 + $incoming_domain = wp_parse_url($url, PHP_URL_HOST);
106 +
107 + # Domain mismatch - not crawled
108 + if (empty($saved_domain) || empty($incoming_domain) || strcasecmp($saved_domain, $incoming_domain) !== 0) {
109 + return false;
110 + }
111 +
112 + # Parse incoming path (ignore query string)
113 + $parsed_url = wp_parse_url($url);
114 + $url_path = $parsed_url['path'] ?? '/';
115 +
116 + # Ensure path starts with / but don't modify trailing slashes
117 + # Otto stores paths exactly as they appear in URLs
118 + if (substr($url_path, 0, 1) !== '/') {
119 + $url_path = '/' . $url_path;
120 + }
121 +
122 + # Compare against crawled URLs - exact match
123 + foreach ($saved['urls'] as $crawled_url) {
124 + if (!is_string($crawled_url)) {
125 + continue;
126 + }
127 +
128 + # Direct comparison - Otto stores paths exactly as they are
129 + if (strcasecmp($crawled_url, $url_path) === 0) {
130 + return true;
131 + }
132 + }
133 +
134 + return false;
135 + }
136 +
40 137 # get the current route
41 138 function get_route(){
42 139
43 140 # check if we're in an HTTP context
@@ -226,30 +323,8 @@
226 323
227 324 # Get cache status for headers
228 325 $cache_status = Metasync_Otto_Transient_Cache::get_cache_status($cache_track_key);
229 326
230 - # POSTMETA BACKSTOP: a MISS means this request already paid for a live
231 - # OTTO fetch, which makes it the cheapest possible place to repair the
232 - # stored SEO meta when the crawl-notify webhook never ran. The sync is
233 - # deferred to a shutdown callback that runs after the response HTML is
234 - # built, so the rendered page and its timing are untouched. A HIT never
235 - # reaches this branch — steady-state requests keep doing zero extra
236 - # work. The class_exists()/method_exists() pair mirrors the guard
237 - # above: during a plugin update an opcache can hold this file without
238 - # the new class, and an unguarded static call would fatal the page.
239 - # The whole hook sits in try/catch: in the mixed-opcache window a missing
240 - # class constant is an Error, and the backstop must never fatal the page.
241 - try {
242 - $is_cache_miss = ($cache_status === Metasync_Otto_Transient_Cache::STATUS_MISS);
243 - # @phpstan-ignore-next-line function.alreadyNarrowedType
244 - if ($is_cache_miss && class_exists('Metasync_Otto_Backstop_Sync') && method_exists('Metasync_Otto_Backstop_Sync', 'maybe_defer_sync')) {
245 - Metasync_Otto_Backstop_Sync::maybe_defer_sync($route, $suggestions, $cache_status);
246 - }
247 - } catch (Throwable $backstop_error) {
248 - // Best-effort repair only; rendering continues untouched.
249 - unset($backstop_error);
250 - }
251 -
252 327 # RENDER PRIORITY:
253 328 # 1. WP Rocket rocket_buffer filter — WP Rocket caches OTTO-modified HTML,
254 329 # so Kinsta also caches the correct version. No exit(), no cache bypass.
255 330 # 2. Output Buffer (fast) — for environments without WP Rocket.
@@ -265,9 +340,9 @@
265 340 # WP ROCKET PATH: highest priority when WP Rocket is active.
266 341 # rocket_buffer fires inside WP Rocket's own cache pipeline, so the
267 342 # cache file WP Rocket writes (and that Kinsta stores) is already
268 343 # OTTO-modified. Eliminates the race where WP Rocket saved pre-OTTO HTML.
269 - if (defined('WP_ROCKET_VERSION') || class_exists('WP_Rocket')) {
344 + if (class_exists('WP_Rocket')) {
270 345 $wp_rocket_compat_mode = Metasync_Otto_Config::get_wp_rocket_compat_mode();
271 346 if ($wp_rocket_compat_mode !== 'http') {
272 347 # disable_otto exits in metasync_start_otto() before we get here, so
273 348 # only 'http' compat mode needs to skip the rocket_buffer path.
@@ -765,9 +840,8 @@
765 840 Metasync_Otto_Render_Strategy::block_http_cache();
766 841 }
767 842
768 843 # continue to render the html
769 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- server-rendered route HTML from the OTTO render strategy; escaping would corrupt the document
770 844 echo $route_html_string;
771 845
772 846 # prevent further wp execution
773 847 exit();