google_search_console_api/lib.rs
1//! # Google Search Console API Client
2//!
3//! An unofficial Rust client library for the Google Search Console API.
4//!
5//! ## Features
6//!
7//! - **Search Analytics** - Query search performance data
8//! - **Sitemaps** - Manage sitemaps
9//! - **Sites** - Manage sites
10//! - **URL Inspection** - Inspect URLs for indexing status
11//! - **Mobile Friendly Test** - Test mobile friendliness
12//!
13//! ## Example
14//!
15//! ```rust,no_run
16//! use google_search_console_api::SearchConsoleApi;
17//! use google_search_console_api::search_analytics::query::SearchAnalyticsQueryRequest;
18//! use google_search_console_api::types::Dimension;
19//!
20//! #[tokio::main]
21//! async fn main() {
22//! let token = "your_oauth_token";
23//! let site_url = "https://example.com/";
24//!
25//! let request = SearchAnalyticsQueryRequest::builder("2024-01-01", "2024-01-31")
26//! .dimensions(vec![Dimension::Query, Dimension::Page])
27//! .row_limit(100)
28//! .build();
29//!
30//! let response = SearchConsoleApi::search_analytics()
31//! .query(token, site_url, request)
32//! .await;
33//! }
34//! ```
35
36mod error;
37mod http;
38
39pub mod mobile_friendly_test;
40pub mod search_analytics;
41pub mod sitemaps;
42pub mod sites;
43pub mod types;
44pub mod url_inspection;
45
46use serde::{Deserialize, Serialize};
47use serde_json::{json, Value};
48use urlencoding::encode;
49
50pub use error::*;
51
52use crate::http::HttpClient;
53use crate::mobile_friendly_test::{RequestMobileFriendlyTest, ResponseMobileFriendlyTest};
54use crate::search_analytics::query::{SearchAnalyticsQueryRequest, SearchAnalyticsQueryResponse};
55use crate::sitemaps::ResponseSitemapApiList;
56use crate::sites::{ResponseSiteApi, ResponseSiteListApi};
57use crate::url_inspection::{RequestUrlInspection, ResponseInspectionResult};
58
59/// Main entry point for the Google Search Console API.
60///
61/// Provides access to all API endpoints through method chaining.
62///
63/// # Example
64///
65/// ```rust,no_run
66/// use google_search_console_api::SearchConsoleApi;
67///
68/// # async fn example() {
69/// let sites = SearchConsoleApi::sites().list("token").await;
70/// # }
71/// ```
72pub struct SearchConsoleApi;
73
74impl SearchConsoleApi {
75 /// Access the Search Analytics API.
76 ///
77 /// Query search performance data including clicks, impressions, CTR, and position.
78 pub fn search_analytics() -> SearchAnalyticsApi {
79 SearchAnalyticsApi
80 }
81
82 /// Access the Sitemaps API.
83 ///
84 /// List, submit, and delete sitemaps for your sites.
85 pub fn sitemaps() -> SitemapsApi {
86 SitemapsApi
87 }
88
89 /// Access the Sites API.
90 ///
91 /// Add, remove, and list sites in your Search Console account.
92 pub fn sites() -> SitesApi {
93 SitesApi
94 }
95
96 /// Access the URL Inspection API.
97 ///
98 /// Inspect URLs for indexing status, crawl info, and more.
99 pub fn url_inspection() -> UrlInspectionApi {
100 UrlInspectionApi
101 }
102
103 /// Access the Mobile Friendly Test API.
104 ///
105 /// Test whether a page is mobile-friendly.
106 pub fn mobile_friendly_test() -> MobileFriendlyTestApi {
107 MobileFriendlyTestApi
108 }
109}
110
111/// Search Analytics API client.
112///
113/// Query search traffic data for your site.
114///
115/// # API Reference
116///
117/// <https://developers.google.com/webmaster-tools/v1/searchanalytics>
118#[derive(Default)]
119pub struct SearchAnalyticsApi;
120
121impl SearchAnalyticsApi {
122 /// Query search analytics data.
123 ///
124 /// # Arguments
125 ///
126 /// * `token` - OAuth2 access token
127 /// * `url` - Site URL (e.g., `https://example.com/`)
128 /// * `request` - Query parameters
129 ///
130 /// # Example
131 ///
132 /// ```rust,no_run
133 /// use google_search_console_api::SearchConsoleApi;
134 /// use google_search_console_api::search_analytics::query::SearchAnalyticsQueryRequest;
135 ///
136 /// # async fn example() {
137 /// let request = SearchAnalyticsQueryRequest::builder("2024-01-01", "2024-01-31")
138 /// .row_limit(100)
139 /// .build();
140 ///
141 /// let response = SearchConsoleApi::search_analytics()
142 /// .query("token", "https://example.com/", request)
143 /// .await;
144 /// # }
145 /// ```
146 pub async fn query(
147 &self,
148 token: &str,
149 url: &str,
150 request: SearchAnalyticsQueryRequest,
151 ) -> Result<SearchAnalyticsQueryResponse, GoogleApiError> {
152 HttpClient::post(
153 token,
154 &format!(
155 "https://www.googleapis.com/webmasters/v3/sites/{}/searchAnalytics/query",
156 encode(url)
157 ),
158 request,
159 )
160 .await
161 }
162}
163
164#[derive(Default, Debug, Serialize, Deserialize, Clone)]
165pub(crate) struct DummyRequest {}
166
167/// Sitemaps API client.
168///
169/// Manage sitemaps for your sites.
170///
171/// # API Reference
172///
173/// <https://developers.google.com/webmaster-tools/v1/sitemaps>
174#[derive(Default)]
175pub struct SitemapsApi;
176
177impl SitemapsApi {
178 /// Delete a sitemap.
179 ///
180 /// # Arguments
181 ///
182 /// * `token` - OAuth2 access token
183 /// * `site_url` - Site URL
184 /// * `feed_path` - Full URL of the sitemap to delete
185 pub async fn delete(
186 &self,
187 token: &str,
188 site_url: &str,
189 feed_path: &str,
190 ) -> Result<Value, GoogleApiError> {
191 HttpClient::delete(
192 token,
193 &format!(
194 "https://www.googleapis.com/webmasters/v3/sites/{}/sitemaps/{}",
195 encode(site_url),
196 encode(feed_path)
197 ),
198 json!({}),
199 )
200 .await
201 }
202
203 /// Get information about a specific sitemap.
204 ///
205 /// # Arguments
206 ///
207 /// * `token` - OAuth2 access token
208 /// * `site_url` - Site URL
209 /// * `feed` - Full URL of the sitemap
210 pub async fn get(
211 &self,
212 token: &str,
213 site_url: &str,
214 feed: &str,
215 ) -> Result<Value, GoogleApiError> {
216 HttpClient::get(
217 token,
218 &format!(
219 "https://www.googleapis.com/webmasters/v3/sites/{}/sitemaps/{}",
220 encode(site_url),
221 encode(feed)
222 ),
223 json!({}),
224 )
225 .await
226 }
227
228 /// List all sitemaps for a site.
229 ///
230 /// # Arguments
231 ///
232 /// * `token` - OAuth2 access token
233 /// * `site_url` - Site URL
234 pub async fn list(
235 &self,
236 token: &str,
237 site_url: &str,
238 ) -> Result<ResponseSitemapApiList, GoogleApiError> {
239 HttpClient::get(
240 token,
241 &format!(
242 "https://www.googleapis.com/webmasters/v3/sites/{}/sitemaps",
243 encode(site_url)
244 ),
245 DummyRequest::default(),
246 )
247 .await
248 }
249
250 /// Resubmit a sitemap.
251 ///
252 /// # Arguments
253 ///
254 /// * `token` - OAuth2 access token
255 /// * `site_url` - Site URL
256 /// * `feed` - Full URL of the sitemap
257 pub async fn put(
258 &self,
259 token: &str,
260 site_url: &str,
261 feed: &str,
262 ) -> Result<Value, GoogleApiError> {
263 HttpClient::post(
264 token,
265 &format!(
266 "https://www.googleapis.com/webmasters/v3/sites/{}/sitemaps/{}",
267 encode(site_url),
268 encode(feed)
269 ),
270 json!({}),
271 )
272 .await
273 }
274
275 /// Submit a new sitemap.
276 ///
277 /// # Arguments
278 ///
279 /// * `token` - OAuth2 access token
280 /// * `site_url` - Site URL
281 /// * `feed` - Full URL of the sitemap to submit
282 pub async fn submit(
283 &self,
284 token: &str,
285 site_url: &str,
286 feed: &str,
287 ) -> Result<Value, GoogleApiError> {
288 HttpClient::put(
289 token,
290 &format!(
291 "https://www.googleapis.com/webmasters/v3/sites/{}/sitemaps/{}",
292 encode(site_url),
293 encode(feed)
294 ),
295 json!({}),
296 )
297 .await
298 }
299}
300
301/// Sites API client.
302///
303/// Manage sites in your Search Console account.
304///
305/// # API Reference
306///
307/// <https://developers.google.com/webmaster-tools/v1/sites>
308#[derive(Default)]
309pub struct SitesApi;
310
311impl SitesApi {
312 /// Add a site to Search Console.
313 ///
314 /// # Arguments
315 ///
316 /// * `token` - OAuth2 access token
317 /// * `site_url` - URL of the site to add
318 pub async fn add(&self, token: &str, site_url: &str) -> Result<Value, GoogleApiError> {
319 HttpClient::put(
320 token,
321 &format!(
322 "https://www.googleapis.com/webmasters/v3/sites/{}",
323 encode(site_url)
324 ),
325 DummyRequest::default(),
326 )
327 .await
328 }
329
330 /// Remove a site from Search Console.
331 ///
332 /// # Arguments
333 ///
334 /// * `token` - OAuth2 access token
335 /// * `site_url` - URL of the site to remove
336 pub async fn delete(&self, token: &str, site_url: &str) -> Result<Value, GoogleApiError> {
337 HttpClient::delete(
338 token,
339 &format!(
340 "https://www.googleapis.com/webmasters/v3/sites/{}",
341 encode(site_url)
342 ),
343 DummyRequest::default(),
344 )
345 .await
346 }
347
348 /// Get information about a specific site.
349 ///
350 /// # Arguments
351 ///
352 /// * `token` - OAuth2 access token
353 /// * `site_url` - URL of the site
354 pub async fn get(
355 &self,
356 token: &str,
357 site_url: &str,
358 ) -> Result<ResponseSiteApi, GoogleApiError> {
359 HttpClient::get(
360 token,
361 &format!(
362 "https://www.googleapis.com/webmasters/v3/sites/{}",
363 encode(site_url)
364 ),
365 DummyRequest::default(),
366 )
367 .await
368 }
369
370 /// List all sites in your Search Console account.
371 ///
372 /// # Arguments
373 ///
374 /// * `token` - OAuth2 access token
375 pub async fn list(&self, token: &str) -> Result<ResponseSiteListApi, GoogleApiError> {
376 HttpClient::get(
377 token,
378 "https://www.googleapis.com/webmasters/v3/sites",
379 DummyRequest::default(),
380 )
381 .await
382 }
383}
384
385/// URL Inspection API client.
386///
387/// Inspect URLs for indexing status and other information.
388///
389/// # API Reference
390///
391/// <https://developers.google.com/webmaster-tools/v1/urlInspection.index>
392#[derive(Default)]
393pub struct UrlInspectionApi;
394
395impl UrlInspectionApi {
396 /// Inspect a URL.
397 ///
398 /// Returns indexing status, crawl info, AMP status, mobile usability, and rich results.
399 ///
400 /// # Arguments
401 ///
402 /// * `token` - OAuth2 access token
403 /// * `request` - Inspection request parameters
404 pub async fn inspect(
405 &self,
406 token: &str,
407 request: &RequestUrlInspection,
408 ) -> Result<ResponseInspectionResult, GoogleApiError> {
409 HttpClient::post(
410 token,
411 "https://searchconsole.googleapis.com/v1/urlInspection/index:inspect",
412 request,
413 )
414 .await
415 }
416}
417
418/// Mobile Friendly Test API client.
419///
420/// Test whether a page is mobile-friendly.
421///
422/// # API Reference
423///
424/// <https://developers.google.com/webmaster-tools/v1/urlTestingTools.mobileFriendlyTest>
425#[derive(Default)]
426pub struct MobileFriendlyTestApi;
427
428impl MobileFriendlyTestApi {
429 /// Run a mobile-friendly test.
430 ///
431 /// Note: This API uses an API key instead of OAuth2.
432 ///
433 /// # Arguments
434 ///
435 /// * `api_key` - Google API key
436 /// * `request` - Test request parameters
437 pub async fn run(
438 &self,
439 api_key: &str,
440 request: &RequestMobileFriendlyTest,
441 ) -> Result<ResponseMobileFriendlyTest, GoogleApiError> {
442 HttpClient::post(
443 "",
444 &format!(
445 "https://searchconsole.googleapis.com/v1/urlTestingTools/mobileFriendlyTest:run?key={}",
446 api_key
447 ),
448 request,
449 )
450 .await
451 }
452}