data_for_seo/entity/dataforseo_labs/element.rs
1//! Shared building blocks for DataForSEO Labs response models.
2//!
3//! These structs are reused across many Labs endpoints (ranked_keywords,
4//! keyword_ideas, competitors_domain, ...).
5//! See <https://docs.dataforseo.com/v3/dataforseo_labs/overview/>.
6
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9use std::collections::HashMap;
10
11/// Google Ads keyword metrics attached to a keyword.
12/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/>.
13#[derive(Debug, Default, Serialize, Deserialize, Clone)]
14pub struct DataForSeoLabsKeywordInfo {
15 /// Search engine type (e.g. `"google"`).
16 pub se_type: Option<String>,
17 /// Timestamp when this data was last updated (UTC).
18 pub last_updated_time: Option<String>,
19 /// Google Ads competition level, from 0 to 1.
20 pub competition: Option<f64>,
21 /// Competition category: `"LOW"`, `"MEDIUM"`, or `"HIGH"`.
22 pub competition_level: Option<String>,
23 /// Average cost per click (USD).
24 pub cpc: Option<f64>,
25 /// Average monthly search volume.
26 pub search_volume: Option<i64>,
27 /// Low range of the top-of-page bid (USD).
28 pub low_top_of_page_bid: Option<f64>,
29 /// High range of the top-of-page bid (USD).
30 pub high_top_of_page_bid: Option<f64>,
31 /// Product and service category codes for the keyword.
32 pub categories: Option<Vec<i64>>,
33 /// Search volume for each of the preceding months.
34 pub monthly_searches: Option<Vec<DataForSeoLabsMonthlySearch>>,
35 /// Percentage change of search volume across recent periods.
36 pub search_volume_trend: Option<DataForSeoLabsSearchVolumeTrend>,
37}
38
39/// A single month of historical search volume.
40#[derive(Debug, Default, Serialize, Deserialize, Clone)]
41pub struct DataForSeoLabsMonthlySearch {
42 /// Year the data point refers to.
43 pub year: Option<i64>,
44 /// Month the data point refers to (1-12).
45 pub month: Option<i64>,
46 /// Average monthly search volume.
47 pub search_volume: Option<i64>,
48}
49
50/// Percentage change of search volume across recent periods.
51#[derive(Debug, Default, Serialize, Deserialize, Clone)]
52pub struct DataForSeoLabsSearchVolumeTrend {
53 /// Percentage change compared with the previous month.
54 pub monthly: Option<i64>,
55 /// Percentage change compared with the previous quarter.
56 pub quarterly: Option<i64>,
57 /// Percentage change compared with the previous year.
58 pub yearly: Option<i64>,
59}
60
61/// Search volume normalized with a secondary data source (Bing or clickstream).
62/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/>.
63#[derive(Debug, Default, Serialize, Deserialize, Clone)]
64pub struct DataForSeoLabsKeywordInfoNormalized {
65 /// Search engine type (e.g. `"google"`).
66 pub se_type: Option<String>,
67 /// Timestamp when this data was last updated (UTC).
68 pub last_updated_time: Option<String>,
69 /// Whether the search volume was normalized with the secondary source.
70 pub is_normalized: Option<bool>,
71 /// Average monthly search volume.
72 pub search_volume: Option<i64>,
73 /// Search volume for each of the preceding months.
74 pub monthly_searches: Option<Vec<DataForSeoLabsMonthlySearch>>,
75}
76
77/// Clickstream-based keyword metrics.
78/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/>.
79#[derive(Debug, Default, Serialize, Deserialize, Clone)]
80pub struct DataForSeoLabsClickstreamKeywordInfo {
81 /// Search engine type (e.g. `"google"`).
82 pub se_type: Option<String>,
83 /// Timestamp when this data was last updated (UTC).
84 pub last_updated_time: Option<String>,
85 /// Average monthly search volume.
86 pub search_volume: Option<i64>,
87 /// Clickstream traffic split by gender.
88 pub gender_distribution: Option<DataForSeoLabsGenderDistribution>,
89 /// Clickstream traffic split by age bracket.
90 pub age_distribution: Option<DataForSeoLabsAgeDistribution>,
91 /// Search volume for each of the preceding months.
92 pub monthly_searches: Option<Vec<DataForSeoLabsMonthlySearch>>,
93}
94
95/// Structural properties of a keyword (difficulty, language, clustering).
96/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/>.
97#[derive(Debug, Default, Serialize, Deserialize, Clone)]
98pub struct DataForSeoLabsKeywordProperties {
99 /// Search engine type (e.g. `"google"`).
100 pub se_type: Option<String>,
101 /// Canonical keyword this keyword was clustered under.
102 pub core_keyword: Option<String>,
103 /// Algorithm used to cluster synonymous keywords.
104 pub synonym_clustering_algorithm: Option<String>,
105 /// Difficulty of ranking in the top 10, from 0 to 100.
106 pub keyword_difficulty: Option<i64>,
107 /// Language detected for the keyword.
108 pub detected_language: Option<String>,
109 /// Whether the keyword is in a language other than requested.
110 pub is_another_language: Option<bool>,
111 /// Number of words in the keyword.
112 pub words_count: Option<i64>,
113}
114
115/// Estimated Google Ads impression/click metrics for a keyword.
116/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/ranked_keywords/live/>.
117#[derive(Debug, Default, Serialize, Deserialize, Clone)]
118pub struct DataForSeoLabsImpressionsInfo {
119 /// Search engine type (e.g. `"google"`).
120 pub se_type: Option<String>,
121 /// Timestamp when this data was last updated (UTC).
122 pub last_updated_time: Option<String>,
123 /// Bid value the impression estimates are based on (USD).
124 pub bid: Option<f64>,
125 /// Keyword match type the estimates are based on.
126 pub match_type: Option<String>,
127 /// Minimum estimated ad position.
128 pub ad_position_min: Option<f64>,
129 /// Maximum estimated ad position.
130 pub ad_position_max: Option<f64>,
131 /// Average estimated ad position.
132 pub ad_position_average: Option<f64>,
133 /// Minimum estimated cost per click (USD).
134 pub cpc_min: Option<f64>,
135 /// Maximum estimated cost per click (USD).
136 pub cpc_max: Option<f64>,
137 /// Average estimated cost per click (USD).
138 pub cpc_average: Option<f64>,
139 /// Minimum estimated daily impressions.
140 pub daily_impressions_min: Option<f64>,
141 /// Maximum estimated daily impressions.
142 pub daily_impressions_max: Option<f64>,
143 /// Average estimated daily impressions.
144 pub daily_impressions_average: Option<f64>,
145 /// Minimum estimated daily clicks.
146 pub daily_clicks_min: Option<f64>,
147 /// Maximum estimated daily clicks.
148 pub daily_clicks_max: Option<f64>,
149 /// Average estimated daily clicks.
150 pub daily_clicks_average: Option<f64>,
151 /// Minimum estimated daily ad cost (USD).
152 pub daily_cost_min: Option<f64>,
153 /// Maximum estimated daily ad cost (USD).
154 pub daily_cost_max: Option<f64>,
155 /// Average estimated daily ad cost (USD).
156 pub daily_cost_average: Option<f64>,
157}
158
159/// Metadata about the SERP a keyword was last checked against.
160/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/>.
161#[derive(Debug, Default, Serialize, Deserialize, Clone)]
162pub struct DataForSeoLabsSerpInfo {
163 /// Search engine type (e.g. `"google"`).
164 pub se_type: Option<String>,
165 /// URL used to check the SERP.
166 pub check_url: Option<String>,
167 /// Types of SERP elements present in the results.
168 pub serp_item_types: Option<Vec<String>>,
169 /// Total number of results the search engine reported.
170 pub se_results_count: Option<i64>,
171 /// Timestamp when this data was last updated (UTC).
172 pub last_updated_time: Option<String>,
173 /// Timestamp of the previous data update (UTC).
174 pub previous_updated_time: Option<String>,
175}
176
177/// Average backlink metrics of the pages ranking for a keyword.
178/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/>.
179#[derive(Debug, Default, Serialize, Deserialize, Clone)]
180pub struct DataForSeoLabsAvgBacklinksInfo {
181 /// Search engine type (e.g. `"google"`).
182 pub se_type: Option<String>,
183 /// Average backlinks of the ranking pages.
184 pub backlinks: Option<f64>,
185 /// Average dofollow backlinks of the ranking pages.
186 pub dofollow: Option<f64>,
187 /// Average referring pages of the ranking pages.
188 pub referring_pages: Option<f64>,
189 /// Average referring domains of the ranking pages.
190 pub referring_domains: Option<f64>,
191 /// Average referring main domains of the ranking pages.
192 pub referring_main_domains: Option<f64>,
193 /// Average rank of the ranking pages.
194 pub rank: Option<f64>,
195 /// Average main-domain rank of the ranking pages.
196 pub main_domain_rank: Option<f64>,
197 /// Timestamp when this data was last updated (UTC).
198 pub last_updated_time: Option<String>,
199}
200
201/// Search intent classification attached to a keyword.
202/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/>.
203#[derive(Debug, Default, Serialize, Deserialize, Clone)]
204pub struct DataForSeoLabsSearchIntentInfo {
205 /// Search engine type (e.g. `"google"`).
206 pub se_type: Option<String>,
207 /// Dominant search intent of the keyword.
208 pub main_intent: Option<String>,
209 /// Additional detected search intents.
210 pub foreign_intent: Option<Vec<String>>,
211 /// Timestamp when this data was last updated (UTC).
212 pub last_updated_time: Option<String>,
213}
214
215/// Full set of metrics DataForSEO stores for a single keyword.
216///
217/// Used both as a standalone item (keyword_ideas, keyword_suggestions,
218/// keywords_for_site, keyword_overview, top_searches) and nested inside
219/// ranked/related keyword items.
220/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/keyword_ideas/live/>.
221#[derive(Debug, Default, Serialize, Deserialize, Clone)]
222pub struct DataForSeoLabsKeywordData {
223 /// Search engine type (e.g. `"google"`).
224 pub se_type: Option<String>,
225 /// Keyword the data relates to.
226 pub keyword: Option<String>,
227 /// Location code (e.g. `2840`); alternative to `location_name`.
228 pub location_code: Option<i32>,
229 /// Language code (e.g. `"en"`); alternative to `language_name`.
230 pub language_code: Option<String>,
231 /// Google Ads keyword metrics.
232 pub keyword_info: Option<DataForSeoLabsKeywordInfo>,
233 /// Search volume normalized with Bing data.
234 pub keyword_info_normalized_with_bing: Option<DataForSeoLabsKeywordInfoNormalized>,
235 /// Search volume normalized with clickstream data.
236 pub keyword_info_normalized_with_clickstream: Option<DataForSeoLabsKeywordInfoNormalized>,
237 /// Clickstream-based keyword metrics.
238 pub clickstream_keyword_info: Option<DataForSeoLabsClickstreamKeywordInfo>,
239 /// Structural properties of the keyword.
240 pub keyword_properties: Option<DataForSeoLabsKeywordProperties>,
241 /// Estimated Google Ads impression and click metrics.
242 pub impressions_info: Option<DataForSeoLabsImpressionsInfo>,
243 /// Metadata about the SERP the keyword was last checked against.
244 pub serp_info: Option<DataForSeoLabsSerpInfo>,
245 /// Average backlink metrics of the ranking pages.
246 pub avg_backlinks_info: Option<DataForSeoLabsAvgBacklinksInfo>,
247 /// Search-intent classification of the keyword.
248 pub search_intent_info: Option<DataForSeoLabsSearchIntentInfo>,
249}
250
251/// Clickstream gender split.
252#[derive(Debug, Default, Serialize, Deserialize, Clone)]
253pub struct DataForSeoLabsGenderDistribution {
254 /// Estimated share of female users.
255 pub female: Option<i64>,
256 /// Estimated share of male users.
257 pub male: Option<i64>,
258}
259
260/// Clickstream age split.
261#[derive(Debug, Default, Serialize, Deserialize, Clone)]
262pub struct DataForSeoLabsAgeDistribution {
263 /// Estimated traffic share for the 18-24 age bracket.
264 #[serde(rename = "18-24")]
265 pub age_18_24: Option<i64>,
266 /// Estimated traffic share for the 25-34 age bracket.
267 #[serde(rename = "25-34")]
268 pub age_25_34: Option<i64>,
269 /// Estimated traffic share for the 35-44 age bracket.
270 #[serde(rename = "35-44")]
271 pub age_35_44: Option<i64>,
272 /// Estimated traffic share for the 45-54 age bracket.
273 #[serde(rename = "45-54")]
274 pub age_45_54: Option<i64>,
275 /// Estimated traffic share for the 55-64 age bracket.
276 #[serde(rename = "55-64")]
277 pub age_55_64: Option<i64>,
278}
279
280/// Aggregated ranking metrics grouped by SERP feature type.
281/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/domain_rank_overview/live/>.
282#[derive(Debug, Default, Serialize, Deserialize, Clone)]
283pub struct DataForSeoLabsMetrics {
284 /// Metrics for organic search results.
285 pub organic: Option<DataForSeoLabsMetricsInfo>,
286 /// Metrics for paid search results.
287 pub paid: Option<DataForSeoLabsMetricsInfo>,
288 /// Metrics for featured snippet results.
289 pub featured_snippet: Option<DataForSeoLabsMetricsInfo>,
290 /// Metrics for local pack results.
291 pub local_pack: Option<DataForSeoLabsMetricsInfo>,
292}
293
294/// Ranking metrics for one SERP feature type (organic, paid, ...).
295/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/domain_rank_overview/live/>.
296#[derive(Debug, Default, Serialize, Deserialize, Clone)]
297pub struct DataForSeoLabsMetricsInfo {
298 /// Number of SERPs where the target ranks #1.
299 pub pos_1: Option<i64>,
300 /// Number of SERPs where the target ranks #2-3.
301 pub pos_2_3: Option<i64>,
302 /// Number of SERPs where the target ranks #4-10.
303 pub pos_4_10: Option<i64>,
304 /// Number of SERPs where the target ranks #11-20.
305 pub pos_11_20: Option<i64>,
306 /// Number of SERPs where the target ranks #21-30.
307 pub pos_21_30: Option<i64>,
308 /// Number of SERPs where the target ranks #31-40.
309 pub pos_31_40: Option<i64>,
310 /// Number of SERPs where the target ranks #41-50.
311 pub pos_41_50: Option<i64>,
312 /// Number of SERPs where the target ranks #51-60.
313 pub pos_51_60: Option<i64>,
314 /// Number of SERPs where the target ranks #61-70.
315 pub pos_61_70: Option<i64>,
316 /// Number of SERPs where the target ranks #71-80.
317 pub pos_71_80: Option<i64>,
318 /// Number of SERPs where the target ranks #81-90.
319 pub pos_81_90: Option<i64>,
320 /// Number of SERPs where the target ranks #91-100.
321 pub pos_91_100: Option<i64>,
322 /// Estimated monthly traffic volume (CTR times search volume across ranking keywords).
323 pub etv: Option<f64>,
324 /// Estimated traffic volume based on impressions.
325 pub impressions_etv: Option<f64>,
326 /// Number of SERPs containing the target for this feature type.
327 pub count: Option<i64>,
328 /// Estimated monthly cost (USD) to obtain this traffic via paid search.
329 pub estimated_paid_traffic_cost: Option<f64>,
330 /// Number of newly ranked elements.
331 pub is_new: Option<i64>,
332 /// Number of elements that improved in rank.
333 pub is_up: Option<i64>,
334 /// Number of elements that declined in rank.
335 pub is_down: Option<i64>,
336 /// Number of previously ranked elements no longer found.
337 pub is_lost: Option<i64>,
338 /// Estimated traffic volume derived from clickstream data.
339 pub clickstream_etv: Option<f64>,
340 /// Clickstream traffic split by gender.
341 pub clickstream_gender_distribution: Option<DataForSeoLabsGenderDistribution>,
342 /// Clickstream traffic split by age bracket.
343 pub clickstream_age_distribution: Option<DataForSeoLabsAgeDistribution>,
344}
345
346/// A ranked SERP position held by a target, wrapping the SERP item.
347/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/ranked_keywords/live/>.
348#[derive(Debug, Default, Serialize, Deserialize, Clone)]
349pub struct DataForSeoLabsRankedSerpElement {
350 /// Search engine type (e.g. `"google"`).
351 pub se_type: Option<String>,
352 /// The SERP element occupying this ranked position.
353 pub serp_item: Option<DataForSeoLabsSerpItem>,
354 /// URL used to check the SERP.
355 pub check_url: Option<String>,
356 /// Types of SERP elements present in the results.
357 pub serp_item_types: Option<Vec<String>>,
358 /// Total number of results the search engine reported.
359 pub se_results_count: Option<i64>,
360 /// Timestamp when this data was last updated (UTC).
361 pub last_updated_time: Option<String>,
362 /// Timestamp of the previous data update (UTC).
363 pub previous_updated_time: Option<String>,
364}
365
366/// A single SERP element (organic result, paid result, featured snippet, ...).
367/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/ranked_keywords/live/>.
368#[derive(Debug, Default, Serialize, Deserialize, Clone)]
369pub struct DataForSeoLabsSerpItem {
370 /// Search engine type (e.g. `"google"`).
371 pub se_type: Option<String>,
372 /// Type of SERP element (serialized as `type`).
373 #[serde(rename = "type")]
374 pub item_type: Option<String>,
375 /// Rank within elements of the same type.
376 pub rank_group: Option<i64>,
377 /// Absolute rank among all SERP elements.
378 pub rank_absolute: Option<i64>,
379 /// Placement within the SERP (e.g. `"left"` or `"right"`).
380 pub position: Option<String>,
381 /// XPath of the element in the SERP HTML.
382 pub xpath: Option<String>,
383 /// Domain of the result.
384 pub domain: Option<String>,
385 /// Title of the result.
386 pub title: Option<String>,
387 /// URL of the result (for an id-list entry, the endpoint the task was posted to).
388 pub url: Option<String>,
389 /// URL path relative to the domain.
390 pub relative_url: Option<String>,
391 /// Text snippet of the result.
392 pub description: Option<String>,
393 /// Estimated monthly traffic volume (CTR times search volume across ranking keywords).
394 pub etv: Option<f64>,
395 /// Estimated traffic volume based on impressions.
396 pub impressions_etv: Option<f64>,
397 /// Estimated monthly cost (USD) to obtain this traffic via paid search.
398 pub estimated_paid_traffic_cost: Option<f64>,
399 /// Estimated traffic volume derived from clickstream data.
400 pub clickstream_etv: Option<f64>,
401 /// How the element's rank changed since the previous check.
402 pub rank_changes: Option<DataForSeoLabsRankChanges>,
403 /// Backlink counters of the ranking page.
404 pub backlinks_info: Option<DataForSeoLabsSerpBacklinksInfo>,
405 /// Page and domain rank of the ranking page.
406 pub rank_info: Option<DataForSeoLabsRankInfo>,
407}
408
409/// Position movement of a SERP element between the last two checks.
410/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/ranked_keywords/live/>.
411#[derive(Debug, Default, Serialize, Deserialize, Clone)]
412pub struct DataForSeoLabsRankChanges {
413 /// Absolute rank at the previous check.
414 pub previous_rank_absolute: Option<i64>,
415 /// Whether the element is newly ranked.
416 pub is_new: Option<bool>,
417 /// Whether the element moved up in rank.
418 pub is_up: Option<bool>,
419 /// Whether the element moved down in rank.
420 pub is_down: Option<bool>,
421}
422
423/// Backlink counters of a ranking page.
424/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/ranked_keywords/live/>.
425#[derive(Debug, Default, Serialize, Deserialize, Clone)]
426pub struct DataForSeoLabsSerpBacklinksInfo {
427 /// Search engine type (e.g. `"google"`).
428 pub se_type: Option<String>,
429 /// Number of referring domains pointing to the page.
430 pub referring_domains: Option<i64>,
431 /// Number of referring main domains pointing to the page.
432 pub referring_main_domains: Option<i64>,
433 /// Number of referring pages pointing to the page.
434 pub referring_pages: Option<i64>,
435 /// Number of dofollow backlinks pointing to the page.
436 pub dofollow: Option<i64>,
437 /// Number of backlinks pointing to the page.
438 pub backlinks: Option<i64>,
439 /// Timestamp when the backlink data was updated (UTC).
440 pub time_update: Option<String>,
441}
442
443/// Page/domain rank of a ranking page.
444/// See <https://docs.dataforseo.com/v3/dataforseo_labs/google/ranked_keywords/live/>.
445#[derive(Debug, Default, Serialize, Deserialize, Clone)]
446pub struct DataForSeoLabsRankInfo {
447 /// Rank of the page, from 0 to 1000.
448 pub page_rank: Option<i64>,
449 /// Rank of the page's main domain, from 0 to 1000.
450 pub main_domain_rank: Option<i64>,
451}
452
453/// Common result wrapper shared by DataForSEO Labs endpoints.
454///
455/// Individual endpoints populate the relevant metadata fields (a target, a
456/// keyword, a seed keyword, ...) plus their `items` array. Fields that a
457/// given endpoint does not return stay `None`.
458/// See <https://docs.dataforseo.com/v3/dataforseo_labs/overview/>.
459#[derive(Debug, Default, Serialize, Deserialize, Clone)]
460pub struct DataForSeoLabsResult<T> {
461 /// Search engine type (e.g. `"google"`).
462 pub se_type: Option<String>,
463 /// Domain, subdomain, or webpage the request targets.
464 pub target: Option<String>,
465 /// First domain to compare.
466 pub target1: Option<String>,
467 /// Second domain to compare.
468 pub target2: Option<String>,
469 /// Store identifier of the app.
470 pub app_id: Option<String>,
471 /// App identifiers, keyed by an index string.
472 pub app_ids: Option<HashMap<String, String>>,
473 /// Keyword the data relates to.
474 pub keyword: Option<String>,
475 /// Seed keyword the results were expanded from.
476 pub seed_keyword: Option<String>,
477 /// Seed keywords the results were expanded from.
478 pub seed_keywords: Option<Vec<String>>,
479 /// Location code (e.g. `2840`); alternative to `location_name`.
480 pub location_code: Option<i32>,
481 /// Language code (e.g. `"en"`); alternative to `language_name`.
482 pub language_code: Option<String>,
483 /// Total number of matching results in the database.
484 pub total_count: Option<i64>,
485 /// Number of items returned in `items`.
486 pub items_count: Option<i64>,
487 /// Offset into the result set, for pagination.
488 pub offset: Option<i32>,
489 /// Token used to page beyond the standard offset limit.
490 pub offset_token: Option<String>,
491 /// Ranking and traffic metrics, grouped by SERP feature type.
492 pub metrics: Option<DataForSeoLabsMetrics>,
493 /// Absolute ranking and traffic metrics, grouped by SERP feature type.
494 pub metrics_absolute: Option<DataForSeoLabsMetrics>,
495 /// Result items.
496 pub items: Option<Vec<T>>,
497}
498
499impl<T> DataForSeoLabsResult<T> {
500 /// Items of this result (empty slice when the API returned none).
501 pub fn items(&self) -> &[T] {
502 self.items.as_deref().unwrap_or_default()
503 }
504}
505
506/// Raw JSON alias for endpoints whose item schema is not modeled in detail.
507pub type DataForSeoLabsRawItem = Value;