Skip to main content

data_for_seo/api/merchant/
google.rs

1use crate::api::merchant::MerchantApi;
2use crate::entity::{
3    MerchantApiGoogleProductInfo, MerchantApiGoogleProducts, MerchantApiGoogleReviews,
4    MerchantApiGoogleSellers, MerchantApiLocation, MerchantApiTaskReady, SerpApiLanguage,
5};
6use crate::{DataForSeoApiResponse, DataForSeoClient};
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9
10impl MerchantApi<'_> {
11    /// Access the Google Shopping Merchant API.
12    /// See <https://docs.dataforseo.com/v3/merchant/google/overview/>.
13    pub fn google(&self) -> MerchantApiGoogle<'_> {
14        MerchantApiGoogle {
15            client: self.client,
16        }
17    }
18}
19
20/// Google Shopping Merchant API (products, sellers, product_info, reviews).
21pub struct MerchantApiGoogle<'a> {
22    client: &'a DataForSeoClient,
23}
24
25impl MerchantApiGoogle<'_> {
26    /// <https://docs.dataforseo.com/v3/merchant/google/locations/>
27    pub async fn locations(&self) -> DataForSeoApiResponse<MerchantApiLocation> {
28        self.client.http_get("/v3/merchant/google/locations").await
29    }
30    /// <https://docs.dataforseo.com/v3/merchant/google/locations/>
31    pub async fn locations_country(
32        &self,
33        country: &str,
34    ) -> DataForSeoApiResponse<MerchantApiLocation> {
35        self.client
36            .http_get(format!("/v3/merchant/google/locations/{country}").as_str())
37            .await
38    }
39    /// <https://docs.dataforseo.com/v3/merchant/google/languages/>
40    pub async fn languages(&self) -> DataForSeoApiResponse<SerpApiLanguage> {
41        self.client.http_get("/v3/merchant/google/languages").await
42    }
43
44    /// <https://docs.dataforseo.com/v3/merchant/google/products/task_post/>
45    pub async fn products_task_post(
46        &self,
47        data: Vec<MerchantApiGoogleProductsPost>,
48    ) -> DataForSeoApiResponse<Value> {
49        self.client
50            .http_post("/v3/merchant/google/products/task_post", &data)
51            .await
52    }
53    /// <https://docs.dataforseo.com/v3/merchant/google/products/tasks_ready/>
54    pub async fn products_tasks_ready(&self) -> DataForSeoApiResponse<MerchantApiTaskReady> {
55        self.client
56            .http_get("/v3/merchant/google/products/tasks_ready")
57            .await
58    }
59    /// <https://docs.dataforseo.com/v3/merchant/google/products/task_get/advanced/>
60    pub async fn products_task_get_advanced(
61        &self,
62        id: &str,
63    ) -> DataForSeoApiResponse<MerchantApiGoogleProducts> {
64        self.client
65            .http_get(format!("/v3/merchant/google/products/task_get/advanced/{id}").as_str())
66            .await
67    }
68    /// <https://docs.dataforseo.com/v3/merchant/google/products/task_get/html/>
69    pub async fn products_task_get_html(&self, id: &str) -> DataForSeoApiResponse<Value> {
70        self.client
71            .http_get(format!("/v3/merchant/google/products/task_get/html/{id}").as_str())
72            .await
73    }
74
75    /// <https://docs.dataforseo.com/v3/merchant/google/sellers/task_post/>
76    pub async fn sellers_task_post(
77        &self,
78        data: Vec<MerchantApiGoogleSellersPost>,
79    ) -> DataForSeoApiResponse<Value> {
80        self.client
81            .http_post("/v3/merchant/google/sellers/task_post", &data)
82            .await
83    }
84    /// <https://docs.dataforseo.com/v3/merchant/google/sellers/tasks_ready/>
85    pub async fn sellers_tasks_ready(&self) -> DataForSeoApiResponse<MerchantApiTaskReady> {
86        self.client
87            .http_get("/v3/merchant/google/sellers/tasks_ready")
88            .await
89    }
90    /// <https://docs.dataforseo.com/v3/merchant/google/sellers/task_get/advanced/>
91    pub async fn sellers_task_get_advanced(
92        &self,
93        id: &str,
94    ) -> DataForSeoApiResponse<MerchantApiGoogleSellers> {
95        self.client
96            .http_get(format!("/v3/merchant/google/sellers/task_get/advanced/{id}").as_str())
97            .await
98    }
99    /// <https://docs.dataforseo.com/v3/merchant/google/sellers/ad_url/>
100    pub async fn sellers_ad_url(&self, id: &str) -> DataForSeoApiResponse<Value> {
101        self.client
102            .http_get(format!("/v3/merchant/google/sellers/ad_url/{id}").as_str())
103            .await
104    }
105
106    /// <https://docs.dataforseo.com/v3/merchant/google/product_info/task_post/>
107    pub async fn product_info_task_post(
108        &self,
109        data: Vec<MerchantApiGoogleProductInfoPost>,
110    ) -> DataForSeoApiResponse<Value> {
111        self.client
112            .http_post("/v3/merchant/google/product_info/task_post", &data)
113            .await
114    }
115    /// <https://docs.dataforseo.com/v3/merchant/google/product_info/tasks_ready/>
116    pub async fn product_info_tasks_ready(&self) -> DataForSeoApiResponse<MerchantApiTaskReady> {
117        self.client
118            .http_get("/v3/merchant/google/product_info/tasks_ready")
119            .await
120    }
121    /// <https://docs.dataforseo.com/v3/merchant/google/product_info/task_get/advanced/>
122    pub async fn product_info_task_get_advanced(
123        &self,
124        id: &str,
125    ) -> DataForSeoApiResponse<MerchantApiGoogleProductInfo> {
126        self.client
127            .http_get(format!("/v3/merchant/google/product_info/task_get/advanced/{id}").as_str())
128            .await
129    }
130
131    /// <https://docs.dataforseo.com/v3/merchant/google/reviews/task_post/>
132    pub async fn reviews_task_post(
133        &self,
134        data: Vec<MerchantApiGoogleReviewsPost>,
135    ) -> DataForSeoApiResponse<Value> {
136        self.client
137            .http_post("/v3/merchant/google/reviews/task_post", &data)
138            .await
139    }
140    /// <https://docs.dataforseo.com/v3/merchant/google/reviews/tasks_ready/>
141    pub async fn reviews_tasks_ready(&self) -> DataForSeoApiResponse<MerchantApiTaskReady> {
142        self.client
143            .http_get("/v3/merchant/google/reviews/tasks_ready")
144            .await
145    }
146    /// <https://docs.dataforseo.com/v3/merchant/google/reviews/task_get/advanced/>
147    pub async fn reviews_task_get_advanced(
148        &self,
149        id: &str,
150    ) -> DataForSeoApiResponse<MerchantApiGoogleReviews> {
151        self.client
152            .http_get(format!("/v3/merchant/google/reviews/task_get/advanced/{id}").as_str())
153            .await
154    }
155}
156
157/// Request payload for the Google Shopping products endpoints.
158/// See <https://docs.dataforseo.com/v3/merchant/google/products/task_post/>.
159#[derive(Debug, Default, Serialize, Deserialize, Clone)]
160pub struct MerchantApiGoogleProductsPost {
161    /// Search keyword (up to 700 characters, URL-decoded).
162    pub keyword: String,
163    /// Direct Google Shopping search URL to parse instead of building one from `keyword`.
164    #[serde(skip_serializing_if = "Option::is_none")]
165    pub url: Option<String>,
166    /// Task priority: `1` (normal, default) or `2` (high, extra charge).
167    #[serde(skip_serializing_if = "Option::is_none")]
168    pub priority: Option<i32>,
169    /// Full location name (e.g. `"London,England,United Kingdom"`).
170    #[serde(skip_serializing_if = "Option::is_none")]
171    pub location_name: Option<String>,
172    /// Location code; alternative to `location_name`.
173    #[serde(skip_serializing_if = "Option::is_none")]
174    pub location_code: Option<i32>,
175    /// GPS coordinates as `"latitude,longitude,radius"`.
176    #[serde(skip_serializing_if = "Option::is_none")]
177    pub location_coordinate: Option<String>,
178    /// Full language name (e.g. `"English"`).
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub language_name: Option<String>,
181    /// Language code (e.g. `en`); alternative to `language_name`.
182    #[serde(skip_serializing_if = "Option::is_none")]
183    pub language_code: Option<String>,
184    /// Custom Google domain (e.g. `google.co.uk`).
185    #[serde(skip_serializing_if = "Option::is_none")]
186    pub se_domain: Option<String>,
187    /// Number of results to retrieve (default `40`, max `120`).
188    #[serde(skip_serializing_if = "Option::is_none")]
189    pub depth: Option<i32>,
190    /// Maximum number of result pages to crawl (max `7`).
191    #[serde(skip_serializing_if = "Option::is_none")]
192    pub max_crawl_pages: Option<i32>,
193    /// Raw price/sorting URL parameters; mutually exclusive with `price_min`/`price_max`/`sort_by`.
194    #[serde(skip_serializing_if = "Option::is_none")]
195    pub search_param: Option<String>,
196    /// Minimum product price filter.
197    #[serde(skip_serializing_if = "Option::is_none")]
198    pub price_min: Option<i32>,
199    /// Maximum product price filter.
200    #[serde(skip_serializing_if = "Option::is_none")]
201    pub price_max: Option<i32>,
202    /// Sort order (`review_score`, `price_low_to_high`, or `price_high_to_low`).
203    #[serde(skip_serializing_if = "Option::is_none")]
204    pub sort_by: Option<String>,
205    /// User-defined task identifier (max 255 characters).
206    #[serde(skip_serializing_if = "Option::is_none")]
207    pub tag: Option<String>,
208    /// URL to receive the completed task via POST; requires `postback_data`.
209    #[serde(skip_serializing_if = "Option::is_none")]
210    pub postback_url: Option<String>,
211    /// Result type delivered to `postback_url` (`advanced` or `html`).
212    #[serde(skip_serializing_if = "Option::is_none")]
213    pub postback_data: Option<String>,
214    /// URL pinged with a GET request when the task completes.
215    #[serde(skip_serializing_if = "Option::is_none")]
216    pub pingback_url: Option<String>,
217}
218
219impl MerchantApiGoogleProductsPost {
220    /// Creates a request for the given search `keyword`.
221    pub fn new(keyword: &str) -> MerchantApiGoogleProductsPost {
222        MerchantApiGoogleProductsPost {
223            keyword: keyword.to_string(),
224            ..Default::default()
225        }
226    }
227}
228
229/// Request payload for the Google Shopping sellers endpoints.
230/// See <https://docs.dataforseo.com/v3/merchant/google/sellers/task_post/>.
231#[derive(Debug, Default, Serialize, Deserialize, Clone)]
232pub struct MerchantApiGoogleSellersPost {
233    /// Google Shopping product identifier (one of `product_id`/`data_docid`/`gid`).
234    #[serde(skip_serializing_if = "Option::is_none")]
235    pub product_id: Option<String>,
236    /// Unique identifier of the SERP data element.
237    #[serde(skip_serializing_if = "Option::is_none")]
238    pub data_docid: Option<String>,
239    /// Global product identifier on Google Shopping.
240    #[serde(skip_serializing_if = "Option::is_none")]
241    pub gid: Option<String>,
242    /// Product variant filter selecting a specific variation.
243    #[serde(skip_serializing_if = "Option::is_none")]
244    pub pvf: Option<String>,
245    /// Task priority: `1` (normal, default) or `2` (high, extra charge).
246    #[serde(skip_serializing_if = "Option::is_none")]
247    pub priority: Option<i32>,
248    /// Full location name (e.g. `"London,England,United Kingdom"`).
249    #[serde(skip_serializing_if = "Option::is_none")]
250    pub location_name: Option<String>,
251    /// Location code; alternative to `location_name`.
252    #[serde(skip_serializing_if = "Option::is_none")]
253    pub location_code: Option<i32>,
254    /// GPS coordinates as `"latitude,longitude,radius"`.
255    #[serde(skip_serializing_if = "Option::is_none")]
256    pub location_coordinate: Option<String>,
257    /// Full language name (e.g. `"English"`).
258    #[serde(skip_serializing_if = "Option::is_none")]
259    pub language_name: Option<String>,
260    /// Language code (e.g. `en`); alternative to `language_name`.
261    #[serde(skip_serializing_if = "Option::is_none")]
262    pub language_code: Option<String>,
263    /// Custom Google domain (e.g. `google.co.uk`).
264    #[serde(skip_serializing_if = "Option::is_none")]
265    pub se_domain: Option<String>,
266    /// Number of results to retrieve (default `10`, max `200`).
267    #[serde(skip_serializing_if = "Option::is_none")]
268    pub depth: Option<i32>,
269    /// Include "buy on Google" shops in the result (doubles the cost).
270    #[serde(skip_serializing_if = "Option::is_none")]
271    pub get_shops_on_google: Option<bool>,
272    /// Extra specification parameters carried over from the products endpoint.
273    #[serde(skip_serializing_if = "Option::is_none")]
274    pub additional_specifications: Option<Value>,
275    /// User-defined task identifier (max 255 characters).
276    #[serde(skip_serializing_if = "Option::is_none")]
277    pub tag: Option<String>,
278    /// URL to receive the completed task via POST; requires `postback_data`.
279    #[serde(skip_serializing_if = "Option::is_none")]
280    pub postback_url: Option<String>,
281    /// Result type delivered to `postback_url` (`advanced`).
282    #[serde(skip_serializing_if = "Option::is_none")]
283    pub postback_data: Option<String>,
284    /// URL pinged with a GET request when the task completes.
285    #[serde(skip_serializing_if = "Option::is_none")]
286    pub pingback_url: Option<String>,
287}
288
289impl MerchantApiGoogleSellersPost {
290    /// Creates a request for the given `product_id`.
291    pub fn new(product_id: &str) -> MerchantApiGoogleSellersPost {
292        MerchantApiGoogleSellersPost {
293            product_id: Some(product_id.to_string()),
294            ..Default::default()
295        }
296    }
297}
298
299/// Request payload for the Google Shopping product_info endpoints.
300/// See <https://docs.dataforseo.com/v3/merchant/google/product_info/task_post/>.
301#[derive(Debug, Default, Serialize, Deserialize, Clone)]
302pub struct MerchantApiGoogleProductInfoPost {
303    /// Google Shopping product identifier (one of `product_id`/`data_docid`/`gid`).
304    #[serde(skip_serializing_if = "Option::is_none")]
305    pub product_id: Option<String>,
306    /// Unique identifier of the SERP data element.
307    #[serde(skip_serializing_if = "Option::is_none")]
308    pub data_docid: Option<String>,
309    /// Global product identifier on Google Shopping.
310    #[serde(skip_serializing_if = "Option::is_none")]
311    pub gid: Option<String>,
312    /// Task priority: `1` (normal, default) or `2` (high, extra charge).
313    #[serde(skip_serializing_if = "Option::is_none")]
314    pub priority: Option<i32>,
315    /// Full location name (e.g. `"London,England,United Kingdom"`).
316    #[serde(skip_serializing_if = "Option::is_none")]
317    pub location_name: Option<String>,
318    /// Location code; alternative to `location_name`.
319    #[serde(skip_serializing_if = "Option::is_none")]
320    pub location_code: Option<i32>,
321    /// GPS coordinates as `"latitude,longitude,radius"`.
322    #[serde(skip_serializing_if = "Option::is_none")]
323    pub location_coordinate: Option<String>,
324    /// Full language name (e.g. `"English"`).
325    #[serde(skip_serializing_if = "Option::is_none")]
326    pub language_name: Option<String>,
327    /// Language code (e.g. `en`); alternative to `language_name`.
328    #[serde(skip_serializing_if = "Option::is_none")]
329    pub language_code: Option<String>,
330    /// Custom Google domain (e.g. `google.co.uk`).
331    #[serde(skip_serializing_if = "Option::is_none")]
332    pub se_domain: Option<String>,
333    /// User-defined task identifier (max 255 characters).
334    #[serde(skip_serializing_if = "Option::is_none")]
335    pub tag: Option<String>,
336    /// URL to receive the completed task via POST; requires `postback_data`.
337    #[serde(skip_serializing_if = "Option::is_none")]
338    pub postback_url: Option<String>,
339    /// Result type delivered to `postback_url` (`advanced`).
340    #[serde(skip_serializing_if = "Option::is_none")]
341    pub postback_data: Option<String>,
342    /// URL pinged with a GET request when the task completes.
343    #[serde(skip_serializing_if = "Option::is_none")]
344    pub pingback_url: Option<String>,
345}
346
347impl MerchantApiGoogleProductInfoPost {
348    /// Creates a request for the given `product_id`.
349    pub fn new(product_id: &str) -> MerchantApiGoogleProductInfoPost {
350        MerchantApiGoogleProductInfoPost {
351            product_id: Some(product_id.to_string()),
352            ..Default::default()
353        }
354    }
355}
356
357/// Request payload for the Google Shopping reviews endpoints.
358/// See <https://docs.dataforseo.com/v3/merchant/google/reviews/task_post/>.
359#[derive(Debug, Default, Serialize, Deserialize, Clone)]
360pub struct MerchantApiGoogleReviewsPost {
361    /// Global product identifier on Google Shopping (recommended primary identifier).
362    #[serde(skip_serializing_if = "Option::is_none")]
363    pub gid: Option<String>,
364    /// Google Shopping product identifier.
365    #[serde(skip_serializing_if = "Option::is_none")]
366    pub product_id: Option<String>,
367    /// Unique identifier of the SERP data element.
368    #[serde(skip_serializing_if = "Option::is_none")]
369    pub data_docid: Option<String>,
370    /// Task priority: `1` (normal, default) or `2` (high, extra charge).
371    #[serde(skip_serializing_if = "Option::is_none")]
372    pub priority: Option<i32>,
373    /// Full location name (e.g. `"London,England,United Kingdom"`).
374    #[serde(skip_serializing_if = "Option::is_none")]
375    pub location_name: Option<String>,
376    /// Location code; alternative to `location_name`.
377    #[serde(skip_serializing_if = "Option::is_none")]
378    pub location_code: Option<i32>,
379    /// GPS coordinates as `"latitude,longitude,radius"`.
380    #[serde(skip_serializing_if = "Option::is_none")]
381    pub location_coordinate: Option<String>,
382    /// Full language name (e.g. `"English"`).
383    #[serde(skip_serializing_if = "Option::is_none")]
384    pub language_name: Option<String>,
385    /// Language code (e.g. `en`); alternative to `language_name`.
386    #[serde(skip_serializing_if = "Option::is_none")]
387    pub language_code: Option<String>,
388    /// Custom Google domain (e.g. `google.co.uk`).
389    #[serde(skip_serializing_if = "Option::is_none")]
390    pub se_domain: Option<String>,
391    /// Number of reviews to parse (default `10`, max `8000`; use multiples of 10).
392    #[serde(skip_serializing_if = "Option::is_none")]
393    pub depth: Option<i32>,
394    /// User-defined task identifier (max 255 characters).
395    #[serde(skip_serializing_if = "Option::is_none")]
396    pub tag: Option<String>,
397    /// URL to receive the completed task via POST; requires `postback_data`.
398    #[serde(skip_serializing_if = "Option::is_none")]
399    pub postback_url: Option<String>,
400    /// Result type delivered to `postback_url` (`advanced`).
401    #[serde(skip_serializing_if = "Option::is_none")]
402    pub postback_data: Option<String>,
403    /// URL pinged with a GET request when the task completes.
404    #[serde(skip_serializing_if = "Option::is_none")]
405    pub pingback_url: Option<String>,
406}
407
408impl MerchantApiGoogleReviewsPost {
409    /// Creates a request for the given `gid` (global product identifier).
410    pub fn new(gid: &str) -> MerchantApiGoogleReviewsPost {
411        MerchantApiGoogleReviewsPost {
412            gid: Some(gid.to_string()),
413            ..Default::default()
414        }
415    }
416}