Skip to main content

data_for_seo/api/on_page/
mod.rs

1use crate::entity::{
2    OnPageDataApiContentParsing, OnPageDataApiDuplicateContent, OnPageDataApiDuplicateTags,
3    OnPageDataApiError, OnPageDataApiIdList, OnPageDataApiInstantPages,
4    OnPageDataApiKeywordDensity, OnPageDataApiLighthouseTaskGet, OnPageDataApiLighthouseTasksReady,
5    OnPageDataApiLinks, OnPageDataApiMicrodata, OnPageDataApiNonIndexable, OnPageDataApiPage,
6    OnPageDataApiPageScreensShot, OnPageDataApiRawHtml, OnPageDataApiRedirectChains,
7    OnPageDataApiResources, OnPageDataApiSummary, OnPageDataApiTasksReady, OnPageDataApiWaterfall,
8};
9use crate::{DataForSeoApiResponse, DataForSeoClient};
10use serde::{Deserialize, Serialize};
11use serde_json::Value;
12
13/// OnPage API — on-page SEO audit and website crawling.
14/// See <https://docs.dataforseo.com/v3/on_page/overview/>.
15pub struct OnPageApi<'a> {
16    client: &'a DataForSeoClient,
17}
18
19impl DataForSeoClient {
20    /// Returns the OnPage API endpoint group.
21    pub fn on_page(&self) -> OnPageApi<'_> {
22        OnPageApi { client: self }
23    }
24}
25
26impl OnPageApi<'_> {
27    /// Sets a crawling task for the target website.
28    /// See <https://docs.dataforseo.com/v3/on_page/task_post/>.
29    pub async fn task_post(&self, data: Vec<OnPageApiTaskPost>) -> DataForSeoApiResponse<Value> {
30        self.client.http_post("/v3/on_page/task_post", &data).await
31    }
32
33    /// Returns the list of completed crawling tasks.
34    /// See <https://docs.dataforseo.com/v3/on_page/tasks_ready/>.
35    pub async fn tasks_ready(&self) -> DataForSeoApiResponse<OnPageDataApiTasksReady> {
36        self.client.http_get("/v3/on_page/tasks_ready").await
37    }
38
39    /// Stops an active crawling session.
40    /// See <https://docs.dataforseo.com/v3/on_page/force_stop/>.
41    pub async fn force_stop(
42        &self,
43        data: Vec<OnPageApiForceStopPost>,
44    ) -> DataForSeoApiResponse<Value> {
45        self.client.http_post("/v3/on_page/force_stop", &data).await
46    }
47
48    /// Returns a summary of the crawling results for a task.
49    /// See <https://docs.dataforseo.com/v3/on_page/summary/>.
50    pub async fn summary(&self, id: &str) -> DataForSeoApiResponse<OnPageDataApiSummary> {
51        self.client
52            .http_get(format!("/v3/on_page/summary/{id}").as_str())
53            .await
54    }
55
56    /// Returns the crawled pages of a task.
57    /// See <https://docs.dataforseo.com/v3/on_page/pages/>.
58    pub async fn pages(
59        &self,
60        data: Vec<OnPageApiPagesPost>,
61    ) -> DataForSeoApiResponse<OnPageDataApiPage> {
62        self.client.http_post("/v3/on_page/pages", &data).await
63    }
64
65    /// Returns the pages on which a given resource appears.
66    /// See <https://docs.dataforseo.com/v3/on_page/pages_by_resource/>.
67    pub async fn pages_by_resource(
68        &self,
69        data: Vec<OnPageApiPagesByResourcePost>,
70    ) -> DataForSeoApiResponse<OnPageDataApiPage> {
71        self.client
72            .http_post("/v3/on_page/pages_by_resource", &data)
73            .await
74    }
75
76    /// Returns the resources (images, scripts, stylesheets, ...) found during crawling.
77    /// See <https://docs.dataforseo.com/v3/on_page/resources/>.
78    pub async fn resources(
79        &self,
80        data: Vec<OnPageApiResourcesPost>,
81    ) -> DataForSeoApiResponse<OnPageDataApiResources> {
82        self.client.http_post("/v3/on_page/resources", &data).await
83    }
84
85    /// Returns pages that share duplicate title or description tags.
86    /// See <https://docs.dataforseo.com/v3/on_page/duplicate_tags/>.
87    pub async fn duplicate_tags(
88        &self,
89        data: Vec<OnPageApiDuplicateTagsPost>,
90    ) -> DataForSeoApiResponse<OnPageDataApiDuplicateTags> {
91        self.client
92            .http_post("/v3/on_page/duplicate_tags", &data)
93            .await
94    }
95
96    /// Returns pages with content duplicating a given page.
97    /// See <https://docs.dataforseo.com/v3/on_page/duplicate_content/>.
98    pub async fn duplicate_content(
99        &self,
100        data: Vec<OnPageApiDuplicateContentPost>,
101    ) -> DataForSeoApiResponse<OnPageDataApiDuplicateContent> {
102        self.client
103            .http_post("/v3/on_page/duplicate_content", &data)
104            .await
105    }
106
107    /// Returns the internal and external links discovered during crawling.
108    /// See <https://docs.dataforseo.com/v3/on_page/links/>.
109    pub async fn links(
110        &self,
111        data: Vec<OnPageApiLinksPost>,
112    ) -> DataForSeoApiResponse<OnPageDataApiLinks> {
113        self.client.http_post("/v3/on_page/links", &data).await
114    }
115
116    /// Returns redirect chains and loops found during crawling.
117    /// See <https://docs.dataforseo.com/v3/on_page/redirect_chains/>.
118    pub async fn redirect_chains(
119        &self,
120        data: Vec<OnPageApiRedirectChainsPost>,
121    ) -> DataForSeoApiResponse<OnPageDataApiRedirectChains> {
122        self.client
123            .http_post("/v3/on_page/redirect_chains", &data)
124            .await
125    }
126
127    /// Returns pages that are not available for indexing.
128    /// See <https://docs.dataforseo.com/v3/on_page/non_indexable/>.
129    pub async fn non_indexable(
130        &self,
131        data: Vec<OnPageApiNonIndexablePost>,
132    ) -> DataForSeoApiResponse<OnPageDataApiNonIndexable> {
133        self.client
134            .http_post("/v3/on_page/non_indexable", &data)
135            .await
136    }
137
138    /// Returns the loading sequence of resources for a page.
139    /// See <https://docs.dataforseo.com/v3/on_page/waterfall/>.
140    pub async fn waterfall(
141        &self,
142        data: Vec<OnPageApiWaterfallPost>,
143    ) -> DataForSeoApiResponse<OnPageDataApiWaterfall> {
144        self.client.http_post("/v3/on_page/waterfall", &data).await
145    }
146
147    /// Returns keyword density metrics for the crawled content.
148    /// See <https://docs.dataforseo.com/v3/on_page/keyword_density/>.
149    pub async fn keyword_density(
150        &self,
151        data: Vec<OnPageApiKeywordDensityPost>,
152    ) -> DataForSeoApiResponse<OnPageDataApiKeywordDensity> {
153        self.client
154            .http_post("/v3/on_page/keyword_density", &data)
155            .await
156    }
157
158    /// Validates the structured markup (microdata) of a page.
159    /// See <https://docs.dataforseo.com/v3/on_page/microdata/>.
160    pub async fn microdata(
161        &self,
162        data: Vec<OnPageApiMicrodataPost>,
163    ) -> DataForSeoApiResponse<OnPageDataApiMicrodata> {
164        self.client.http_post("/v3/on_page/microdata", &data).await
165    }
166
167    /// Returns the raw HTML stored for a crawled page.
168    /// See <https://docs.dataforseo.com/v3/on_page/raw_html/>.
169    pub async fn raw_html(
170        &self,
171        data: Vec<OnPageApiRawHtmlPost>,
172    ) -> DataForSeoApiResponse<OnPageDataApiRawHtml> {
173        self.client.http_post("/v3/on_page/raw_html", &data).await
174    }
175
176    /// Captures a screenshot of a page.
177    /// See <https://docs.dataforseo.com/v3/on_page/page_screenshot/>.
178    pub async fn page_screenshot(
179        &self,
180        data: Vec<OnPageApiPageScreenshotPost>,
181    ) -> DataForSeoApiResponse<OnPageDataApiPageScreensShot> {
182        self.client
183            .http_post("/v3/on_page/page_screenshot", &data)
184            .await
185    }
186
187    /// Parses the structured content of a crawled page.
188    /// See <https://docs.dataforseo.com/v3/on_page/content_parsing/>.
189    pub async fn content_parsing(
190        &self,
191        data: Vec<OnPageApiContentParsingPost>,
192    ) -> DataForSeoApiResponse<OnPageDataApiContentParsing> {
193        self.client
194            .http_post("/v3/on_page/content_parsing", &data)
195            .await
196    }
197
198    /// Parses the structured content of a page in real time.
199    /// See <https://docs.dataforseo.com/v3/on_page/content_parsing/live/>.
200    pub async fn content_parsing_live(
201        &self,
202        data: Vec<OnPageApiContentParsingLivePost>,
203    ) -> DataForSeoApiResponse<OnPageDataApiContentParsing> {
204        self.client
205            .http_post("/v3/on_page/content_parsing/live", &data)
206            .await
207    }
208
209    /// Crawls and returns on-page data for a single page in real time.
210    /// See <https://docs.dataforseo.com/v3/on_page/instant_pages/>.
211    pub async fn instant_pages(
212        &self,
213        data: Vec<OnPageApiInstantPagesPost>,
214    ) -> DataForSeoApiResponse<OnPageDataApiInstantPages> {
215        self.client
216            .http_post("/v3/on_page/instant_pages", &data)
217            .await
218    }
219
220    /// Returns the list of task IDs created within a datetime range.
221    /// See <https://docs.dataforseo.com/v3/on_page/id_list/>.
222    pub async fn id_list(
223        &self,
224        data: Vec<OnPageApiIdListPost>,
225    ) -> DataForSeoApiResponse<OnPageDataApiIdList> {
226        self.client.http_post("/v3/on_page/id_list", &data).await
227    }
228
229    /// Returns OnPage API errors from the past 7 days (free of charge).
230    /// See <https://docs.dataforseo.com/v3/on_page/errors/>.
231    pub async fn errors(
232        &self,
233        data: Vec<OnPageApiErrorsPost>,
234    ) -> DataForSeoApiResponse<OnPageDataApiError> {
235        self.client.http_post("/v3/on_page/errors", &data).await
236    }
237
238    /// Returns the full list of filters available for OnPage endpoints (free of charge).
239    /// See <https://docs.dataforseo.com/v3/on_page/filters_and_thresholds/>.
240    pub async fn available_filters(&self) -> DataForSeoApiResponse<Value> {
241        self.client.http_get("/v3/on_page/available_filters").await
242    }
243
244    /// Sets a Lighthouse audit task for a page.
245    /// See <https://docs.dataforseo.com/v3/on_page/lighthouse/task_post/>.
246    pub async fn lighthouse_task_post(
247        &self,
248        data: Vec<OnPageApiLighthouseTaskPost>,
249    ) -> DataForSeoApiResponse<Value> {
250        self.client
251            .http_post("/v3/on_page/lighthouse/task_post", &data)
252            .await
253    }
254
255    /// Returns the list of completed Lighthouse audit tasks.
256    /// See <https://docs.dataforseo.com/v3/on_page/lighthouse/tasks_ready/>.
257    pub async fn lighthouse_tasks_ready(
258        &self,
259    ) -> DataForSeoApiResponse<OnPageDataApiLighthouseTasksReady> {
260        self.client
261            .http_get("/v3/on_page/lighthouse/tasks_ready")
262            .await
263    }
264
265    /// Returns the result of a completed Lighthouse audit task.
266    /// See <https://docs.dataforseo.com/v3/on_page/lighthouse/task_get/>.
267    pub async fn lighthouse_task_get(
268        &self,
269        id: &str,
270    ) -> DataForSeoApiResponse<OnPageDataApiLighthouseTaskGet> {
271        self.client
272            .http_get(format!("/v3/on_page/lighthouse/task_get/json/{id}").as_str())
273            .await
274    }
275
276    /// Runs a Lighthouse audit for a page in real time.
277    /// See <https://docs.dataforseo.com/v3/on_page/lighthouse/live/>.
278    pub async fn lighthouse_live(
279        &self,
280        data: Vec<OnPageApiLighthouseLivePost>,
281    ) -> DataForSeoApiResponse<OnPageDataApiLighthouseTaskGet> {
282        self.client
283            .http_post("/v3/on_page/lighthouse/live/json", &data)
284            .await
285    }
286}
287
288/// Request for [`OnPageApi::task_post`].
289/// See <https://docs.dataforseo.com/v3/on_page/task_post/>.
290#[derive(Debug, Default, Serialize, Deserialize, Clone)]
291pub struct OnPageApiTaskPost {
292    /// Domain to crawl, without protocol or `www` (e.g. "example.com").
293    pub target: String,
294    /// Maximum number of pages to crawl.
295    pub max_crawl_pages: i32,
296    /// First URL to crawl; defaults to the domain's home page.
297    #[serde(skip_serializing_if = "Option::is_none")]
298    pub start_url: Option<String>,
299    /// Run sitewide checks even when only a single page is crawled.
300    #[serde(skip_serializing_if = "Option::is_none")]
301    pub force_sitewide_checks: Option<bool>,
302    /// URLs to crawl before the rest of the site (max 20).
303    #[serde(skip_serializing_if = "Option::is_none")]
304    pub priority_urls: Option<Vec<String>>,
305    /// Maximum crawl depth, counted in clicks from the start page.
306    #[serde(skip_serializing_if = "Option::is_none")]
307    pub max_crawl_depth: Option<i32>,
308    /// Delay between page requests, in milliseconds.
309    #[serde(skip_serializing_if = "Option::is_none")]
310    pub crawl_delay: Option<i32>,
311    /// Store the raw HTML of crawled pages for later retrieval.
312    #[serde(skip_serializing_if = "Option::is_none")]
313    pub store_raw_html: Option<bool>,
314    /// Parse page content so it can be retrieved via the content endpoints.
315    #[serde(skip_serializing_if = "Option::is_none")]
316    pub enable_content_parsing: Option<bool>,
317    /// Accept cookies while crawling.
318    #[serde(skip_serializing_if = "Option::is_none")]
319    pub support_cookies: Option<bool>,
320    /// Value of the Accept-Language header sent while crawling.
321    #[serde(skip_serializing_if = "Option::is_none")]
322    pub accept_language: Option<String>,
323    /// Custom robots.txt content to apply during the crawl.
324    #[serde(skip_serializing_if = "Option::is_none")]
325    pub custom_robots_txt: Option<String>,
326    /// How custom robots.txt combines with the site's: "merge" or "override".
327    #[serde(skip_serializing_if = "Option::is_none")]
328    pub robots_txt_merge_mode: Option<String>,
329    /// Custom User-Agent header sent while crawling.
330    #[serde(skip_serializing_if = "Option::is_none")]
331    pub custom_user_agent: Option<String>,
332    /// Device preset for rendering: "desktop", "mobile", or "tablet".
333    #[serde(skip_serializing_if = "Option::is_none")]
334    pub browser_preset: Option<String>,
335    /// Viewport width used for rendering, in pixels.
336    #[serde(skip_serializing_if = "Option::is_none")]
337    pub browser_screen_width: Option<i32>,
338    /// Viewport height used for rendering, in pixels.
339    #[serde(skip_serializing_if = "Option::is_none")]
340    pub browser_screen_height: Option<i32>,
341    /// Device pixel ratio used for rendering.
342    #[serde(skip_serializing_if = "Option::is_none")]
343    pub browser_screen_scale_factor: Option<f64>,
344    /// Crawl following the site's XML sitemap.
345    #[serde(skip_serializing_if = "Option::is_none")]
346    pub respect_sitemap: Option<bool>,
347    /// URL of a custom sitemap to crawl.
348    #[serde(skip_serializing_if = "Option::is_none")]
349    pub custom_sitemap: Option<String>,
350    /// Restrict the crawl to URLs listed in the sitemap.
351    #[serde(skip_serializing_if = "Option::is_none")]
352    pub crawl_sitemap_only: Option<bool>,
353    /// Load page resources (images, scripts, stylesheets) while crawling.
354    #[serde(skip_serializing_if = "Option::is_none")]
355    pub load_resources: Option<bool>,
356    /// Check whether the www and non-www versions redirect consistently.
357    #[serde(skip_serializing_if = "Option::is_none")]
358    pub enable_www_redirect_check: Option<bool>,
359    /// Execute page JavaScript while crawling (incurs extra cost).
360    #[serde(skip_serializing_if = "Option::is_none")]
361    pub enable_javascript: Option<bool>,
362    /// Allow XMLHttpRequest calls while rendering the page.
363    #[serde(skip_serializing_if = "Option::is_none")]
364    pub enable_xhr: Option<bool>,
365    /// Emulate full browser rendering to measure Core Web Vitals.
366    #[serde(skip_serializing_if = "Option::is_none")]
367    pub enable_browser_rendering: Option<bool>,
368    /// Hide cookie-consent popups before capturing the page.
369    #[serde(skip_serializing_if = "Option::is_none")]
370    pub disable_cookie_popup: Option<bool>,
371    /// Custom JavaScript to execute on each crawled page.
372    #[serde(skip_serializing_if = "Option::is_none")]
373    pub custom_js: Option<String>,
374    /// Validate structured microdata markup on crawled pages.
375    #[serde(skip_serializing_if = "Option::is_none")]
376    pub validate_micromarkup: Option<bool>,
377    /// Crawl subdomains of the target domain.
378    #[serde(skip_serializing_if = "Option::is_none")]
379    pub allow_subdomains: Option<bool>,
380    /// Subdomains to crawl (used when subdomains are otherwise excluded).
381    #[serde(skip_serializing_if = "Option::is_none")]
382    pub allowed_subdomains: Option<Vec<String>>,
383    /// Subdomains to exclude from the crawl.
384    #[serde(skip_serializing_if = "Option::is_none")]
385    pub disallowed_subdomains: Option<Vec<String>>,
386    /// Check spelling on crawled pages using the Hunspell library.
387    #[serde(skip_serializing_if = "Option::is_none")]
388    pub check_spell: Option<bool>,
389    /// Hunspell language code used for spell checking.
390    #[serde(skip_serializing_if = "Option::is_none")]
391    pub check_spell_language: Option<String>,
392    /// Words to ignore during spell checking (max 1000).
393    #[serde(skip_serializing_if = "Option::is_none")]
394    pub check_spell_exceptions: Option<Vec<String>>,
395    /// Compute keyword density for crawled pages.
396    #[serde(skip_serializing_if = "Option::is_none")]
397    pub calculate_keyword_density: Option<bool>,
398    /// Custom threshold values for the checks in OnPage responses.
399    #[serde(skip_serializing_if = "Option::is_none")]
400    pub checks_threshold: Option<Value>,
401    /// Sitewide checks to skip during the crawl.
402    #[serde(skip_serializing_if = "Option::is_none")]
403    pub disable_sitewide_checks: Option<Vec<String>>,
404    /// Per-page checks to skip during the crawl.
405    #[serde(skip_serializing_if = "Option::is_none")]
406    pub disable_page_checks: Option<Vec<String>>,
407    /// Retry using a different proxy pool if the first attempt fails.
408    #[serde(skip_serializing_if = "Option::is_none")]
409    pub switch_pool: Option<bool>,
410    /// Return partial results even if the crawl times out.
411    #[serde(skip_serializing_if = "Option::is_none")]
412    pub return_despite_timeout: Option<bool>,
413    /// User-defined task identifier (max 255 characters).
414    #[serde(skip_serializing_if = "Option::is_none")]
415    pub tag: Option<String>,
416    /// URL notified by GET when the task completes.
417    #[serde(skip_serializing_if = "Option::is_none")]
418    pub pingback_url: Option<String>,
419}
420
421impl OnPageApiTaskPost {
422    /// Creates a task request for `target`, crawling up to `max_crawl_pages` pages.
423    pub fn new(target: String, max_crawl_pages: i32) -> Self {
424        OnPageApiTaskPost {
425            target,
426            max_crawl_pages,
427            ..OnPageApiTaskPost::default()
428        }
429    }
430}
431
432/// Request for [`OnPageApi::pages`].
433/// See <https://docs.dataforseo.com/v3/on_page/pages/>.
434#[derive(Debug, Default, Serialize, Deserialize, Clone)]
435pub struct OnPageApiPagesPost {
436    /// Task identifier returned by the Task POST endpoint.
437    pub id: String,
438    /// Maximum number of pages to return (default 100, max 1000).
439    #[serde(skip_serializing_if = "Option::is_none")]
440    pub limit: Option<i32>,
441    /// Offset into the results array (default 0).
442    #[serde(skip_serializing_if = "Option::is_none")]
443    pub offset: Option<i32>,
444    /// Result filtering rules (max 8).
445    #[serde(skip_serializing_if = "Option::is_none")]
446    pub filters: Option<Vec<Vec<String>>>,
447    /// Sorting rules, each as "field,asc" or "field,desc" (max 3).
448    #[serde(skip_serializing_if = "Option::is_none")]
449    pub order_by: Option<Vec<String>>,
450    /// Pagination token returned by a previous response.
451    #[serde(skip_serializing_if = "Option::is_none")]
452    pub search_after_token: Option<String>,
453    /// User-defined task identifier (max 255 characters).
454    #[serde(skip_serializing_if = "Option::is_none")]
455    pub tag: Option<String>,
456}
457
458impl OnPageApiPagesPost {
459    /// Creates a pages request for the given task `id`.
460    pub fn new(id: String) -> Self {
461        OnPageApiPagesPost {
462            id,
463            ..OnPageApiPagesPost::default()
464        }
465    }
466}
467
468/// Request for [`OnPageApi::pages_by_resource`].
469/// See <https://docs.dataforseo.com/v3/on_page/pages_by_resource/>.
470#[derive(Debug, Default, Serialize, Deserialize, Clone)]
471pub struct OnPageApiPagesByResourcePost {
472    /// Task identifier returned by the Task POST endpoint.
473    pub id: String,
474    /// Resource URL, obtained from the Resources endpoint.
475    pub url: String,
476    /// Maximum number of pages to return (default 100, max 1000).
477    #[serde(skip_serializing_if = "Option::is_none")]
478    pub limit: Option<i32>,
479    /// Offset into the results array (default 0).
480    #[serde(skip_serializing_if = "Option::is_none")]
481    pub offset: Option<i32>,
482    /// Result filtering rules (max 8).
483    #[serde(skip_serializing_if = "Option::is_none")]
484    pub filters: Option<Vec<Vec<String>>>,
485    /// Sorting rules, each as "field,asc" or "field,desc" (max 3).
486    #[serde(skip_serializing_if = "Option::is_none")]
487    pub order_by: Option<Vec<String>>,
488    /// User-defined task identifier (max 255 characters).
489    #[serde(skip_serializing_if = "Option::is_none")]
490    pub tag: Option<String>,
491}
492
493impl OnPageApiPagesByResourcePost {
494    /// Creates a request for pages on which the resource `url` appears, for task `id`.
495    pub fn new(id: String, url: String) -> Self {
496        OnPageApiPagesByResourcePost {
497            id,
498            url,
499            ..OnPageApiPagesByResourcePost::default()
500        }
501    }
502}
503
504/// Request for [`OnPageApi::resources`].
505/// See <https://docs.dataforseo.com/v3/on_page/resources/>.
506#[derive(Debug, Default, Serialize, Deserialize, Clone)]
507pub struct OnPageApiResourcesPost {
508    /// Task identifier returned by the Task POST endpoint.
509    pub id: String,
510    /// Restrict results to resources found on this page URL.
511    #[serde(skip_serializing_if = "Option::is_none")]
512    pub url: Option<String>,
513    /// Maximum number of resources to return (default 100, max 1000).
514    #[serde(skip_serializing_if = "Option::is_none")]
515    pub limit: Option<i32>,
516    /// Offset into the results array (default 0).
517    #[serde(skip_serializing_if = "Option::is_none")]
518    pub offset: Option<i32>,
519    /// Result filtering rules applied to resources (max 8).
520    #[serde(skip_serializing_if = "Option::is_none")]
521    pub filters: Option<Vec<Value>>,
522    /// Filtering rules applied to the pages that reference each resource.
523    #[serde(skip_serializing_if = "Option::is_none")]
524    pub relevant_pages_filters: Option<Vec<Value>>,
525    /// Sorting rules, each as "field,asc" or "field,desc" (max 3).
526    #[serde(skip_serializing_if = "Option::is_none")]
527    pub order_by: Option<Vec<String>>,
528    /// Pagination token returned by a previous response.
529    #[serde(skip_serializing_if = "Option::is_none")]
530    pub search_after_token: Option<String>,
531    /// User-defined task identifier (max 255 characters).
532    #[serde(skip_serializing_if = "Option::is_none")]
533    pub tag: Option<String>,
534}
535
536impl OnPageApiResourcesPost {
537    /// Creates a resources request for the given task `id`.
538    pub fn new(id: String) -> Self {
539        OnPageApiResourcesPost {
540            id,
541            ..OnPageApiResourcesPost::default()
542        }
543    }
544}
545
546/// Request for [`OnPageApi::duplicate_tags`].
547/// See <https://docs.dataforseo.com/v3/on_page/duplicate_tags/>.
548#[derive(Debug, Default, Serialize, Deserialize, Clone)]
549pub struct OnPageApiDuplicateTagsPost {
550    /// Task identifier returned by the Task POST endpoint.
551    pub id: String,
552    /// `duplicate_title` or `duplicate_description`.
553    #[serde(rename = "type")]
554    pub duplicate_type: String,
555    /// Restrict results to a specific title or description value.
556    #[serde(skip_serializing_if = "Option::is_none")]
557    pub accumulator: Option<String>,
558    /// Maximum number of pages to return (default 100, max 1000).
559    #[serde(skip_serializing_if = "Option::is_none")]
560    pub limit: Option<i32>,
561    /// Offset into the results array (default 0).
562    #[serde(skip_serializing_if = "Option::is_none")]
563    pub offset: Option<i32>,
564    /// User-defined task identifier (max 255 characters).
565    #[serde(skip_serializing_if = "Option::is_none")]
566    pub tag: Option<String>,
567}
568
569impl OnPageApiDuplicateTagsPost {
570    /// Creates a duplicate-tags request for task `id` and the given `duplicate_type`.
571    pub fn new(id: String, duplicate_type: String) -> Self {
572        OnPageApiDuplicateTagsPost {
573            id,
574            duplicate_type,
575            ..OnPageApiDuplicateTagsPost::default()
576        }
577    }
578}
579
580/// Request for [`OnPageApi::duplicate_content`].
581/// See <https://docs.dataforseo.com/v3/on_page/duplicate_content/>.
582#[derive(Debug, Default, Serialize, Deserialize, Clone)]
583pub struct OnPageApiDuplicateContentPost {
584    /// Task identifier returned by the Task POST endpoint.
585    pub id: String,
586    /// Page URL to compare other pages against.
587    pub url: String,
588    /// Minimum content similarity to include, from 0 to 10 (default 6).
589    #[serde(skip_serializing_if = "Option::is_none")]
590    pub similarity: Option<i32>,
591    /// Maximum number of pages to return (default 100, max 1000).
592    #[serde(skip_serializing_if = "Option::is_none")]
593    pub limit: Option<i32>,
594    /// Offset into the results array (default 0).
595    #[serde(skip_serializing_if = "Option::is_none")]
596    pub offset: Option<i32>,
597    /// User-defined task identifier (max 255 characters).
598    #[serde(skip_serializing_if = "Option::is_none")]
599    pub tag: Option<String>,
600}
601
602impl OnPageApiDuplicateContentPost {
603    /// Creates a duplicate-content request for task `id`, comparing against `url`.
604    pub fn new(id: String, url: String) -> Self {
605        OnPageApiDuplicateContentPost {
606            id,
607            url,
608            ..OnPageApiDuplicateContentPost::default()
609        }
610    }
611}
612
613/// Request for [`OnPageApi::links`].
614/// See <https://docs.dataforseo.com/v3/on_page/links/>.
615#[derive(Debug, Default, Serialize, Deserialize, Clone)]
616pub struct OnPageApiLinksPost {
617    /// Task identifier returned by the Task POST endpoint.
618    pub id: String,
619    /// Restrict results to links originating from this page URL.
620    #[serde(skip_serializing_if = "Option::is_none")]
621    pub page_from: Option<String>,
622    /// Restrict results to links pointing to this page URL.
623    #[serde(skip_serializing_if = "Option::is_none")]
624    pub page_to: Option<String>,
625    /// Maximum number of links to return (default 100, max 1000).
626    #[serde(skip_serializing_if = "Option::is_none")]
627    pub limit: Option<i32>,
628    /// Offset into the results array (default 0).
629    #[serde(skip_serializing_if = "Option::is_none")]
630    pub offset: Option<i32>,
631    /// Result filtering rules (max 8).
632    #[serde(skip_serializing_if = "Option::is_none")]
633    pub filters: Option<Vec<Value>>,
634    /// Pagination token returned by a previous response.
635    #[serde(skip_serializing_if = "Option::is_none")]
636    pub search_after_token: Option<String>,
637    /// User-defined task identifier (max 255 characters).
638    #[serde(skip_serializing_if = "Option::is_none")]
639    pub tag: Option<String>,
640}
641
642impl OnPageApiLinksPost {
643    /// Creates a links request for the given task `id`.
644    pub fn new(id: String) -> Self {
645        OnPageApiLinksPost {
646            id,
647            ..OnPageApiLinksPost::default()
648        }
649    }
650}
651
652/// Request for [`OnPageApi::redirect_chains`].
653/// See <https://docs.dataforseo.com/v3/on_page/redirect_chains/>.
654#[derive(Debug, Default, Serialize, Deserialize, Clone)]
655pub struct OnPageApiRedirectChainsPost {
656    /// Task identifier returned by the Task POST endpoint.
657    pub id: String,
658    /// Restrict results to redirect chains starting at this URL.
659    #[serde(skip_serializing_if = "Option::is_none")]
660    pub url: Option<String>,
661    /// Maximum number of chains to return (default 100, max 1000).
662    #[serde(skip_serializing_if = "Option::is_none")]
663    pub limit: Option<i32>,
664    /// Offset into the results array (default 0).
665    #[serde(skip_serializing_if = "Option::is_none")]
666    pub offset: Option<i32>,
667    /// Result filtering rules; only `is_redirect_loop` is supported.
668    #[serde(skip_serializing_if = "Option::is_none")]
669    pub filters: Option<Vec<Value>>,
670    /// User-defined task identifier (max 255 characters).
671    #[serde(skip_serializing_if = "Option::is_none")]
672    pub tag: Option<String>,
673}
674
675impl OnPageApiRedirectChainsPost {
676    /// Creates a redirect-chains request for the given task `id`.
677    pub fn new(id: String) -> Self {
678        OnPageApiRedirectChainsPost {
679            id,
680            ..OnPageApiRedirectChainsPost::default()
681        }
682    }
683}
684
685/// Request for [`OnPageApi::non_indexable`].
686/// See <https://docs.dataforseo.com/v3/on_page/non_indexable/>.
687#[derive(Debug, Default, Serialize, Deserialize, Clone)]
688pub struct OnPageApiNonIndexablePost {
689    /// Task identifier returned by the Task POST endpoint.
690    pub id: String,
691    /// Maximum number of pages to return (default 100, max 1000).
692    #[serde(skip_serializing_if = "Option::is_none")]
693    pub limit: Option<i32>,
694    /// Offset into the results array (default 0).
695    #[serde(skip_serializing_if = "Option::is_none")]
696    pub offset: Option<i32>,
697    /// Result filtering rules (max 8).
698    #[serde(skip_serializing_if = "Option::is_none")]
699    pub filters: Option<Vec<Value>>,
700}
701
702impl OnPageApiNonIndexablePost {
703    /// Creates a non-indexable request for the given task `id`.
704    pub fn new(id: String) -> Self {
705        OnPageApiNonIndexablePost {
706            id,
707            ..OnPageApiNonIndexablePost::default()
708        }
709    }
710}
711
712/// Request for [`OnPageApi::waterfall`].
713/// See <https://docs.dataforseo.com/v3/on_page/waterfall/>.
714#[derive(Debug, Default, Serialize, Deserialize, Clone)]
715pub struct OnPageApiWaterfallPost {
716    /// Task identifier returned by the Task POST endpoint.
717    pub id: String,
718    /// Page URL to build the resource loading waterfall for.
719    pub url: String,
720    /// User-defined task identifier (max 255 characters).
721    #[serde(skip_serializing_if = "Option::is_none")]
722    pub tag: Option<String>,
723}
724
725impl OnPageApiWaterfallPost {
726    /// Creates a waterfall request for task `id` and page `url`.
727    pub fn new(id: String, url: String) -> OnPageApiWaterfallPost {
728        OnPageApiWaterfallPost { id, url, tag: None }
729    }
730}
731
732/// Request for [`OnPageApi::keyword_density`].
733/// See <https://docs.dataforseo.com/v3/on_page/keyword_density/>.
734#[derive(Debug, Default, Serialize, Deserialize, Clone)]
735pub struct OnPageApiKeywordDensityPost {
736    /// Task identifier returned by the Task POST endpoint.
737    pub id: String,
738    /// Number of words per keyword (1-5).
739    pub keyword_length: i32,
740    /// Restrict results to this page URL; omit for whole-site results.
741    #[serde(skip_serializing_if = "Option::is_none")]
742    pub url: Option<String>,
743    /// Maximum number of keywords to return (default 100, max 1000).
744    #[serde(skip_serializing_if = "Option::is_none")]
745    pub limit: Option<i32>,
746    /// Offset into the results array (default 0).
747    #[serde(skip_serializing_if = "Option::is_none")]
748    pub offset: Option<i32>,
749    /// Result filtering rules (max 8).
750    #[serde(skip_serializing_if = "Option::is_none")]
751    pub filters: Option<Vec<Vec<String>>>,
752    /// Sorting rules, each as "field,asc" or "field,desc" (max 3).
753    #[serde(skip_serializing_if = "Option::is_none")]
754    pub order_by: Option<Vec<String>>,
755    /// User-defined task identifier (max 255 characters).
756    #[serde(skip_serializing_if = "Option::is_none")]
757    pub tag: Option<String>,
758}
759
760impl OnPageApiKeywordDensityPost {
761    /// Creates a keyword-density request for task `id` and the given `keyword_length`.
762    pub fn new(id: String, keyword_length: i32) -> OnPageApiKeywordDensityPost {
763        OnPageApiKeywordDensityPost {
764            id,
765            keyword_length,
766            ..OnPageApiKeywordDensityPost::default()
767        }
768    }
769}
770
771/// Request for [`OnPageApi::microdata`].
772/// See <https://docs.dataforseo.com/v3/on_page/microdata/>.
773#[derive(Debug, Default, Serialize, Deserialize, Clone)]
774pub struct OnPageApiMicrodataPost {
775    /// Task identifier returned by the Task POST endpoint.
776    pub id: String,
777    /// Page URL to validate structured markup for.
778    pub url: String,
779    /// User-defined task identifier (max 255 characters).
780    #[serde(skip_serializing_if = "Option::is_none")]
781    pub tag: Option<String>,
782}
783
784impl OnPageApiMicrodataPost {
785    /// Creates a microdata request for task `id` and page `url`.
786    pub fn new(id: String, url: String) -> OnPageApiMicrodataPost {
787        OnPageApiMicrodataPost { id, url, tag: None }
788    }
789}
790
791/// Request for [`OnPageApi::raw_html`].
792/// See <https://docs.dataforseo.com/v3/on_page/raw_html/>.
793#[derive(Debug, Default, Serialize, Deserialize, Clone)]
794pub struct OnPageApiRawHtmlPost {
795    /// Task identifier returned by the Task POST endpoint.
796    pub id: String,
797    /// Page URL whose stored raw HTML to return.
798    pub url: String,
799}
800
801impl OnPageApiRawHtmlPost {
802    /// Creates a raw-HTML request for task `id` and page `url`.
803    pub fn new(id: String, url: String) -> Self {
804        OnPageApiRawHtmlPost { id, url }
805    }
806}
807
808/// Request for [`OnPageApi::page_screenshot`].
809/// See <https://docs.dataforseo.com/v3/on_page/page_screenshot/>.
810#[derive(Debug, Default, Serialize, Deserialize, Clone)]
811pub struct OnPageApiPageScreenshotPost {
812    /// Page URL to capture.
813    pub url: String,
814    /// Value of the Accept-Language header sent while loading the page.
815    #[serde(skip_serializing_if = "Option::is_none")]
816    pub accept_language: Option<String>,
817    /// Custom User-Agent header sent while loading the page.
818    #[serde(skip_serializing_if = "Option::is_none")]
819    pub custom_user_agent: Option<String>,
820    /// Device preset for rendering: "desktop", "mobile", or "tablet".
821    #[serde(skip_serializing_if = "Option::is_none")]
822    pub browser_preset: Option<String>,
823    /// Viewport width used for rendering, in pixels.
824    #[serde(skip_serializing_if = "Option::is_none")]
825    pub browser_screen_width: Option<i32>,
826    /// Viewport height used for rendering, in pixels.
827    #[serde(skip_serializing_if = "Option::is_none")]
828    pub browser_screen_height: Option<i32>,
829    /// Device pixel ratio used for rendering.
830    #[serde(skip_serializing_if = "Option::is_none")]
831    pub browser_screen_scale_factor: Option<f64>,
832    /// Capture the entire scrollable page rather than just the viewport.
833    #[serde(skip_serializing_if = "Option::is_none")]
834    pub full_page_screenshot: Option<bool>,
835    /// Hide cookie-consent popups before capturing.
836    #[serde(skip_serializing_if = "Option::is_none")]
837    pub disable_cookie_popup: Option<bool>,
838    /// Retry using a different proxy pool if the first attempt fails.
839    #[serde(skip_serializing_if = "Option::is_none")]
840    pub switch_pool: Option<bool>,
841    /// Proxy location to load the page from: "us" or "de".
842    #[serde(skip_serializing_if = "Option::is_none")]
843    pub ip_pool_for_scan: Option<String>,
844}
845
846impl OnPageApiPageScreenshotPost {
847    /// Creates a screenshot request for the given page `url`.
848    pub fn new(url: String) -> Self {
849        OnPageApiPageScreenshotPost {
850            url,
851            ..OnPageApiPageScreenshotPost::default()
852        }
853    }
854}
855
856/// Request for [`OnPageApi::content_parsing`].
857/// See <https://docs.dataforseo.com/v3/on_page/content_parsing/>.
858#[derive(Debug, Default, Serialize, Deserialize, Clone)]
859pub struct OnPageApiContentParsingPost {
860    /// Task identifier returned by the Task POST endpoint.
861    pub id: String,
862    /// Page URL whose parsed content to return.
863    pub url: String,
864    /// Return the page content rendered as Markdown.
865    #[serde(skip_serializing_if = "Option::is_none")]
866    pub markdown_view: Option<bool>,
867}
868
869impl OnPageApiContentParsingPost {
870    /// Creates a content-parsing request for task `id` and page `url`.
871    pub fn new(id: String, url: String) -> Self {
872        OnPageApiContentParsingPost {
873            id,
874            url,
875            ..OnPageApiContentParsingPost::default()
876        }
877    }
878}
879
880/// Request for [`OnPageApi::content_parsing_live`].
881/// See <https://docs.dataforseo.com/v3/on_page/content_parsing/live/>.
882#[derive(Debug, Default, Serialize, Deserialize, Clone)]
883pub struct OnPageApiContentParsingLivePost {
884    /// Page URL to fetch and parse.
885    pub url: String,
886    /// Custom User-Agent header sent while loading the page.
887    #[serde(skip_serializing_if = "Option::is_none")]
888    pub custom_user_agent: Option<String>,
889    /// Device preset for rendering: "desktop", "mobile", or "tablet".
890    #[serde(skip_serializing_if = "Option::is_none")]
891    pub browser_preset: Option<String>,
892    /// Viewport width used for rendering, in pixels.
893    #[serde(skip_serializing_if = "Option::is_none")]
894    pub browser_screen_width: Option<i32>,
895    /// Viewport height used for rendering, in pixels.
896    #[serde(skip_serializing_if = "Option::is_none")]
897    pub browser_screen_height: Option<i32>,
898    /// Device pixel ratio used for rendering.
899    #[serde(skip_serializing_if = "Option::is_none")]
900    pub browser_screen_scale_factor: Option<f64>,
901    /// Store the raw HTML for later retrieval.
902    #[serde(skip_serializing_if = "Option::is_none")]
903    pub store_raw_html: Option<bool>,
904    /// Hide cookie-consent popups before loading the page.
905    #[serde(skip_serializing_if = "Option::is_none")]
906    pub disable_cookie_popup: Option<bool>,
907    /// Value of the Accept-Language header sent while loading the page.
908    #[serde(skip_serializing_if = "Option::is_none")]
909    pub accept_language: Option<String>,
910    /// Execute page JavaScript (incurs extra cost).
911    #[serde(skip_serializing_if = "Option::is_none")]
912    pub enable_javascript: Option<bool>,
913    /// Emulate full browser rendering.
914    #[serde(skip_serializing_if = "Option::is_none")]
915    pub enable_browser_rendering: Option<bool>,
916    /// Allow XMLHttpRequest calls while rendering the page.
917    #[serde(skip_serializing_if = "Option::is_none")]
918    pub enable_xhr: Option<bool>,
919    /// Retry using a different proxy pool if the first attempt fails.
920    #[serde(skip_serializing_if = "Option::is_none")]
921    pub switch_pool: Option<bool>,
922    /// Proxy location to load the page from: "us" or "de".
923    #[serde(skip_serializing_if = "Option::is_none")]
924    pub ip_pool_for_scan: Option<String>,
925    /// Return the page content rendered as Markdown.
926    #[serde(skip_serializing_if = "Option::is_none")]
927    pub markdown_view: Option<bool>,
928}
929
930impl OnPageApiContentParsingLivePost {
931    /// Creates a live content-parsing request for the given page `url`.
932    pub fn new(url: String) -> Self {
933        OnPageApiContentParsingLivePost {
934            url,
935            ..OnPageApiContentParsingLivePost::default()
936        }
937    }
938}
939
940/// Request for [`OnPageApi::instant_pages`].
941/// See <https://docs.dataforseo.com/v3/on_page/instant_pages/>.
942#[derive(Debug, Default, Serialize, Deserialize, Clone)]
943pub struct OnPageApiInstantPagesPost {
944    /// Page URL to crawl.
945    pub url: String,
946    /// Custom User-Agent header sent while loading the page.
947    #[serde(skip_serializing_if = "Option::is_none")]
948    pub custom_user_agent: Option<String>,
949    /// Device preset for rendering: "desktop", "mobile", or "tablet".
950    #[serde(skip_serializing_if = "Option::is_none")]
951    pub browser_preset: Option<String>,
952    /// Viewport width used for rendering, in pixels.
953    #[serde(skip_serializing_if = "Option::is_none")]
954    pub browser_screen_width: Option<i32>,
955    /// Viewport height used for rendering, in pixels.
956    #[serde(skip_serializing_if = "Option::is_none")]
957    pub browser_screen_height: Option<i32>,
958    /// Device pixel ratio used for rendering.
959    #[serde(skip_serializing_if = "Option::is_none")]
960    pub browser_screen_scale_factor: Option<f64>,
961    /// Store the raw HTML for later retrieval.
962    #[serde(skip_serializing_if = "Option::is_none")]
963    pub store_raw_html: Option<bool>,
964    /// Value of the Accept-Language header sent while loading the page.
965    #[serde(skip_serializing_if = "Option::is_none")]
966    pub accept_language: Option<String>,
967    /// Load page resources (images, scripts, stylesheets) while crawling.
968    #[serde(skip_serializing_if = "Option::is_none")]
969    pub load_resources: Option<bool>,
970    /// Execute page JavaScript (incurs extra cost).
971    #[serde(skip_serializing_if = "Option::is_none")]
972    pub enable_javascript: Option<bool>,
973    /// Emulate full browser rendering to measure Core Web Vitals.
974    #[serde(skip_serializing_if = "Option::is_none")]
975    pub enable_browser_rendering: Option<bool>,
976    /// Hide cookie-consent popups before loading the page.
977    #[serde(skip_serializing_if = "Option::is_none")]
978    pub disable_cookie_popup: Option<bool>,
979    /// Return partial results even if the request times out.
980    #[serde(skip_serializing_if = "Option::is_none")]
981    pub return_despite_timeout: Option<bool>,
982    /// Allow XMLHttpRequest calls while rendering the page.
983    #[serde(skip_serializing_if = "Option::is_none")]
984    pub enable_xhr: Option<bool>,
985    /// Custom JavaScript to execute on the page.
986    #[serde(skip_serializing_if = "Option::is_none")]
987    pub custom_js: Option<String>,
988    /// Validate structured microdata markup.
989    #[serde(skip_serializing_if = "Option::is_none")]
990    pub validate_micromarkup: Option<bool>,
991    /// Check spelling on the page using the Hunspell library.
992    #[serde(skip_serializing_if = "Option::is_none")]
993    pub check_spell: Option<bool>,
994    /// Custom threshold values for the checks in the response.
995    #[serde(skip_serializing_if = "Option::is_none")]
996    pub checks_threshold: Option<Value>,
997    /// Retry using a different proxy pool if the first attempt fails.
998    #[serde(skip_serializing_if = "Option::is_none")]
999    pub switch_pool: Option<bool>,
1000    /// Proxy location to load the page from: "us" or "de".
1001    #[serde(skip_serializing_if = "Option::is_none")]
1002    pub ip_pool_for_scan: Option<String>,
1003}
1004
1005impl OnPageApiInstantPagesPost {
1006    /// Creates an instant-pages request for the given page `url`.
1007    pub fn new(url: String) -> Self {
1008        OnPageApiInstantPagesPost {
1009            url,
1010            ..OnPageApiInstantPagesPost::default()
1011        }
1012    }
1013}
1014
1015/// Request for [`OnPageApi::id_list`].
1016/// See <https://docs.dataforseo.com/v3/on_page/id_list/>.
1017#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1018pub struct OnPageApiIdListPost {
1019    /// Start of the time range, as "yyyy-mm-dd hh-mm-ss +00:00".
1020    pub datetime_from: String,
1021    /// End of the time range, as "yyyy-mm-dd hh-mm-ss +00:00".
1022    pub datetime_to: String,
1023    /// Maximum number of task IDs to return (default 100, max 1000).
1024    #[serde(skip_serializing_if = "Option::is_none")]
1025    pub limit: Option<i32>,
1026    /// Offset into the results array (default 0).
1027    #[serde(skip_serializing_if = "Option::is_none")]
1028    pub offset: Option<i32>,
1029    /// Sort order by post date: "asc" or "desc".
1030    #[serde(skip_serializing_if = "Option::is_none")]
1031    pub sort: Option<String>,
1032    /// Include each task's metadata in the response.
1033    #[serde(skip_serializing_if = "Option::is_none")]
1034    pub include_metadata: Option<bool>,
1035}
1036
1037impl OnPageApiIdListPost {
1038    /// Creates an id-list request for tasks created between `datetime_from` and `datetime_to`.
1039    pub fn new(datetime_from: String, datetime_to: String) -> Self {
1040        OnPageApiIdListPost {
1041            datetime_from,
1042            datetime_to,
1043            ..OnPageApiIdListPost::default()
1044        }
1045    }
1046}
1047
1048/// Request for [`OnPageApi::errors`].
1049/// See <https://docs.dataforseo.com/v3/on_page/errors/>.
1050#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1051pub struct OnPageApiErrorsPost {
1052    /// Maximum number of error records to return (default 1000, max 1000).
1053    #[serde(skip_serializing_if = "Option::is_none")]
1054    pub limit: Option<i32>,
1055    /// Offset into the results array (default 0).
1056    #[serde(skip_serializing_if = "Option::is_none")]
1057    pub offset: Option<i32>,
1058    /// Restrict results to a specific API function name.
1059    #[serde(skip_serializing_if = "Option::is_none")]
1060    pub filtered_function: Option<String>,
1061    /// Start of the time range (within the last 7 days).
1062    #[serde(skip_serializing_if = "Option::is_none")]
1063    pub datetime_from: Option<String>,
1064    /// End of the time range (within the last 7 days).
1065    #[serde(skip_serializing_if = "Option::is_none")]
1066    pub datetime_to: Option<String>,
1067}
1068
1069/// Request for [`OnPageApi::force_stop`].
1070/// See <https://docs.dataforseo.com/v3/on_page/force_stop/>.
1071#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1072pub struct OnPageApiForceStopPost {
1073    /// Identifier of the crawling task to stop.
1074    pub id: String,
1075}
1076
1077impl OnPageApiForceStopPost {
1078    /// Creates a force-stop request for the given task `id`.
1079    pub fn new(id: String) -> Self {
1080        OnPageApiForceStopPost { id }
1081    }
1082}
1083
1084/// Request for [`OnPageApi::lighthouse_task_post`].
1085/// See <https://docs.dataforseo.com/v3/on_page/lighthouse/task_post/>.
1086#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1087pub struct OnPageApiLighthouseTaskPost {
1088    /// Page URL to audit with Lighthouse.
1089    pub url: String,
1090    /// Run the audit emulating a mobile device.
1091    #[serde(skip_serializing_if = "Option::is_none")]
1092    pub for_mobile: Option<bool>,
1093    /// Lighthouse categories to run (e.g. "performance", "seo").
1094    #[serde(skip_serializing_if = "Option::is_none")]
1095    pub categories: Option<Vec<String>>,
1096    /// Specific Lighthouse audits to run.
1097    #[serde(skip_serializing_if = "Option::is_none")]
1098    pub audits: Option<Vec<String>>,
1099    /// Lighthouse version to use.
1100    #[serde(skip_serializing_if = "Option::is_none")]
1101    pub version: Option<String>,
1102    /// Full language name for the report (e.g. "English").
1103    #[serde(skip_serializing_if = "Option::is_none")]
1104    pub language_name: Option<String>,
1105    /// Language code for the report (e.g. "en").
1106    #[serde(skip_serializing_if = "Option::is_none")]
1107    pub language_code: Option<String>,
1108    /// User-defined task identifier (max 255 characters).
1109    #[serde(skip_serializing_if = "Option::is_none")]
1110    pub tag: Option<String>,
1111    /// URL notified by GET when the task completes.
1112    #[serde(skip_serializing_if = "Option::is_none")]
1113    pub pingback_url: Option<String>,
1114    /// URL the results are POSTed to when the task completes.
1115    #[serde(skip_serializing_if = "Option::is_none")]
1116    pub postback_url: Option<String>,
1117}
1118
1119impl OnPageApiLighthouseTaskPost {
1120    /// Creates a Lighthouse task request for the given page `url`.
1121    pub fn new(url: String) -> Self {
1122        OnPageApiLighthouseTaskPost {
1123            url,
1124            ..OnPageApiLighthouseTaskPost::default()
1125        }
1126    }
1127}
1128
1129/// Request for [`OnPageApi::lighthouse_live`].
1130/// See <https://docs.dataforseo.com/v3/on_page/lighthouse/live/>.
1131#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1132pub struct OnPageApiLighthouseLivePost {
1133    /// Page URL to audit with Lighthouse.
1134    pub url: String,
1135    /// Run the audit emulating a mobile device.
1136    #[serde(skip_serializing_if = "Option::is_none")]
1137    pub for_mobile: Option<bool>,
1138    /// Lighthouse categories to run (e.g. "performance", "seo").
1139    #[serde(skip_serializing_if = "Option::is_none")]
1140    pub categories: Option<Vec<String>>,
1141    /// Specific Lighthouse audits to run.
1142    #[serde(skip_serializing_if = "Option::is_none")]
1143    pub audits: Option<Vec<String>>,
1144    /// Lighthouse version to use.
1145    #[serde(skip_serializing_if = "Option::is_none")]
1146    pub version: Option<String>,
1147    /// Full language name for the report (e.g. "English").
1148    #[serde(skip_serializing_if = "Option::is_none")]
1149    pub language_name: Option<String>,
1150    /// Language code for the report (e.g. "en").
1151    #[serde(skip_serializing_if = "Option::is_none")]
1152    pub language_code: Option<String>,
1153    /// Custom User-Agent header sent while loading the page.
1154    #[serde(skip_serializing_if = "Option::is_none")]
1155    pub custom_user_agent: Option<String>,
1156    /// Viewport width used for rendering, in pixels.
1157    #[serde(skip_serializing_if = "Option::is_none")]
1158    pub browser_screen_width: Option<i32>,
1159    /// Viewport height used for rendering, in pixels.
1160    #[serde(skip_serializing_if = "Option::is_none")]
1161    pub browser_screen_height: Option<i32>,
1162    /// Device pixel ratio used for rendering.
1163    #[serde(skip_serializing_if = "Option::is_none")]
1164    pub browser_screen_scale_factor: Option<f64>,
1165    /// Network throttling method: "provided", "devtools", or "simulate".
1166    #[serde(skip_serializing_if = "Option::is_none")]
1167    pub browser_network_throttling_method: Option<String>,
1168    /// CPU slowdown multiplier applied during the audit.
1169    #[serde(skip_serializing_if = "Option::is_none")]
1170    pub browser_cpu_throttling_multiplier: Option<f64>,
1171    /// Network throttling preset applied during the audit.
1172    #[serde(skip_serializing_if = "Option::is_none")]
1173    pub browser_network_throttling: Option<String>,
1174    /// User-defined task identifier (max 255 characters).
1175    #[serde(skip_serializing_if = "Option::is_none")]
1176    pub tag: Option<String>,
1177}
1178
1179impl OnPageApiLighthouseLivePost {
1180    /// Creates a live Lighthouse request for the given page `url`.
1181    pub fn new(url: String) -> Self {
1182        OnPageApiLighthouseLivePost {
1183            url,
1184            ..OnPageApiLighthouseLivePost::default()
1185        }
1186    }
1187}