Skip to main content

data_for_seo/api/dataforseo_labs/
google.rs

1//! Google endpoints of the DataForSEO Labs API.
2//! See <https://docs.dataforseo.com/v3/dataforseo_labs/google/>.
3
4use crate::entity::{
5    DataForSeoLabsAppCompetitorItem, DataForSeoLabsAppIntersectionItem,
6    DataForSeoLabsAppKeywordItem, DataForSeoLabsBulkAppMetricsItem,
7    DataForSeoLabsCategoriesForKeywordsItem, DataForSeoLabsCategoryMetricsItem,
8    DataForSeoLabsCompetitorItem, DataForSeoLabsDomainIntersectionItem,
9    DataForSeoLabsDomainMetricsByCategoriesItem, DataForSeoLabsDomainMetricsItem,
10    DataForSeoLabsHistoricalKeywordDataItem, DataForSeoLabsHistoricalRankOverviewItem,
11    DataForSeoLabsHistoricalSerpItem, DataForSeoLabsHistoricalTrafficEstimationItem,
12    DataForSeoLabsKeywordData, DataForSeoLabsKeywordDifficultyItem,
13    DataForSeoLabsPageIntersectionItem, DataForSeoLabsRankedKeywordItem,
14    DataForSeoLabsRelatedKeywordItem, DataForSeoLabsRelevantPageItem, DataForSeoLabsResult,
15    DataForSeoLabsSearchIntentItem, DataForSeoLabsSerpCompetitorItem, DataForSeoLabsSubdomainItem,
16    DataForSeoLabsTrafficEstimationItem,
17};
18use crate::{DataForSeoApiResponse, DataForSeoClient};
19use serde::{Deserialize, Serialize};
20use serde_json::Value;
21use std::collections::HashMap;
22
23/// Google endpoints of the DataForSEO Labs API.
24pub struct DataForSeoLabsApiGoogle<'a> {
25    pub(crate) client: &'a DataForSeoClient,
26}
27
28impl DataForSeoLabsApiGoogle<'_> {
29    /// Keywords a domain/subdomain/page ranks for in organic and paid search.
30    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/ranked_keywords/live/>.
31    pub async fn ranked_keywords(
32        &self,
33        data: Vec<DataForSeoLabsRankedKeywordsRequest>,
34    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsRankedKeywordItem>> {
35        self.client
36            .http_post("/v3/dataforseo_labs/google/ranked_keywords/live", &data)
37            .await
38    }
39
40    /// Keyword ideas relevant to the provided seed keywords.
41    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/>.
42    pub async fn keyword_ideas(
43        &self,
44        data: Vec<DataForSeoLabsKeywordIdeasRequest>,
45    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsKeywordData>> {
46        self.client
47            .http_post("/v3/dataforseo_labs/google/keyword_ideas/live", &data)
48            .await
49    }
50
51    /// Keyword suggestions that include the seed keyword as a substring.
52    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_suggestions/live/>.
53    pub async fn keyword_suggestions(
54        &self,
55        data: Vec<DataForSeoLabsKeywordSuggestionsRequest>,
56    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsKeywordData>> {
57        self.client
58            .http_post("/v3/dataforseo_labs/google/keyword_suggestions/live", &data)
59            .await
60    }
61
62    /// Keywords related to a seed keyword, discovered via "searches related to".
63    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/related_keywords/live/>.
64    pub async fn related_keywords(
65        &self,
66        data: Vec<DataForSeoLabsRelatedKeywordsRequest>,
67    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsRelatedKeywordItem>> {
68        self.client
69            .http_post("/v3/dataforseo_labs/google/related_keywords/live", &data)
70            .await
71    }
72
73    /// Keywords a website is known to be relevant for.
74    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keywords_for_site/live/>.
75    pub async fn keywords_for_site(
76        &self,
77        data: Vec<DataForSeoLabsKeywordsForSiteRequest>,
78    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsKeywordData>> {
79        self.client
80            .http_post("/v3/dataforseo_labs/google/keywords_for_site/live", &data)
81            .await
82    }
83
84    /// Keyword difficulty for a batch of keywords.
85    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/bulk_keyword_difficulty/live/>.
86    pub async fn bulk_keyword_difficulty(
87        &self,
88        data: Vec<DataForSeoLabsBulkKeywordDifficultyRequest>,
89    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsKeywordDifficultyItem>> {
90        self.client
91            .http_post(
92                "/v3/dataforseo_labs/google/bulk_keyword_difficulty/live",
93                &data,
94            )
95            .await
96    }
97
98    /// Search-intent classification for a batch of keywords.
99    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/search_intent/live/>.
100    pub async fn search_intent(
101        &self,
102        data: Vec<DataForSeoLabsSearchIntentRequest>,
103    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsSearchIntentItem>> {
104        self.client
105            .http_post("/v3/dataforseo_labs/google/search_intent/live", &data)
106            .await
107    }
108
109    /// Full keyword metrics (overview) for a batch of keywords.
110    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_overview/live/>.
111    pub async fn keyword_overview(
112        &self,
113        data: Vec<DataForSeoLabsKeywordOverviewRequest>,
114    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsKeywordData>> {
115        self.client
116            .http_post("/v3/dataforseo_labs/google/keyword_overview/live", &data)
117            .await
118    }
119
120    /// Historical monthly Google Ads metrics for a batch of keywords.
121    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/historical_keyword_data/live/>.
122    pub async fn historical_keyword_data(
123        &self,
124        data: Vec<DataForSeoLabsHistoricalKeywordDataRequest>,
125    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsHistoricalKeywordDataItem>> {
126        self.client
127            .http_post(
128                "/v3/dataforseo_labs/google/historical_keyword_data/live",
129                &data,
130            )
131            .await
132    }
133
134    /// Historical SERP snapshots for a keyword.
135    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/historical_serps/live/>.
136    pub async fn historical_serps(
137        &self,
138        data: Vec<DataForSeoLabsHistoricalSerpsRequest>,
139    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsHistoricalSerpItem>> {
140        self.client
141            .http_post("/v3/dataforseo_labs/google/historical_serps/live", &data)
142            .await
143    }
144
145    /// Most popular keywords for a location/language.
146    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/top_searches/live/>.
147    pub async fn top_searches(
148        &self,
149        data: Vec<DataForSeoLabsTopSearchesRequest>,
150    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsKeywordData>> {
151        self.client
152            .http_post("/v3/dataforseo_labs/google/top_searches/live", &data)
153            .await
154    }
155
156    /// Domains competing for a set of keywords in the live SERP.
157    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/serp_competitors/live/>.
158    pub async fn serp_competitors(
159        &self,
160        data: Vec<DataForSeoLabsSerpCompetitorsRequest>,
161    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsSerpCompetitorItem>> {
162        self.client
163            .http_post("/v3/dataforseo_labs/google/serp_competitors/live", &data)
164            .await
165    }
166
167    /// Domains that compete with a target across their organic keywords.
168    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/competitors_domain/live/>.
169    pub async fn competitors_domain(
170        &self,
171        data: Vec<DataForSeoLabsCompetitorsDomainRequest>,
172    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsCompetitorItem>> {
173        self.client
174            .http_post("/v3/dataforseo_labs/google/competitors_domain/live", &data)
175            .await
176    }
177
178    /// Keywords two domains both rank for, with each domain's SERP element.
179    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/domain_intersection/live/>.
180    pub async fn domain_intersection(
181        &self,
182        data: Vec<DataForSeoLabsDomainIntersectionRequest>,
183    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsDomainIntersectionItem>> {
184        self.client
185            .http_post("/v3/dataforseo_labs/google/domain_intersection/live", &data)
186            .await
187    }
188
189    /// Subdomains of a target and their ranking metrics.
190    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/subdomains/live/>.
191    pub async fn subdomains(
192        &self,
193        data: Vec<DataForSeoLabsSubdomainsRequest>,
194    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsSubdomainItem>> {
195        self.client
196            .http_post("/v3/dataforseo_labs/google/subdomains/live", &data)
197            .await
198    }
199
200    /// Pages of a target ranked by the number of keywords they rank for.
201    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/relevant_pages/live/>.
202    pub async fn relevant_pages(
203        &self,
204        data: Vec<DataForSeoLabsRelevantPagesRequest>,
205    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsRelevantPageItem>> {
206        self.client
207            .http_post("/v3/dataforseo_labs/google/relevant_pages/live", &data)
208            .await
209    }
210
211    /// Aggregated ranking overview of a domain.
212    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/domain_rank_overview/live/>.
213    pub async fn domain_rank_overview(
214        &self,
215        data: Vec<DataForSeoLabsDomainRankOverviewRequest>,
216    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsDomainMetricsItem>> {
217        self.client
218            .http_post(
219                "/v3/dataforseo_labs/google/domain_rank_overview/live",
220                &data,
221            )
222            .await
223    }
224
225    /// Keywords for which a set of pages appear together in the SERP.
226    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/page_intersection/live/>.
227    pub async fn page_intersection(
228        &self,
229        data: Vec<DataForSeoLabsPageIntersectionRequest>,
230    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsPageIntersectionItem>> {
231        self.client
232            .http_post("/v3/dataforseo_labs/google/page_intersection/live", &data)
233            .await
234    }
235
236    /// Estimated organic/paid traffic for a batch of targets.
237    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/bulk_traffic_estimation/live/>.
238    pub async fn bulk_traffic_estimation(
239        &self,
240        data: Vec<DataForSeoLabsBulkTrafficEstimationRequest>,
241    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsTrafficEstimationItem>> {
242        self.client
243            .http_post(
244                "/v3/dataforseo_labs/google/bulk_traffic_estimation/live",
245                &data,
246            )
247            .await
248    }
249
250    /// Historical estimated traffic for a batch of targets.
251    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/historical_bulk_traffic_estimation/live/>.
252    pub async fn historical_bulk_traffic_estimation(
253        &self,
254        data: Vec<DataForSeoLabsHistoricalBulkTrafficEstimationRequest>,
255    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsHistoricalTrafficEstimationItem>>
256    {
257        self.client
258            .http_post(
259                "/v3/dataforseo_labs/google/historical_bulk_traffic_estimation/live",
260                &data,
261            )
262            .await
263    }
264
265    /// Monthly historical ranking overview of a domain.
266    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/historical_rank_overview/live/>.
267    pub async fn historical_rank_overview(
268        &self,
269        data: Vec<DataForSeoLabsHistoricalRankOverviewRequest>,
270    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsHistoricalRankOverviewItem>> {
271        self.client
272            .http_post(
273                "/v3/dataforseo_labs/google/historical_rank_overview/live",
274                &data,
275            )
276            .await
277    }
278
279    /// Product categories a domain ranks in, with per-category metrics.
280    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/categories_for_domain/live/>.
281    pub async fn categories_for_domain(
282        &self,
283        data: Vec<DataForSeoLabsCategoriesForDomainRequest>,
284    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsCategoryMetricsItem>> {
285        self.client
286            .http_post(
287                "/v3/dataforseo_labs/google/categories_for_domain/live",
288                &data,
289            )
290            .await
291    }
292
293    /// Product categories associated with a batch of keywords.
294    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/categories_for_keywords/live/>.
295    pub async fn categories_for_keywords(
296        &self,
297        data: Vec<DataForSeoLabsCategoriesForKeywordsRequest>,
298    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsCategoriesForKeywordsItem>> {
299        self.client
300            .http_post(
301                "/v3/dataforseo_labs/google/categories_for_keywords/live",
302                &data,
303            )
304            .await
305    }
306
307    /// Keywords that belong to a set of product categories.
308    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keywords_for_categories/live/>.
309    pub async fn keywords_for_categories(
310        &self,
311        data: Vec<DataForSeoLabsKeywordsForCategoriesRequest>,
312    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsKeywordData>> {
313        self.client
314            .http_post(
315                "/v3/dataforseo_labs/google/keywords_for_categories/live",
316                &data,
317            )
318            .await
319    }
320
321    /// Domains ranking within a set of product categories, with their metrics.
322    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/domain_metrics_by_categories/live/>.
323    pub async fn domain_metrics_by_categories(
324        &self,
325        data: Vec<DataForSeoLabsDomainMetricsByCategoriesRequest>,
326    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsDomainMetricsByCategoriesItem>>
327    {
328        self.client
329            .http_post(
330                "/v3/dataforseo_labs/google/domain_metrics_by_categories/live",
331                &data,
332            )
333            .await
334    }
335
336    /// Keywords a Google Play app ranks for.
337    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keywords_for_app/live/>.
338    pub async fn keywords_for_app(
339        &self,
340        data: Vec<DataForSeoLabsKeywordsForAppRequest>,
341    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsAppKeywordItem>> {
342        self.client
343            .http_post("/v3/dataforseo_labs/google/keywords_for_app/live", &data)
344            .await
345    }
346
347    /// Google Play apps competing with a target app.
348    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/app_competitors/live/>.
349    pub async fn app_competitors(
350        &self,
351        data: Vec<DataForSeoLabsAppCompetitorsRequest>,
352    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsAppCompetitorItem>> {
353        self.client
354            .http_post("/v3/dataforseo_labs/google/app_competitors/live", &data)
355            .await
356    }
357
358    /// Keywords a set of Google Play apps rank for together.
359    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/app_intersection/live/>.
360    pub async fn app_intersection(
361        &self,
362        data: Vec<DataForSeoLabsAppIntersectionRequest>,
363    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsAppIntersectionItem>> {
364        self.client
365            .http_post("/v3/dataforseo_labs/google/app_intersection/live", &data)
366            .await
367    }
368
369    /// Aggregated metrics for a batch of Google Play apps.
370    /// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/bulk_app_metrics/live/>.
371    pub async fn bulk_app_metrics(
372        &self,
373        data: Vec<DataForSeoLabsBulkAppMetricsRequest>,
374    ) -> DataForSeoApiResponse<DataForSeoLabsResult<DataForSeoLabsBulkAppMetricsItem>> {
375        self.client
376            .http_post("/v3/dataforseo_labs/google/bulk_app_metrics/live", &data)
377            .await
378    }
379}
380
381/// Request body for `ranked_keywords`.
382/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/ranked_keywords/live/>.
383#[derive(Debug, Default, Serialize, Deserialize, Clone)]
384pub struct DataForSeoLabsRankedKeywordsRequest {
385    /// Domain, subdomain, or webpage the request targets.
386    pub target: String,
387    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
388    #[serde(skip_serializing_if = "Option::is_none")]
389    pub location_name: Option<String>,
390    /// Location code (e.g. `2840`); alternative to `location_name`.
391    #[serde(skip_serializing_if = "Option::is_none")]
392    pub location_code: Option<i32>,
393    /// Full language name (e.g. `"English"`); alternative to `language_code`.
394    #[serde(skip_serializing_if = "Option::is_none")]
395    pub language_name: Option<String>,
396    /// Language code (e.g. `"en"`); alternative to `language_name`.
397    #[serde(skip_serializing_if = "Option::is_none")]
398    pub language_code: Option<String>,
399    /// Whether to exclude highly similar keywords from the results.
400    #[serde(skip_serializing_if = "Option::is_none")]
401    pub ignore_synonyms: Option<bool>,
402    /// SERP feature types to include (e.g. `"organic"`, `"paid"`).
403    #[serde(skip_serializing_if = "Option::is_none")]
404    pub item_types: Option<Vec<String>>,
405    /// Whether to enrich the response with clickstream-based metrics.
406    #[serde(skip_serializing_if = "Option::is_none")]
407    pub include_clickstream_data: Option<bool>,
408    /// Whether to include the absolute rank of each element.
409    #[serde(skip_serializing_if = "Option::is_none")]
410    pub load_rank_absolute: Option<bool>,
411    /// How to treat historical SERP data: `"live"`, `"lost"`, or `"all"`.
412    #[serde(skip_serializing_if = "Option::is_none")]
413    pub historical_serp_mode: Option<String>,
414    /// Array of filtering conditions applied to the results.
415    #[serde(skip_serializing_if = "Option::is_none")]
416    pub filters: Option<Vec<Value>>,
417    /// Sorting rules applied to the results.
418    #[serde(skip_serializing_if = "Option::is_none")]
419    pub order_by: Option<Vec<String>>,
420    /// Maximum number of returned items (default 100, max 1000).
421    #[serde(skip_serializing_if = "Option::is_none")]
422    pub limit: Option<i32>,
423    /// Offset into the result set, for pagination.
424    #[serde(skip_serializing_if = "Option::is_none")]
425    pub offset: Option<i32>,
426    /// User-defined task identifier (max 255 characters).
427    #[serde(skip_serializing_if = "Option::is_none")]
428    pub tag: Option<String>,
429}
430
431impl DataForSeoLabsRankedKeywordsRequest {
432    /// Creates a request for the given target (domain, subdomain or page URL).
433    pub fn new(target: &str) -> DataForSeoLabsRankedKeywordsRequest {
434        DataForSeoLabsRankedKeywordsRequest {
435            target: target.to_string(),
436            ..Default::default()
437        }
438    }
439}
440
441/// Request body for `keyword_ideas`.
442/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/>.
443#[derive(Debug, Default, Serialize, Deserialize, Clone)]
444pub struct DataForSeoLabsKeywordIdeasRequest {
445    /// Keywords to analyze.
446    pub keywords: Vec<String>,
447    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
448    #[serde(skip_serializing_if = "Option::is_none")]
449    pub location_name: Option<String>,
450    /// Location code (e.g. `2840`); alternative to `location_name`.
451    #[serde(skip_serializing_if = "Option::is_none")]
452    pub location_code: Option<i32>,
453    /// Full language name (e.g. `"English"`); alternative to `language_code`.
454    #[serde(skip_serializing_if = "Option::is_none")]
455    pub language_name: Option<String>,
456    /// Language code (e.g. `"en"`); alternative to `language_name`.
457    #[serde(skip_serializing_if = "Option::is_none")]
458    pub language_code: Option<String>,
459    /// Whether to match only close variants of the seed keywords.
460    #[serde(skip_serializing_if = "Option::is_none")]
461    pub closely_variants: Option<bool>,
462    /// Whether to exclude highly similar keywords from the results.
463    #[serde(skip_serializing_if = "Option::is_none")]
464    pub ignore_synonyms: Option<bool>,
465    /// Whether to include SERP metadata for each keyword.
466    #[serde(skip_serializing_if = "Option::is_none")]
467    pub include_serp_info: Option<bool>,
468    /// Whether to enrich the response with clickstream-based metrics.
469    #[serde(skip_serializing_if = "Option::is_none")]
470    pub include_clickstream_data: Option<bool>,
471    /// Array of filtering conditions applied to the results.
472    #[serde(skip_serializing_if = "Option::is_none")]
473    pub filters: Option<Vec<Value>>,
474    /// Sorting rules applied to the results.
475    #[serde(skip_serializing_if = "Option::is_none")]
476    pub order_by: Option<Vec<String>>,
477    /// Maximum number of returned items (default 100, max 1000).
478    #[serde(skip_serializing_if = "Option::is_none")]
479    pub limit: Option<i32>,
480    /// Offset into the result set, for pagination.
481    #[serde(skip_serializing_if = "Option::is_none")]
482    pub offset: Option<i32>,
483    /// Token used to page beyond the standard offset limit.
484    #[serde(skip_serializing_if = "Option::is_none")]
485    pub offset_token: Option<String>,
486    /// User-defined task identifier (max 255 characters).
487    #[serde(skip_serializing_if = "Option::is_none")]
488    pub tag: Option<String>,
489}
490
491impl DataForSeoLabsKeywordIdeasRequest {
492    /// Creates a request for the given seed keywords.
493    pub fn new(keywords: Vec<String>) -> DataForSeoLabsKeywordIdeasRequest {
494        DataForSeoLabsKeywordIdeasRequest {
495            keywords,
496            ..Default::default()
497        }
498    }
499}
500
501/// Request body for `keyword_suggestions`.
502/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_suggestions/live/>.
503#[derive(Debug, Default, Serialize, Deserialize, Clone)]
504pub struct DataForSeoLabsKeywordSuggestionsRequest {
505    /// Keyword the data relates to.
506    pub keyword: String,
507    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
508    #[serde(skip_serializing_if = "Option::is_none")]
509    pub location_name: Option<String>,
510    /// Location code (e.g. `2840`); alternative to `location_name`.
511    #[serde(skip_serializing_if = "Option::is_none")]
512    pub location_code: Option<i32>,
513    /// Full language name (e.g. `"English"`); alternative to `language_code`.
514    #[serde(skip_serializing_if = "Option::is_none")]
515    pub language_name: Option<String>,
516    /// Language code (e.g. `"en"`); alternative to `language_name`.
517    #[serde(skip_serializing_if = "Option::is_none")]
518    pub language_code: Option<String>,
519    /// Whether to include data for the seed keyword itself.
520    #[serde(skip_serializing_if = "Option::is_none")]
521    pub include_seed_keyword: Option<bool>,
522    /// Whether to include SERP metadata for each keyword.
523    #[serde(skip_serializing_if = "Option::is_none")]
524    pub include_serp_info: Option<bool>,
525    /// Whether to enrich the response with clickstream-based metrics.
526    #[serde(skip_serializing_if = "Option::is_none")]
527    pub include_clickstream_data: Option<bool>,
528    /// Whether to return only keywords containing the exact seed phrase.
529    #[serde(skip_serializing_if = "Option::is_none")]
530    pub exact_match: Option<bool>,
531    /// Whether to exclude highly similar keywords from the results.
532    #[serde(skip_serializing_if = "Option::is_none")]
533    pub ignore_synonyms: Option<bool>,
534    /// Array of filtering conditions applied to the results.
535    #[serde(skip_serializing_if = "Option::is_none")]
536    pub filters: Option<Vec<Value>>,
537    /// Sorting rules applied to the results.
538    #[serde(skip_serializing_if = "Option::is_none")]
539    pub order_by: Option<Vec<String>>,
540    /// Maximum number of returned items (default 100, max 1000).
541    #[serde(skip_serializing_if = "Option::is_none")]
542    pub limit: Option<i32>,
543    /// Offset into the result set, for pagination.
544    #[serde(skip_serializing_if = "Option::is_none")]
545    pub offset: Option<i32>,
546    /// Token used to page beyond the standard offset limit.
547    #[serde(skip_serializing_if = "Option::is_none")]
548    pub offset_token: Option<String>,
549    /// User-defined task identifier (max 255 characters).
550    #[serde(skip_serializing_if = "Option::is_none")]
551    pub tag: Option<String>,
552}
553
554impl DataForSeoLabsKeywordSuggestionsRequest {
555    /// Creates a request for the given seed keyword.
556    pub fn new(keyword: &str) -> DataForSeoLabsKeywordSuggestionsRequest {
557        DataForSeoLabsKeywordSuggestionsRequest {
558            keyword: keyword.to_string(),
559            ..Default::default()
560        }
561    }
562}
563
564/// Request body for `related_keywords`.
565/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/related_keywords/live/>.
566#[derive(Debug, Default, Serialize, Deserialize, Clone)]
567pub struct DataForSeoLabsRelatedKeywordsRequest {
568    /// Keyword the data relates to.
569    pub keyword: String,
570    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
571    #[serde(skip_serializing_if = "Option::is_none")]
572    pub location_name: Option<String>,
573    /// Location code (e.g. `2840`); alternative to `location_name`.
574    #[serde(skip_serializing_if = "Option::is_none")]
575    pub location_code: Option<i32>,
576    /// Full language name (e.g. `"English"`); alternative to `language_code`.
577    #[serde(skip_serializing_if = "Option::is_none")]
578    pub language_name: Option<String>,
579    /// Language code (e.g. `"en"`); alternative to `language_name`.
580    #[serde(skip_serializing_if = "Option::is_none")]
581    pub language_code: Option<String>,
582    /// Keyword expansion depth (0-4); higher values return more keywords.
583    #[serde(skip_serializing_if = "Option::is_none")]
584    pub depth: Option<i64>,
585    /// Whether to include data for the seed keyword itself.
586    #[serde(skip_serializing_if = "Option::is_none")]
587    pub include_seed_keyword: Option<bool>,
588    /// Whether to include SERP metadata for each keyword.
589    #[serde(skip_serializing_if = "Option::is_none")]
590    pub include_serp_info: Option<bool>,
591    /// Whether to enrich the response with clickstream-based metrics.
592    #[serde(skip_serializing_if = "Option::is_none")]
593    pub include_clickstream_data: Option<bool>,
594    /// Whether to exclude highly similar keywords from the results.
595    #[serde(skip_serializing_if = "Option::is_none")]
596    pub ignore_synonyms: Option<bool>,
597    /// Whether to group results under their core (canonical) keyword.
598    #[serde(skip_serializing_if = "Option::is_none")]
599    pub replace_with_core_keyword: Option<bool>,
600    /// Array of filtering conditions applied to the results.
601    #[serde(skip_serializing_if = "Option::is_none")]
602    pub filters: Option<Vec<Value>>,
603    /// Sorting rules applied to the results.
604    #[serde(skip_serializing_if = "Option::is_none")]
605    pub order_by: Option<Vec<String>>,
606    /// Maximum number of returned items (default 100, max 1000).
607    #[serde(skip_serializing_if = "Option::is_none")]
608    pub limit: Option<i32>,
609    /// Offset into the result set, for pagination.
610    #[serde(skip_serializing_if = "Option::is_none")]
611    pub offset: Option<i32>,
612    /// User-defined task identifier (max 255 characters).
613    #[serde(skip_serializing_if = "Option::is_none")]
614    pub tag: Option<String>,
615}
616
617impl DataForSeoLabsRelatedKeywordsRequest {
618    /// Creates a request for the given seed keyword.
619    pub fn new(keyword: &str) -> DataForSeoLabsRelatedKeywordsRequest {
620        DataForSeoLabsRelatedKeywordsRequest {
621            keyword: keyword.to_string(),
622            ..Default::default()
623        }
624    }
625}
626
627/// Request body for `keywords_for_site`.
628/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keywords_for_site/live/>.
629#[derive(Debug, Default, Serialize, Deserialize, Clone)]
630pub struct DataForSeoLabsKeywordsForSiteRequest {
631    /// Domain, subdomain, or webpage the request targets.
632    pub target: String,
633    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
634    #[serde(skip_serializing_if = "Option::is_none")]
635    pub location_name: Option<String>,
636    /// Location code (e.g. `2840`); alternative to `location_name`.
637    #[serde(skip_serializing_if = "Option::is_none")]
638    pub location_code: Option<i32>,
639    /// Full language name (e.g. `"English"`); alternative to `language_code`.
640    #[serde(skip_serializing_if = "Option::is_none")]
641    pub language_name: Option<String>,
642    /// Language code (e.g. `"en"`); alternative to `language_name`.
643    #[serde(skip_serializing_if = "Option::is_none")]
644    pub language_code: Option<String>,
645    /// Type of target: `"domain"`, `"subdomain"`, or `"page"`.
646    #[serde(skip_serializing_if = "Option::is_none")]
647    pub target_type: Option<String>,
648    /// Whether to include SERP metadata for each keyword.
649    #[serde(skip_serializing_if = "Option::is_none")]
650    pub include_serp_info: Option<bool>,
651    /// Whether to include subdomains of the target.
652    #[serde(skip_serializing_if = "Option::is_none")]
653    pub include_subdomains: Option<bool>,
654    /// Whether to enrich the response with clickstream-based metrics.
655    #[serde(skip_serializing_if = "Option::is_none")]
656    pub include_clickstream_data: Option<bool>,
657    /// Whether to exclude highly similar keywords from the results.
658    #[serde(skip_serializing_if = "Option::is_none")]
659    pub ignore_synonyms: Option<bool>,
660    /// Array of filtering conditions applied to the results.
661    #[serde(skip_serializing_if = "Option::is_none")]
662    pub filters: Option<Vec<Value>>,
663    /// Sorting rules applied to the results.
664    #[serde(skip_serializing_if = "Option::is_none")]
665    pub order_by: Option<Vec<String>>,
666    /// Maximum number of returned items (default 100, max 1000).
667    #[serde(skip_serializing_if = "Option::is_none")]
668    pub limit: Option<i32>,
669    /// Offset into the result set, for pagination.
670    #[serde(skip_serializing_if = "Option::is_none")]
671    pub offset: Option<i32>,
672    /// User-defined task identifier (max 255 characters).
673    #[serde(skip_serializing_if = "Option::is_none")]
674    pub tag: Option<String>,
675}
676
677impl DataForSeoLabsKeywordsForSiteRequest {
678    /// Creates a request for the given target site.
679    pub fn new(target: &str) -> DataForSeoLabsKeywordsForSiteRequest {
680        DataForSeoLabsKeywordsForSiteRequest {
681            target: target.to_string(),
682            ..Default::default()
683        }
684    }
685}
686
687/// Request body for `bulk_keyword_difficulty`.
688/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/bulk_keyword_difficulty/live/>.
689#[derive(Debug, Default, Serialize, Deserialize, Clone)]
690pub struct DataForSeoLabsBulkKeywordDifficultyRequest {
691    /// Keywords to analyze.
692    pub keywords: Vec<String>,
693    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
694    #[serde(skip_serializing_if = "Option::is_none")]
695    pub location_name: Option<String>,
696    /// Location code (e.g. `2840`); alternative to `location_name`.
697    #[serde(skip_serializing_if = "Option::is_none")]
698    pub location_code: Option<i32>,
699    /// Full language name (e.g. `"English"`); alternative to `language_code`.
700    #[serde(skip_serializing_if = "Option::is_none")]
701    pub language_name: Option<String>,
702    /// Language code (e.g. `"en"`); alternative to `language_name`.
703    #[serde(skip_serializing_if = "Option::is_none")]
704    pub language_code: Option<String>,
705    /// User-defined task identifier (max 255 characters).
706    #[serde(skip_serializing_if = "Option::is_none")]
707    pub tag: Option<String>,
708}
709
710impl DataForSeoLabsBulkKeywordDifficultyRequest {
711    /// Creates a request for the given keywords.
712    pub fn new(keywords: Vec<String>) -> DataForSeoLabsBulkKeywordDifficultyRequest {
713        DataForSeoLabsBulkKeywordDifficultyRequest {
714            keywords,
715            ..Default::default()
716        }
717    }
718}
719
720/// Request body for `search_intent`.
721/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/search_intent/live/>.
722#[derive(Debug, Default, Serialize, Deserialize, Clone)]
723pub struct DataForSeoLabsSearchIntentRequest {
724    /// Keywords to analyze.
725    pub keywords: Vec<String>,
726    /// Full language name (e.g. `"English"`); alternative to `language_code`.
727    #[serde(skip_serializing_if = "Option::is_none")]
728    pub language_name: Option<String>,
729    /// Language code (e.g. `"en"`); alternative to `language_name`.
730    #[serde(skip_serializing_if = "Option::is_none")]
731    pub language_code: Option<String>,
732    /// User-defined task identifier (max 255 characters).
733    #[serde(skip_serializing_if = "Option::is_none")]
734    pub tag: Option<String>,
735}
736
737impl DataForSeoLabsSearchIntentRequest {
738    /// Creates a request for the given keywords.
739    pub fn new(keywords: Vec<String>) -> DataForSeoLabsSearchIntentRequest {
740        DataForSeoLabsSearchIntentRequest {
741            keywords,
742            ..Default::default()
743        }
744    }
745}
746
747/// Request body for `keyword_overview`.
748/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_overview/live/>.
749#[derive(Debug, Default, Serialize, Deserialize, Clone)]
750pub struct DataForSeoLabsKeywordOverviewRequest {
751    /// Keywords to analyze.
752    pub keywords: Vec<String>,
753    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
754    #[serde(skip_serializing_if = "Option::is_none")]
755    pub location_name: Option<String>,
756    /// Location code (e.g. `2840`); alternative to `location_name`.
757    #[serde(skip_serializing_if = "Option::is_none")]
758    pub location_code: Option<i32>,
759    /// Full language name (e.g. `"English"`); alternative to `language_code`.
760    #[serde(skip_serializing_if = "Option::is_none")]
761    pub language_name: Option<String>,
762    /// Language code (e.g. `"en"`); alternative to `language_name`.
763    #[serde(skip_serializing_if = "Option::is_none")]
764    pub language_code: Option<String>,
765    /// Whether to include SERP metadata for each keyword.
766    #[serde(skip_serializing_if = "Option::is_none")]
767    pub include_serp_info: Option<bool>,
768    /// Whether to enrich the response with clickstream-based metrics.
769    #[serde(skip_serializing_if = "Option::is_none")]
770    pub include_clickstream_data: Option<bool>,
771    /// User-defined task identifier (max 255 characters).
772    #[serde(skip_serializing_if = "Option::is_none")]
773    pub tag: Option<String>,
774}
775
776impl DataForSeoLabsKeywordOverviewRequest {
777    /// Creates a request for the given keywords.
778    pub fn new(keywords: Vec<String>) -> DataForSeoLabsKeywordOverviewRequest {
779        DataForSeoLabsKeywordOverviewRequest {
780            keywords,
781            ..Default::default()
782        }
783    }
784}
785
786/// Request body for `historical_keyword_data`.
787/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/historical_keyword_data/live/>.
788#[derive(Debug, Default, Serialize, Deserialize, Clone)]
789pub struct DataForSeoLabsHistoricalKeywordDataRequest {
790    /// Keywords to analyze.
791    pub keywords: Vec<String>,
792    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
793    #[serde(skip_serializing_if = "Option::is_none")]
794    pub location_name: Option<String>,
795    /// Location code (e.g. `2840`); alternative to `location_name`.
796    #[serde(skip_serializing_if = "Option::is_none")]
797    pub location_code: Option<i32>,
798    /// Full language name (e.g. `"English"`); alternative to `language_code`.
799    #[serde(skip_serializing_if = "Option::is_none")]
800    pub language_name: Option<String>,
801    /// Language code (e.g. `"en"`); alternative to `language_name`.
802    #[serde(skip_serializing_if = "Option::is_none")]
803    pub language_code: Option<String>,
804    /// User-defined task identifier (max 255 characters).
805    #[serde(skip_serializing_if = "Option::is_none")]
806    pub tag: Option<String>,
807}
808
809impl DataForSeoLabsHistoricalKeywordDataRequest {
810    /// Creates a request for the given keywords.
811    pub fn new(keywords: Vec<String>) -> DataForSeoLabsHistoricalKeywordDataRequest {
812        DataForSeoLabsHistoricalKeywordDataRequest {
813            keywords,
814            ..Default::default()
815        }
816    }
817}
818
819/// Request body for `historical_serps`.
820/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/historical_serps/live/>.
821#[derive(Debug, Default, Serialize, Deserialize, Clone)]
822pub struct DataForSeoLabsHistoricalSerpsRequest {
823    /// Keyword the data relates to.
824    pub keyword: String,
825    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
826    #[serde(skip_serializing_if = "Option::is_none")]
827    pub location_name: Option<String>,
828    /// Location code (e.g. `2840`); alternative to `location_name`.
829    #[serde(skip_serializing_if = "Option::is_none")]
830    pub location_code: Option<i32>,
831    /// Full language name (e.g. `"English"`); alternative to `language_code`.
832    #[serde(skip_serializing_if = "Option::is_none")]
833    pub language_name: Option<String>,
834    /// Language code (e.g. `"en"`); alternative to `language_name`.
835    #[serde(skip_serializing_if = "Option::is_none")]
836    pub language_code: Option<String>,
837    /// Start date of the range, `yyyy-mm-dd`.
838    #[serde(skip_serializing_if = "Option::is_none")]
839    pub date_from: Option<String>,
840    /// End date of the range, `yyyy-mm-dd`.
841    #[serde(skip_serializing_if = "Option::is_none")]
842    pub date_to: Option<String>,
843    /// User-defined task identifier (max 255 characters).
844    #[serde(skip_serializing_if = "Option::is_none")]
845    pub tag: Option<String>,
846}
847
848impl DataForSeoLabsHistoricalSerpsRequest {
849    /// Creates a request for the given keyword.
850    pub fn new(keyword: &str) -> DataForSeoLabsHistoricalSerpsRequest {
851        DataForSeoLabsHistoricalSerpsRequest {
852            keyword: keyword.to_string(),
853            ..Default::default()
854        }
855    }
856}
857
858/// Request body for `top_searches`.
859/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/top_searches/live/>.
860#[derive(Debug, Default, Serialize, Deserialize, Clone)]
861pub struct DataForSeoLabsTopSearchesRequest {
862    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
863    #[serde(skip_serializing_if = "Option::is_none")]
864    pub location_name: Option<String>,
865    /// Location code (e.g. `2840`); alternative to `location_name`.
866    #[serde(skip_serializing_if = "Option::is_none")]
867    pub location_code: Option<i32>,
868    /// Full language name (e.g. `"English"`); alternative to `language_code`.
869    #[serde(skip_serializing_if = "Option::is_none")]
870    pub language_name: Option<String>,
871    /// Language code (e.g. `"en"`); alternative to `language_name`.
872    #[serde(skip_serializing_if = "Option::is_none")]
873    pub language_code: Option<String>,
874    /// Whether to include SERP metadata for each keyword.
875    #[serde(skip_serializing_if = "Option::is_none")]
876    pub include_serp_info: Option<bool>,
877    /// Whether to enrich the response with clickstream-based metrics.
878    #[serde(skip_serializing_if = "Option::is_none")]
879    pub include_clickstream_data: Option<bool>,
880    /// Whether to exclude highly similar keywords from the results.
881    #[serde(skip_serializing_if = "Option::is_none")]
882    pub ignore_synonyms: Option<bool>,
883    /// Array of filtering conditions applied to the results.
884    #[serde(skip_serializing_if = "Option::is_none")]
885    pub filters: Option<Vec<Value>>,
886    /// Sorting rules applied to the results.
887    #[serde(skip_serializing_if = "Option::is_none")]
888    pub order_by: Option<Vec<String>>,
889    /// Maximum number of returned items (default 100, max 1000).
890    #[serde(skip_serializing_if = "Option::is_none")]
891    pub limit: Option<i32>,
892    /// Offset into the result set, for pagination.
893    #[serde(skip_serializing_if = "Option::is_none")]
894    pub offset: Option<i32>,
895    /// Token used to page beyond the standard offset limit.
896    #[serde(skip_serializing_if = "Option::is_none")]
897    pub offset_token: Option<String>,
898    /// User-defined task identifier (max 255 characters).
899    #[serde(skip_serializing_if = "Option::is_none")]
900    pub tag: Option<String>,
901}
902
903impl DataForSeoLabsTopSearchesRequest {
904    /// Creates a request for the given location/language (set via the fields).
905    pub fn new() -> DataForSeoLabsTopSearchesRequest {
906        DataForSeoLabsTopSearchesRequest::default()
907    }
908}
909
910/// Request body for `serp_competitors`.
911/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/serp_competitors/live/>.
912#[derive(Debug, Default, Serialize, Deserialize, Clone)]
913pub struct DataForSeoLabsSerpCompetitorsRequest {
914    /// Keywords to analyze.
915    pub keywords: Vec<String>,
916    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
917    #[serde(skip_serializing_if = "Option::is_none")]
918    pub location_name: Option<String>,
919    /// Location code (e.g. `2840`); alternative to `location_name`.
920    #[serde(skip_serializing_if = "Option::is_none")]
921    pub location_code: Option<i32>,
922    /// Full language name (e.g. `"English"`); alternative to `language_code`.
923    #[serde(skip_serializing_if = "Option::is_none")]
924    pub language_name: Option<String>,
925    /// Language code (e.g. `"en"`); alternative to `language_name`.
926    #[serde(skip_serializing_if = "Option::is_none")]
927    pub language_code: Option<String>,
928    /// Whether to include subdomains of the target.
929    #[serde(skip_serializing_if = "Option::is_none")]
930    pub include_subdomains: Option<bool>,
931    /// SERP feature types to include (e.g. `"organic"`, `"paid"`).
932    #[serde(skip_serializing_if = "Option::is_none")]
933    pub item_types: Option<Vec<String>>,
934    /// Array of filtering conditions applied to the results.
935    #[serde(skip_serializing_if = "Option::is_none")]
936    pub filters: Option<Vec<Value>>,
937    /// Sorting rules applied to the results.
938    #[serde(skip_serializing_if = "Option::is_none")]
939    pub order_by: Option<Vec<String>>,
940    /// Maximum number of returned items (default 100, max 1000).
941    #[serde(skip_serializing_if = "Option::is_none")]
942    pub limit: Option<i32>,
943    /// Offset into the result set, for pagination.
944    #[serde(skip_serializing_if = "Option::is_none")]
945    pub offset: Option<i32>,
946    /// User-defined task identifier (max 255 characters).
947    #[serde(skip_serializing_if = "Option::is_none")]
948    pub tag: Option<String>,
949}
950
951impl DataForSeoLabsSerpCompetitorsRequest {
952    /// Creates a request for the given keywords.
953    pub fn new(keywords: Vec<String>) -> DataForSeoLabsSerpCompetitorsRequest {
954        DataForSeoLabsSerpCompetitorsRequest {
955            keywords,
956            ..Default::default()
957        }
958    }
959}
960
961/// Request body for `competitors_domain`.
962/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/competitors_domain/live/>.
963#[derive(Debug, Default, Serialize, Deserialize, Clone)]
964pub struct DataForSeoLabsCompetitorsDomainRequest {
965    /// Domain, subdomain, or webpage the request targets.
966    pub target: String,
967    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
968    #[serde(skip_serializing_if = "Option::is_none")]
969    pub location_name: Option<String>,
970    /// Location code (e.g. `2840`); alternative to `location_name`.
971    #[serde(skip_serializing_if = "Option::is_none")]
972    pub location_code: Option<i32>,
973    /// Full language name (e.g. `"English"`); alternative to `language_code`.
974    #[serde(skip_serializing_if = "Option::is_none")]
975    pub language_name: Option<String>,
976    /// Language code (e.g. `"en"`); alternative to `language_name`.
977    #[serde(skip_serializing_if = "Option::is_none")]
978    pub language_code: Option<String>,
979    /// SERP feature types to include (e.g. `"organic"`, `"paid"`).
980    #[serde(skip_serializing_if = "Option::is_none")]
981    pub item_types: Option<Vec<String>>,
982    /// Whether to enrich the response with clickstream-based metrics.
983    #[serde(skip_serializing_if = "Option::is_none")]
984    pub include_clickstream_data: Option<bool>,
985    /// Maximum rank position considered when detecting competitors.
986    #[serde(skip_serializing_if = "Option::is_none")]
987    pub max_rank_group: Option<i64>,
988    /// Whether to exclude the most popular domains from the results.
989    #[serde(skip_serializing_if = "Option::is_none")]
990    pub exclude_top_domains: Option<bool>,
991    /// Domains to exclude from the results.
992    #[serde(skip_serializing_if = "Option::is_none")]
993    pub exclude_domains: Option<Vec<String>>,
994    /// Domains used to refine competitor-detection accuracy.
995    #[serde(skip_serializing_if = "Option::is_none")]
996    pub intersecting_domains: Option<Vec<String>>,
997    /// Whether to exclude highly similar keywords from the results.
998    #[serde(skip_serializing_if = "Option::is_none")]
999    pub ignore_synonyms: Option<bool>,
1000    /// Array of filtering conditions applied to the results.
1001    #[serde(skip_serializing_if = "Option::is_none")]
1002    pub filters: Option<Vec<Value>>,
1003    /// Sorting rules applied to the results.
1004    #[serde(skip_serializing_if = "Option::is_none")]
1005    pub order_by: Option<Vec<String>>,
1006    /// Maximum number of returned items (default 100, max 1000).
1007    #[serde(skip_serializing_if = "Option::is_none")]
1008    pub limit: Option<i32>,
1009    /// Offset into the result set, for pagination.
1010    #[serde(skip_serializing_if = "Option::is_none")]
1011    pub offset: Option<i32>,
1012    /// User-defined task identifier (max 255 characters).
1013    #[serde(skip_serializing_if = "Option::is_none")]
1014    pub tag: Option<String>,
1015}
1016
1017impl DataForSeoLabsCompetitorsDomainRequest {
1018    /// Creates a request for the given target domain.
1019    pub fn new(target: &str) -> DataForSeoLabsCompetitorsDomainRequest {
1020        DataForSeoLabsCompetitorsDomainRequest {
1021            target: target.to_string(),
1022            ..Default::default()
1023        }
1024    }
1025}
1026
1027/// Request body for `domain_intersection`.
1028/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/domain_intersection/live/>.
1029#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1030pub struct DataForSeoLabsDomainIntersectionRequest {
1031    /// First domain to compare.
1032    pub target1: String,
1033    /// Second domain to compare.
1034    pub target2: String,
1035    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1036    #[serde(skip_serializing_if = "Option::is_none")]
1037    pub location_name: Option<String>,
1038    /// Location code (e.g. `2840`); alternative to `location_name`.
1039    #[serde(skip_serializing_if = "Option::is_none")]
1040    pub location_code: Option<i32>,
1041    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1042    #[serde(skip_serializing_if = "Option::is_none")]
1043    pub language_name: Option<String>,
1044    /// Language code (e.g. `"en"`); alternative to `language_name`.
1045    #[serde(skip_serializing_if = "Option::is_none")]
1046    pub language_code: Option<String>,
1047    /// Whether to return only keywords both targets rank for.
1048    #[serde(skip_serializing_if = "Option::is_none")]
1049    pub intersections: Option<bool>,
1050    /// SERP feature types to include (e.g. `"organic"`, `"paid"`).
1051    #[serde(skip_serializing_if = "Option::is_none")]
1052    pub item_types: Option<Vec<String>>,
1053    /// Whether to include SERP metadata for each keyword.
1054    #[serde(skip_serializing_if = "Option::is_none")]
1055    pub include_serp_info: Option<bool>,
1056    /// Whether to enrich the response with clickstream-based metrics.
1057    #[serde(skip_serializing_if = "Option::is_none")]
1058    pub include_clickstream_data: Option<bool>,
1059    /// Array of filtering conditions applied to the results.
1060    #[serde(skip_serializing_if = "Option::is_none")]
1061    pub filters: Option<Vec<Value>>,
1062    /// Sorting rules applied to the results.
1063    #[serde(skip_serializing_if = "Option::is_none")]
1064    pub order_by: Option<Vec<String>>,
1065    /// Maximum number of returned items (default 100, max 1000).
1066    #[serde(skip_serializing_if = "Option::is_none")]
1067    pub limit: Option<i32>,
1068    /// Offset into the result set, for pagination.
1069    #[serde(skip_serializing_if = "Option::is_none")]
1070    pub offset: Option<i32>,
1071    /// User-defined task identifier (max 255 characters).
1072    #[serde(skip_serializing_if = "Option::is_none")]
1073    pub tag: Option<String>,
1074}
1075
1076impl DataForSeoLabsDomainIntersectionRequest {
1077    /// Creates a request comparing `target1` and `target2`.
1078    pub fn new(target1: &str, target2: &str) -> DataForSeoLabsDomainIntersectionRequest {
1079        DataForSeoLabsDomainIntersectionRequest {
1080            target1: target1.to_string(),
1081            target2: target2.to_string(),
1082            ..Default::default()
1083        }
1084    }
1085}
1086
1087/// Request body for `subdomains`.
1088/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/subdomains/live/>.
1089#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1090pub struct DataForSeoLabsSubdomainsRequest {
1091    /// Domain, subdomain, or webpage the request targets.
1092    pub target: String,
1093    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1094    #[serde(skip_serializing_if = "Option::is_none")]
1095    pub location_name: Option<String>,
1096    /// Location code (e.g. `2840`); alternative to `location_name`.
1097    #[serde(skip_serializing_if = "Option::is_none")]
1098    pub location_code: Option<i32>,
1099    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1100    #[serde(skip_serializing_if = "Option::is_none")]
1101    pub language_name: Option<String>,
1102    /// Language code (e.g. `"en"`); alternative to `language_name`.
1103    #[serde(skip_serializing_if = "Option::is_none")]
1104    pub language_code: Option<String>,
1105    /// SERP feature types to include (e.g. `"organic"`, `"paid"`).
1106    #[serde(skip_serializing_if = "Option::is_none")]
1107    pub item_types: Option<Vec<String>>,
1108    /// Whether to enrich the response with clickstream-based metrics.
1109    #[serde(skip_serializing_if = "Option::is_none")]
1110    pub include_clickstream_data: Option<bool>,
1111    /// How to treat historical SERP data: `"live"`, `"lost"`, or `"all"`.
1112    #[serde(skip_serializing_if = "Option::is_none")]
1113    pub historical_serp_mode: Option<String>,
1114    /// Whether to exclude highly similar keywords from the results.
1115    #[serde(skip_serializing_if = "Option::is_none")]
1116    pub ignore_synonyms: Option<bool>,
1117    /// Array of filtering conditions applied to the results.
1118    #[serde(skip_serializing_if = "Option::is_none")]
1119    pub filters: Option<Vec<Value>>,
1120    /// Sorting rules applied to the results.
1121    #[serde(skip_serializing_if = "Option::is_none")]
1122    pub order_by: Option<Vec<String>>,
1123    /// Maximum number of returned items (default 100, max 1000).
1124    #[serde(skip_serializing_if = "Option::is_none")]
1125    pub limit: Option<i32>,
1126    /// Offset into the result set, for pagination.
1127    #[serde(skip_serializing_if = "Option::is_none")]
1128    pub offset: Option<i32>,
1129    /// User-defined task identifier (max 255 characters).
1130    #[serde(skip_serializing_if = "Option::is_none")]
1131    pub tag: Option<String>,
1132}
1133
1134impl DataForSeoLabsSubdomainsRequest {
1135    /// Creates a request for the given target domain.
1136    pub fn new(target: &str) -> DataForSeoLabsSubdomainsRequest {
1137        DataForSeoLabsSubdomainsRequest {
1138            target: target.to_string(),
1139            ..Default::default()
1140        }
1141    }
1142}
1143
1144/// Request body for `relevant_pages`.
1145/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/relevant_pages/live/>.
1146#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1147pub struct DataForSeoLabsRelevantPagesRequest {
1148    /// Domain, subdomain, or webpage the request targets.
1149    pub target: String,
1150    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1151    #[serde(skip_serializing_if = "Option::is_none")]
1152    pub location_name: Option<String>,
1153    /// Location code (e.g. `2840`); alternative to `location_name`.
1154    #[serde(skip_serializing_if = "Option::is_none")]
1155    pub location_code: Option<i32>,
1156    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1157    #[serde(skip_serializing_if = "Option::is_none")]
1158    pub language_name: Option<String>,
1159    /// Language code (e.g. `"en"`); alternative to `language_name`.
1160    #[serde(skip_serializing_if = "Option::is_none")]
1161    pub language_code: Option<String>,
1162    /// SERP feature types to include (e.g. `"organic"`, `"paid"`).
1163    #[serde(skip_serializing_if = "Option::is_none")]
1164    pub item_types: Option<Vec<String>>,
1165    /// Whether to enrich the response with clickstream-based metrics.
1166    #[serde(skip_serializing_if = "Option::is_none")]
1167    pub include_clickstream_data: Option<bool>,
1168    /// Array of filtering conditions applied to the results.
1169    #[serde(skip_serializing_if = "Option::is_none")]
1170    pub filters: Option<Vec<Value>>,
1171    /// Sorting rules applied to the results.
1172    #[serde(skip_serializing_if = "Option::is_none")]
1173    pub order_by: Option<Vec<String>>,
1174    /// Maximum number of returned items (default 100, max 1000).
1175    #[serde(skip_serializing_if = "Option::is_none")]
1176    pub limit: Option<i32>,
1177    /// Offset into the result set, for pagination.
1178    #[serde(skip_serializing_if = "Option::is_none")]
1179    pub offset: Option<i32>,
1180    /// User-defined task identifier (max 255 characters).
1181    #[serde(skip_serializing_if = "Option::is_none")]
1182    pub tag: Option<String>,
1183}
1184
1185impl DataForSeoLabsRelevantPagesRequest {
1186    /// Creates a request for the given target domain.
1187    pub fn new(target: &str) -> DataForSeoLabsRelevantPagesRequest {
1188        DataForSeoLabsRelevantPagesRequest {
1189            target: target.to_string(),
1190            ..Default::default()
1191        }
1192    }
1193}
1194
1195/// Request body for `domain_rank_overview`.
1196/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/domain_rank_overview/live/>.
1197#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1198pub struct DataForSeoLabsDomainRankOverviewRequest {
1199    /// Domain, subdomain, or webpage the request targets.
1200    pub target: String,
1201    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1202    #[serde(skip_serializing_if = "Option::is_none")]
1203    pub location_name: Option<String>,
1204    /// Location code (e.g. `2840`); alternative to `location_name`.
1205    #[serde(skip_serializing_if = "Option::is_none")]
1206    pub location_code: Option<i32>,
1207    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1208    #[serde(skip_serializing_if = "Option::is_none")]
1209    pub language_name: Option<String>,
1210    /// Language code (e.g. `"en"`); alternative to `language_name`.
1211    #[serde(skip_serializing_if = "Option::is_none")]
1212    pub language_code: Option<String>,
1213    /// Whether to exclude highly similar keywords from the results.
1214    #[serde(skip_serializing_if = "Option::is_none")]
1215    pub ignore_synonyms: Option<bool>,
1216    /// Maximum number of returned items (default 100, max 1000).
1217    #[serde(skip_serializing_if = "Option::is_none")]
1218    pub limit: Option<i32>,
1219    /// Offset into the result set, for pagination.
1220    #[serde(skip_serializing_if = "Option::is_none")]
1221    pub offset: Option<i32>,
1222    /// User-defined task identifier (max 255 characters).
1223    #[serde(skip_serializing_if = "Option::is_none")]
1224    pub tag: Option<String>,
1225}
1226
1227impl DataForSeoLabsDomainRankOverviewRequest {
1228    /// Creates a request for the given target domain.
1229    pub fn new(target: &str) -> DataForSeoLabsDomainRankOverviewRequest {
1230        DataForSeoLabsDomainRankOverviewRequest {
1231            target: target.to_string(),
1232            ..Default::default()
1233        }
1234    }
1235}
1236
1237/// Request body for `page_intersection`.
1238/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/page_intersection/live/>.
1239#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1240pub struct DataForSeoLabsPageIntersectionRequest {
1241    /// Target page URLs to intersect, keyed by an index string.
1242    pub pages: HashMap<String, String>,
1243    /// Page URLs to exclude from the results.
1244    #[serde(skip_serializing_if = "Option::is_none")]
1245    pub exclude_pages: Option<Vec<String>>,
1246    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1247    #[serde(skip_serializing_if = "Option::is_none")]
1248    pub location_name: Option<String>,
1249    /// Location code (e.g. `2840`); alternative to `location_name`.
1250    #[serde(skip_serializing_if = "Option::is_none")]
1251    pub location_code: Option<i32>,
1252    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1253    #[serde(skip_serializing_if = "Option::is_none")]
1254    pub language_name: Option<String>,
1255    /// Language code (e.g. `"en"`); alternative to `language_name`.
1256    #[serde(skip_serializing_if = "Option::is_none")]
1257    pub language_code: Option<String>,
1258    /// SERP feature types to include (e.g. `"organic"`, `"paid"`).
1259    #[serde(skip_serializing_if = "Option::is_none")]
1260    pub item_types: Option<Vec<String>>,
1261    /// How the intersection is computed: `"union"` or `"intersect"`.
1262    #[serde(skip_serializing_if = "Option::is_none")]
1263    pub intersection_mode: Option<String>,
1264    /// Whether to include SERP metadata for each keyword.
1265    #[serde(skip_serializing_if = "Option::is_none")]
1266    pub include_serp_info: Option<bool>,
1267    /// Whether to enrich the response with clickstream-based metrics.
1268    #[serde(skip_serializing_if = "Option::is_none")]
1269    pub include_clickstream_data: Option<bool>,
1270    /// Array of filtering conditions applied to the results.
1271    #[serde(skip_serializing_if = "Option::is_none")]
1272    pub filters: Option<Vec<Value>>,
1273    /// Sorting rules applied to the results.
1274    #[serde(skip_serializing_if = "Option::is_none")]
1275    pub order_by: Option<Vec<String>>,
1276    /// Maximum number of returned items (default 100, max 1000).
1277    #[serde(skip_serializing_if = "Option::is_none")]
1278    pub limit: Option<i32>,
1279    /// Offset into the result set, for pagination.
1280    #[serde(skip_serializing_if = "Option::is_none")]
1281    pub offset: Option<i32>,
1282    /// User-defined task identifier (max 255 characters).
1283    #[serde(skip_serializing_if = "Option::is_none")]
1284    pub tag: Option<String>,
1285}
1286
1287impl DataForSeoLabsPageIntersectionRequest {
1288    /// Creates a request over the given pages map (index string -> page URL).
1289    pub fn new(pages: HashMap<String, String>) -> DataForSeoLabsPageIntersectionRequest {
1290        DataForSeoLabsPageIntersectionRequest {
1291            pages,
1292            ..Default::default()
1293        }
1294    }
1295}
1296
1297/// Request body for `bulk_traffic_estimation`.
1298/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/bulk_traffic_estimation/live/>.
1299#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1300pub struct DataForSeoLabsBulkTrafficEstimationRequest {
1301    /// Domains, subdomains, or webpages to analyze (up to 1000).
1302    pub targets: Vec<String>,
1303    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1304    #[serde(skip_serializing_if = "Option::is_none")]
1305    pub location_name: Option<String>,
1306    /// Location code (e.g. `2840`); alternative to `location_name`.
1307    #[serde(skip_serializing_if = "Option::is_none")]
1308    pub location_code: Option<i32>,
1309    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1310    #[serde(skip_serializing_if = "Option::is_none")]
1311    pub language_name: Option<String>,
1312    /// Language code (e.g. `"en"`); alternative to `language_name`.
1313    #[serde(skip_serializing_if = "Option::is_none")]
1314    pub language_code: Option<String>,
1315    /// SERP feature types to include (e.g. `"organic"`, `"paid"`).
1316    #[serde(skip_serializing_if = "Option::is_none")]
1317    pub item_types: Option<Vec<String>>,
1318    /// Whether to exclude highly similar keywords from the results.
1319    #[serde(skip_serializing_if = "Option::is_none")]
1320    pub ignore_synonyms: Option<bool>,
1321    /// User-defined task identifier (max 255 characters).
1322    #[serde(skip_serializing_if = "Option::is_none")]
1323    pub tag: Option<String>,
1324}
1325
1326impl DataForSeoLabsBulkTrafficEstimationRequest {
1327    /// Creates a request for the given targets.
1328    pub fn new(targets: Vec<String>) -> DataForSeoLabsBulkTrafficEstimationRequest {
1329        DataForSeoLabsBulkTrafficEstimationRequest {
1330            targets,
1331            ..Default::default()
1332        }
1333    }
1334}
1335
1336/// Request body for `historical_bulk_traffic_estimation`.
1337/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/historical_bulk_traffic_estimation/live/>.
1338#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1339pub struct DataForSeoLabsHistoricalBulkTrafficEstimationRequest {
1340    /// Domains, subdomains, or webpages to analyze (up to 1000).
1341    pub targets: Vec<String>,
1342    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1343    #[serde(skip_serializing_if = "Option::is_none")]
1344    pub location_name: Option<String>,
1345    /// Location code (e.g. `2840`); alternative to `location_name`.
1346    #[serde(skip_serializing_if = "Option::is_none")]
1347    pub location_code: Option<i32>,
1348    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1349    #[serde(skip_serializing_if = "Option::is_none")]
1350    pub language_name: Option<String>,
1351    /// Language code (e.g. `"en"`); alternative to `language_name`.
1352    #[serde(skip_serializing_if = "Option::is_none")]
1353    pub language_code: Option<String>,
1354    /// Start date of the range, `yyyy-mm-dd`.
1355    #[serde(skip_serializing_if = "Option::is_none")]
1356    pub date_from: Option<String>,
1357    /// End date of the range, `yyyy-mm-dd`.
1358    #[serde(skip_serializing_if = "Option::is_none")]
1359    pub date_to: Option<String>,
1360    /// Whether to exclude highly similar keywords from the results.
1361    #[serde(skip_serializing_if = "Option::is_none")]
1362    pub ignore_synonyms: Option<bool>,
1363    /// SERP feature types to include (e.g. `"organic"`, `"paid"`).
1364    #[serde(skip_serializing_if = "Option::is_none")]
1365    pub item_types: Option<Vec<String>>,
1366    /// User-defined task identifier (max 255 characters).
1367    #[serde(skip_serializing_if = "Option::is_none")]
1368    pub tag: Option<String>,
1369}
1370
1371impl DataForSeoLabsHistoricalBulkTrafficEstimationRequest {
1372    /// Creates a request for the given targets.
1373    pub fn new(targets: Vec<String>) -> DataForSeoLabsHistoricalBulkTrafficEstimationRequest {
1374        DataForSeoLabsHistoricalBulkTrafficEstimationRequest {
1375            targets,
1376            ..Default::default()
1377        }
1378    }
1379}
1380
1381/// Request body for `historical_rank_overview`.
1382/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/historical_rank_overview/live/>.
1383#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1384pub struct DataForSeoLabsHistoricalRankOverviewRequest {
1385    /// Domain, subdomain, or webpage the request targets.
1386    pub target: String,
1387    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1388    #[serde(skip_serializing_if = "Option::is_none")]
1389    pub location_name: Option<String>,
1390    /// Location code (e.g. `2840`); alternative to `location_name`.
1391    #[serde(skip_serializing_if = "Option::is_none")]
1392    pub location_code: Option<i32>,
1393    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1394    #[serde(skip_serializing_if = "Option::is_none")]
1395    pub language_name: Option<String>,
1396    /// Language code (e.g. `"en"`); alternative to `language_name`.
1397    #[serde(skip_serializing_if = "Option::is_none")]
1398    pub language_code: Option<String>,
1399    /// Start date of the range, `yyyy-mm-dd`.
1400    #[serde(skip_serializing_if = "Option::is_none")]
1401    pub date_from: Option<String>,
1402    /// End date of the range, `yyyy-mm-dd`.
1403    #[serde(skip_serializing_if = "Option::is_none")]
1404    pub date_to: Option<String>,
1405    /// Whether to align metrics across the returned dates.
1406    #[serde(skip_serializing_if = "Option::is_none")]
1407    pub correlate: Option<bool>,
1408    /// Whether to exclude highly similar keywords from the results.
1409    #[serde(skip_serializing_if = "Option::is_none")]
1410    pub ignore_synonyms: Option<bool>,
1411    /// Whether to enrich the response with clickstream-based metrics.
1412    #[serde(skip_serializing_if = "Option::is_none")]
1413    pub include_clickstream_data: Option<bool>,
1414    /// User-defined task identifier (max 255 characters).
1415    #[serde(skip_serializing_if = "Option::is_none")]
1416    pub tag: Option<String>,
1417}
1418
1419impl DataForSeoLabsHistoricalRankOverviewRequest {
1420    /// Creates a request for the given target domain.
1421    pub fn new(target: &str) -> DataForSeoLabsHistoricalRankOverviewRequest {
1422        DataForSeoLabsHistoricalRankOverviewRequest {
1423            target: target.to_string(),
1424            ..Default::default()
1425        }
1426    }
1427}
1428
1429/// Request body for `categories_for_domain`.
1430/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/categories_for_domain/live/>.
1431#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1432pub struct DataForSeoLabsCategoriesForDomainRequest {
1433    /// Domain, subdomain, or webpage the request targets.
1434    pub target: String,
1435    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1436    #[serde(skip_serializing_if = "Option::is_none")]
1437    pub location_name: Option<String>,
1438    /// Location code (e.g. `2840`); alternative to `location_name`.
1439    #[serde(skip_serializing_if = "Option::is_none")]
1440    pub location_code: Option<i32>,
1441    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1442    #[serde(skip_serializing_if = "Option::is_none")]
1443    pub language_name: Option<String>,
1444    /// Language code (e.g. `"en"`); alternative to `language_name`.
1445    #[serde(skip_serializing_if = "Option::is_none")]
1446    pub language_code: Option<String>,
1447    /// Whether to include subcategories in the results.
1448    #[serde(skip_serializing_if = "Option::is_none")]
1449    pub include_subcategories: Option<bool>,
1450    /// Whether to enrich the response with clickstream-based metrics.
1451    #[serde(skip_serializing_if = "Option::is_none")]
1452    pub include_clickstream_data: Option<bool>,
1453    /// How to treat historical SERP data: `"live"`, `"lost"`, or `"all"`.
1454    #[serde(skip_serializing_if = "Option::is_none")]
1455    pub historical_serp_mode: Option<String>,
1456    /// SERP feature types to include (e.g. `"organic"`, `"paid"`).
1457    #[serde(skip_serializing_if = "Option::is_none")]
1458    pub item_types: Option<Vec<String>>,
1459    /// Array of filtering conditions applied to the results.
1460    #[serde(skip_serializing_if = "Option::is_none")]
1461    pub filters: Option<Vec<Value>>,
1462    /// Sorting rules applied to the results.
1463    #[serde(skip_serializing_if = "Option::is_none")]
1464    pub order_by: Option<Vec<String>>,
1465    /// Maximum number of returned items (default 100, max 1000).
1466    #[serde(skip_serializing_if = "Option::is_none")]
1467    pub limit: Option<i32>,
1468    /// Offset into the result set, for pagination.
1469    #[serde(skip_serializing_if = "Option::is_none")]
1470    pub offset: Option<i32>,
1471    /// User-defined task identifier (max 255 characters).
1472    #[serde(skip_serializing_if = "Option::is_none")]
1473    pub tag: Option<String>,
1474}
1475
1476impl DataForSeoLabsCategoriesForDomainRequest {
1477    /// Creates a request for the given target domain.
1478    pub fn new(target: &str) -> DataForSeoLabsCategoriesForDomainRequest {
1479        DataForSeoLabsCategoriesForDomainRequest {
1480            target: target.to_string(),
1481            ..Default::default()
1482        }
1483    }
1484}
1485
1486/// Request body for `categories_for_keywords`.
1487/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/categories_for_keywords/live/>.
1488#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1489pub struct DataForSeoLabsCategoriesForKeywordsRequest {
1490    /// Keywords to analyze.
1491    pub keywords: Vec<String>,
1492    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1493    #[serde(skip_serializing_if = "Option::is_none")]
1494    pub language_name: Option<String>,
1495    /// Language code (e.g. `"en"`); alternative to `language_name`.
1496    #[serde(skip_serializing_if = "Option::is_none")]
1497    pub language_code: Option<String>,
1498    /// User-defined task identifier (max 255 characters).
1499    #[serde(skip_serializing_if = "Option::is_none")]
1500    pub tag: Option<String>,
1501}
1502
1503impl DataForSeoLabsCategoriesForKeywordsRequest {
1504    /// Creates a request for the given keywords.
1505    pub fn new(keywords: Vec<String>) -> DataForSeoLabsCategoriesForKeywordsRequest {
1506        DataForSeoLabsCategoriesForKeywordsRequest {
1507            keywords,
1508            ..Default::default()
1509        }
1510    }
1511}
1512
1513/// Request body for `keywords_for_categories`.
1514/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keywords_for_categories/live/>.
1515#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1516pub struct DataForSeoLabsKeywordsForCategoriesRequest {
1517    /// Product-category codes to query.
1518    pub category_codes: Vec<String>,
1519    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1520    #[serde(skip_serializing_if = "Option::is_none")]
1521    pub location_name: Option<String>,
1522    /// Location code (e.g. `2840`); alternative to `location_name`.
1523    #[serde(skip_serializing_if = "Option::is_none")]
1524    pub location_code: Option<i32>,
1525    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1526    #[serde(skip_serializing_if = "Option::is_none")]
1527    pub language_name: Option<String>,
1528    /// Language code (e.g. `"en"`); alternative to `language_name`.
1529    #[serde(skip_serializing_if = "Option::is_none")]
1530    pub language_code: Option<String>,
1531    /// Whether returned keywords must belong to all given categories.
1532    #[serde(skip_serializing_if = "Option::is_none")]
1533    pub category_intersection: Option<bool>,
1534    /// Whether to include SERP metadata for each keyword.
1535    #[serde(skip_serializing_if = "Option::is_none")]
1536    pub include_serp_info: Option<bool>,
1537    /// Whether to enrich the response with clickstream-based metrics.
1538    #[serde(skip_serializing_if = "Option::is_none")]
1539    pub include_clickstream_data: Option<bool>,
1540    /// Whether to exclude highly similar keywords from the results.
1541    #[serde(skip_serializing_if = "Option::is_none")]
1542    pub ignore_synonyms: Option<bool>,
1543    /// Array of filtering conditions applied to the results.
1544    #[serde(skip_serializing_if = "Option::is_none")]
1545    pub filters: Option<Vec<Value>>,
1546    /// Sorting rules applied to the results.
1547    #[serde(skip_serializing_if = "Option::is_none")]
1548    pub order_by: Option<Vec<String>>,
1549    /// Maximum number of returned items (default 100, max 1000).
1550    #[serde(skip_serializing_if = "Option::is_none")]
1551    pub limit: Option<i32>,
1552    /// Offset into the result set, for pagination.
1553    #[serde(skip_serializing_if = "Option::is_none")]
1554    pub offset: Option<i32>,
1555    /// Token used to page beyond the standard offset limit.
1556    #[serde(skip_serializing_if = "Option::is_none")]
1557    pub offset_token: Option<String>,
1558    /// User-defined task identifier (max 255 characters).
1559    #[serde(skip_serializing_if = "Option::is_none")]
1560    pub tag: Option<String>,
1561}
1562
1563impl DataForSeoLabsKeywordsForCategoriesRequest {
1564    /// Creates a request for the given product-category codes.
1565    pub fn new(category_codes: Vec<String>) -> DataForSeoLabsKeywordsForCategoriesRequest {
1566        DataForSeoLabsKeywordsForCategoriesRequest {
1567            category_codes,
1568            ..Default::default()
1569        }
1570    }
1571}
1572
1573/// Request body for `domain_metrics_by_categories`.
1574/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/domain_metrics_by_categories/live/>.
1575#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1576pub struct DataForSeoLabsDomainMetricsByCategoriesRequest {
1577    /// Product-category codes to query.
1578    pub category_codes: Vec<String>,
1579    /// First date to compare, `yyyy-mm-dd`.
1580    #[serde(skip_serializing_if = "Option::is_none")]
1581    pub first_date: Option<String>,
1582    /// Second date to compare, `yyyy-mm-dd`.
1583    #[serde(skip_serializing_if = "Option::is_none")]
1584    pub second_date: Option<String>,
1585    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1586    #[serde(skip_serializing_if = "Option::is_none")]
1587    pub location_name: Option<String>,
1588    /// Location code (e.g. `2840`); alternative to `location_name`.
1589    #[serde(skip_serializing_if = "Option::is_none")]
1590    pub location_code: Option<i32>,
1591    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1592    #[serde(skip_serializing_if = "Option::is_none")]
1593    pub language_name: Option<String>,
1594    /// Language code (e.g. `"en"`); alternative to `language_name`.
1595    #[serde(skip_serializing_if = "Option::is_none")]
1596    pub language_code: Option<String>,
1597    /// SERP feature types to include (e.g. `"organic"`, `"paid"`).
1598    #[serde(skip_serializing_if = "Option::is_none")]
1599    pub item_types: Option<Vec<String>>,
1600    /// Number of top categories to return.
1601    #[serde(skip_serializing_if = "Option::is_none")]
1602    pub top_categories_count: Option<i64>,
1603    /// Whether to include subdomains of the target.
1604    #[serde(skip_serializing_if = "Option::is_none")]
1605    pub include_subdomains: Option<bool>,
1606    /// Minimum estimated-traffic-volume filter.
1607    #[serde(skip_serializing_if = "Option::is_none")]
1608    pub etv_min: Option<i64>,
1609    /// Maximum estimated-traffic-volume filter.
1610    #[serde(skip_serializing_if = "Option::is_none")]
1611    pub etv_max: Option<i64>,
1612    /// Whether to align metrics across the returned dates.
1613    #[serde(skip_serializing_if = "Option::is_none")]
1614    pub correlate: Option<bool>,
1615    /// Array of filtering conditions applied to the results.
1616    #[serde(skip_serializing_if = "Option::is_none")]
1617    pub filters: Option<Vec<Value>>,
1618    /// Sorting rules applied to the results.
1619    #[serde(skip_serializing_if = "Option::is_none")]
1620    pub order_by: Option<Vec<String>>,
1621    /// Maximum number of returned items (default 100, max 1000).
1622    #[serde(skip_serializing_if = "Option::is_none")]
1623    pub limit: Option<i32>,
1624    /// Offset into the result set, for pagination.
1625    #[serde(skip_serializing_if = "Option::is_none")]
1626    pub offset: Option<i32>,
1627    /// User-defined task identifier (max 255 characters).
1628    #[serde(skip_serializing_if = "Option::is_none")]
1629    pub tag: Option<String>,
1630}
1631
1632impl DataForSeoLabsDomainMetricsByCategoriesRequest {
1633    /// Creates a request for the given product-category codes.
1634    pub fn new(category_codes: Vec<String>) -> DataForSeoLabsDomainMetricsByCategoriesRequest {
1635        DataForSeoLabsDomainMetricsByCategoriesRequest {
1636            category_codes,
1637            ..Default::default()
1638        }
1639    }
1640}
1641
1642/// Request body for `keywords_for_app`.
1643/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keywords_for_app/live/>.
1644#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1645pub struct DataForSeoLabsKeywordsForAppRequest {
1646    /// Store identifier of the app.
1647    pub app_id: String,
1648    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1649    #[serde(skip_serializing_if = "Option::is_none")]
1650    pub location_name: Option<String>,
1651    /// Location code (e.g. `2840`); alternative to `location_name`.
1652    #[serde(skip_serializing_if = "Option::is_none")]
1653    pub location_code: Option<i32>,
1654    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1655    #[serde(skip_serializing_if = "Option::is_none")]
1656    pub language_name: Option<String>,
1657    /// Language code (e.g. `"en"`); alternative to `language_name`.
1658    #[serde(skip_serializing_if = "Option::is_none")]
1659    pub language_code: Option<String>,
1660    /// Array of filtering conditions applied to the results.
1661    #[serde(skip_serializing_if = "Option::is_none")]
1662    pub filters: Option<Vec<Value>>,
1663    /// Sorting rules applied to the results.
1664    #[serde(skip_serializing_if = "Option::is_none")]
1665    pub order_by: Option<Vec<String>>,
1666    /// Maximum number of returned items (default 100, max 1000).
1667    #[serde(skip_serializing_if = "Option::is_none")]
1668    pub limit: Option<i32>,
1669    /// Offset into the result set, for pagination.
1670    #[serde(skip_serializing_if = "Option::is_none")]
1671    pub offset: Option<i32>,
1672    /// User-defined task identifier (max 255 characters).
1673    #[serde(skip_serializing_if = "Option::is_none")]
1674    pub tag: Option<String>,
1675}
1676
1677impl DataForSeoLabsKeywordsForAppRequest {
1678    /// Creates a request for the given Google Play app id.
1679    pub fn new(app_id: &str) -> DataForSeoLabsKeywordsForAppRequest {
1680        DataForSeoLabsKeywordsForAppRequest {
1681            app_id: app_id.to_string(),
1682            ..Default::default()
1683        }
1684    }
1685}
1686
1687/// Request body for `app_competitors`.
1688/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/app_competitors/live/>.
1689#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1690pub struct DataForSeoLabsAppCompetitorsRequest {
1691    /// Store identifier of the app.
1692    pub app_id: String,
1693    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1694    #[serde(skip_serializing_if = "Option::is_none")]
1695    pub location_name: Option<String>,
1696    /// Location code (e.g. `2840`); alternative to `location_name`.
1697    #[serde(skip_serializing_if = "Option::is_none")]
1698    pub location_code: Option<i32>,
1699    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1700    #[serde(skip_serializing_if = "Option::is_none")]
1701    pub language_name: Option<String>,
1702    /// Language code (e.g. `"en"`); alternative to `language_name`.
1703    #[serde(skip_serializing_if = "Option::is_none")]
1704    pub language_code: Option<String>,
1705    /// Array of filtering conditions applied to the results.
1706    #[serde(skip_serializing_if = "Option::is_none")]
1707    pub filters: Option<Vec<Value>>,
1708    /// Sorting rules applied to the results.
1709    #[serde(skip_serializing_if = "Option::is_none")]
1710    pub order_by: Option<Vec<String>>,
1711    /// Maximum number of returned items (default 100, max 1000).
1712    #[serde(skip_serializing_if = "Option::is_none")]
1713    pub limit: Option<i32>,
1714    /// Offset into the result set, for pagination.
1715    #[serde(skip_serializing_if = "Option::is_none")]
1716    pub offset: Option<i32>,
1717    /// User-defined task identifier (max 255 characters).
1718    #[serde(skip_serializing_if = "Option::is_none")]
1719    pub tag: Option<String>,
1720}
1721
1722impl DataForSeoLabsAppCompetitorsRequest {
1723    /// Creates a request for the given Google Play app id.
1724    pub fn new(app_id: &str) -> DataForSeoLabsAppCompetitorsRequest {
1725        DataForSeoLabsAppCompetitorsRequest {
1726            app_id: app_id.to_string(),
1727            ..Default::default()
1728        }
1729    }
1730}
1731
1732/// Request body for `app_intersection`.
1733/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/app_intersection/live/>.
1734#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1735pub struct DataForSeoLabsAppIntersectionRequest {
1736    /// App identifiers, keyed by an index string.
1737    pub app_ids: HashMap<String, String>,
1738    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1739    #[serde(skip_serializing_if = "Option::is_none")]
1740    pub location_name: Option<String>,
1741    /// Location code (e.g. `2840`); alternative to `location_name`.
1742    #[serde(skip_serializing_if = "Option::is_none")]
1743    pub location_code: Option<i32>,
1744    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1745    #[serde(skip_serializing_if = "Option::is_none")]
1746    pub language_name: Option<String>,
1747    /// Language code (e.g. `"en"`); alternative to `language_name`.
1748    #[serde(skip_serializing_if = "Option::is_none")]
1749    pub language_code: Option<String>,
1750    /// Array of filtering conditions applied to the results.
1751    #[serde(skip_serializing_if = "Option::is_none")]
1752    pub filters: Option<Vec<Value>>,
1753    /// Sorting rules applied to the results.
1754    #[serde(skip_serializing_if = "Option::is_none")]
1755    pub order_by: Option<Vec<String>>,
1756    /// Maximum number of returned items (default 100, max 1000).
1757    #[serde(skip_serializing_if = "Option::is_none")]
1758    pub limit: Option<i32>,
1759    /// Offset into the result set, for pagination.
1760    #[serde(skip_serializing_if = "Option::is_none")]
1761    pub offset: Option<i32>,
1762    /// User-defined task identifier (max 255 characters).
1763    #[serde(skip_serializing_if = "Option::is_none")]
1764    pub tag: Option<String>,
1765}
1766
1767impl DataForSeoLabsAppIntersectionRequest {
1768    /// Creates a request over the given app ids map (index string -> app id).
1769    pub fn new(app_ids: HashMap<String, String>) -> DataForSeoLabsAppIntersectionRequest {
1770        DataForSeoLabsAppIntersectionRequest {
1771            app_ids,
1772            ..Default::default()
1773        }
1774    }
1775}
1776
1777/// Request body for `bulk_app_metrics`.
1778/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/bulk_app_metrics/live/>.
1779#[derive(Debug, Default, Serialize, Deserialize, Clone)]
1780pub struct DataForSeoLabsBulkAppMetricsRequest {
1781    /// App identifiers, keyed by an index string.
1782    pub app_ids: Vec<String>,
1783    /// Full location name (e.g. `"United States"`); alternative to `location_code`.
1784    #[serde(skip_serializing_if = "Option::is_none")]
1785    pub location_name: Option<String>,
1786    /// Location code (e.g. `2840`); alternative to `location_name`.
1787    #[serde(skip_serializing_if = "Option::is_none")]
1788    pub location_code: Option<i32>,
1789    /// Full language name (e.g. `"English"`); alternative to `language_code`.
1790    #[serde(skip_serializing_if = "Option::is_none")]
1791    pub language_name: Option<String>,
1792    /// Language code (e.g. `"en"`); alternative to `language_name`.
1793    #[serde(skip_serializing_if = "Option::is_none")]
1794    pub language_code: Option<String>,
1795    /// User-defined task identifier (max 255 characters).
1796    #[serde(skip_serializing_if = "Option::is_none")]
1797    pub tag: Option<String>,
1798}
1799
1800impl DataForSeoLabsBulkAppMetricsRequest {
1801    /// Creates a request for the given Google Play app ids.
1802    pub fn new(app_ids: Vec<String>) -> DataForSeoLabsBulkAppMetricsRequest {
1803        DataForSeoLabsBulkAppMetricsRequest {
1804            app_ids,
1805            ..Default::default()
1806        }
1807    }
1808}