{"id":24866562,"url":"https://github.com/abromeit/gsc-api-client","last_synced_at":"2025-04-13T01:43:55.123Z","repository":{"id":275015180,"uuid":"924798997","full_name":"Abromeit/gsc-api-client","owner":"Abromeit","description":"A reasonably fast Google Search Console (GSC) API Class, written in PHP. Knows things so you don't have to.","archived":false,"fork":false,"pushed_at":"2025-02-16T19:12:38.000Z","size":305,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-13T01:43:47.928Z","etag":null,"topics":["api-client","api-consumer","batch","batch-processing","batch-request","batch-requests","class","generator-functions","google-search-console","google-search-console-api","google-webmaster-tools","gsc","memory-optimization","php","php8","seo","seo-api","technical-seo","webmaster-tools","yield"],"latest_commit_sha":null,"homepage":"https://github.com/Abromeit/gsc-api-client","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Abromeit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-30T17:10:28.000Z","updated_at":"2025-04-04T14:28:25.000Z","dependencies_parsed_at":"2025-01-30T18:28:48.752Z","dependency_job_id":"b1bafed8-1392-43ff-8a16-87c513565ebf","html_url":"https://github.com/Abromeit/gsc-api-client","commit_stats":null,"previous_names":["abromeit/gsc-api-client"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abromeit%2Fgsc-api-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abromeit%2Fgsc-api-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abromeit%2Fgsc-api-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abromeit%2Fgsc-api-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Abromeit","download_url":"https://codeload.github.com/Abromeit/gsc-api-client/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248654030,"owners_count":21140235,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-client","api-consumer","batch","batch-processing","batch-request","batch-requests","class","generator-functions","google-search-console","google-search-console-api","google-webmaster-tools","gsc","memory-optimization","php","php8","seo","seo-api","technical-seo","webmaster-tools","yield"],"created_at":"2025-02-01T01:42:37.678Z","updated_at":"2025-04-13T01:43:55.097Z","avatar_url":"https://github.com/Abromeit.png","language":"PHP","readme":"# GSC API Client - A PHP Class for Easy-Peasy Data Retrieval from Google Search Console\n\nA **PHP client** for the Google Search Console API that makes it easy to import search performance data programmatically into your application.\n\n## Table of Contents\n\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Usage Examples](#usage-examples)\n  - [Example Files](#example-files)\n  - [Initialize the Client](#initialize-the-client)\n  - [List Available Properties](#list-available-properties)\n  - [Select a Property](#select-a-property)\n  - [Set Date Range](#set-date-range)\n  - [Get Search Performance Data](#get-search-performance-data)\n  - [Configure Batch Processing](#configure-batch-processing)\n  - [Accessing Returned Keyword Data](#accessing-returned-keyword-data)\n  - [Accessing Returned URL Data](#accessing-returned-url-data)\n- [Return Values](#return-values)\n  - [Keyword Data Structure](#keyword-data-structure)\n  - [URL Data Structure](#url-data-structure)\n  - [Search Performance by URL Data Structure](#search-performance-by-url-data-structure)\n- [API Reference](#api-reference)\n- [Speed and Resource Requirements](#speed-and-resource-requirements)\n  - [Tested with Large-ish GSC Accounts](#tested-with-large-ish-gsc-accounts)\n    - [Test Results](#test-results)\n      - [Batch=1 (the long way round)](#batch1-the-long-way-round)\n      - [Batch=10 (getting somewhere)](#batch10-getting-somewhere)\n      - [Batch=1000 (now we're cooking)](#batch1000-now-were-cooking)\n      - [How to find a good BatchSize](#how-to-find-a-good-batchsize)\n  - [Real-World Performance Test](#real-world-performance-test)\n- [Google's Table Schema](#googles-table-schema)\n  - [Table `searchdata_site_impression`](#table-searchdata_site_impression)\n  - [Table `searchdata_url_impression`](#table-searchdata_url_impression)\n- [Additional Resources](#additional-resources)\n\n## Requirements\n\nNothing fancy here:\n\n- PHP 8.2+\n- Google Search Console API credentials\n- A GSC property that actually has some data in it\n\n## Installation\n\nThe GSC API Client is available as Composer package, which is most likely the easiest way to use this library.\n\nSo, to install it via Composer:\n\n```bash\ncomposer require abromeit/gsc-api-client:dev-main\n```\n\nBefore you can start pulling data, you'll need to:\n\n1. Set up a Google Cloud Project and enable the Search Console API\n2. Create credentials (we use service accounts)\n3. Download your JSON credentials file\n4. Give your service account email access to your GSC properties\n\n## Usage Examples\n\n### Example Files\n\nCheck out these ready-to-use examples in the `examples/` directory:\n\n- [`get-all-properties.php`](examples/get-all-properties.php) - List all GSC properties you have access to\n- [`get-top3-keywords-per-day.php`](examples/get-top3-keywords-per-day.php) - Get the top 3 keywords for each day\n- [`get-top3-urls-per-day.php`](examples/get-top3-urls-per-day.php) - Get the top 3 URLs for each day\n\n### Initialize the Client\n\n```php\nuse Abromeit\\GscApiClient\\GscApiClient;\nuse Google\\Client;\nuse Google\\Service\\SearchConsole;\n\n// Initialize with service account\n$googleClient = new Client();\n$googleClient-\u003esetAuthConfig('/path/to/service-account.json');\n$googleClient-\u003eaddScope(SearchConsole::WEBMASTERS_READONLY);\n\n$apiClient = new GscApiClient($googleClient);\n```\n\n### List Available Properties\n\nWant to see what properties you have access to? Easy:\n\n```php\n$properties = $apiClient-\u003egetProperties();\nforeach ($properties as $property) {\n    echo $property-\u003egetSiteUrl() . \"\\n\";\n    echo \"Permission Level: \" . $property-\u003egetPermissionLevel() . \"\\n\";\n}\n```\n\n### Select a Property\n\nPick your poison:\n\n```php\n// Using URL\n$apiClient-\u003esetProperty('https://example.com/');\n\n// Using domain property\n$apiClient-\u003esetProperty('sc-domain:example.com');\n```\n\n### Set Date Range\n\nNeed last week's data? Got you covered:\n\n```php\n// Last 7 days\n$startDate = (new DateTime('today'))-\u003esub(new DateInterval('P7D'));\n$endDate = new DateTime('today');\n$apiClient-\u003esetDates($startDate, $endDate);\n\n// Or if you need specific dates\n$apiClient-\u003esetDates(\n    new DateTime('2024-01-01'),\n    new DateTime('2024-01-31')\n);\n```\n\n### Get Search Performance Data\n\nAaand here's where the magic happens:\n\n```php\n// Get daily performance data\n$keywordData = $apiClient-\u003egetTopKeywordsByDay();\n\n// Get URL data (max 25k rows per request)\n$urlData = $apiClient-\u003egetTopUrlsByDay();\n\n// Want fewer rows? No problem\n$keywordData = $apiClient-\u003egetTopKeywordsByDay(100);\n$urlData = $apiClient-\u003egetTopUrlsByDay(10);\n\n// Get comprehensive search performance data\n$performanceData = $apiClient-\u003egetSearchPerformanceByUrl();\n\n// Filter by country (ISO-3166-1-Alpha-3, because apparently ISO codes weren't confusing enough)\n$apiClient-\u003esetCountry('USA');\n\n// Filter by device type (DESKTOP, MOBILE, TABLET)\n$apiClient-\u003esetDevice(\\Abromeit\\GscApiClient\\Enums\\GSCDeviceType::MOBILE);\n// or just\n$apiClient-\u003esetDevice('MOBILE');\n\n// Clear individual filters\n$apiClient-\u003esetCountry(null);\n$apiClient-\u003esetDevice(null);\n$apiClient-\u003esetSearchType(null);\n\n// Create custom dimension filters\n$queryFilter = $apiClient-\u003egetNewApiDimensionFilterGroup('query', 'foo bar'); // \"query = foo bar\"\n$queryFilter = $apiClient-\u003egetNewApiDimensionFilterGroup('query', 'foo bar', 'contains'); // \"query *= foo bar\"\n```\n\n### Configure Batch Processing\n\nSee https://developers.google.com/webmaster-tools/v1/how-tos/batch\n\n```php\n// Get current batch size\n$batchSize = $apiClient-\u003egetBatchSize();\n\n// Set number of requests to batch together (1-1000)\n// Pro tip: Set this BEFORE calling methods that hit the API \u003e.\u003c'\n$apiClient-\u003esetBatchSize(10);\n```\n\n### Accessing Returned Keyword Data\n\nHere's how to access returned GSC data:\n\n```php\n$keywordData = $apiClient-\u003egetTopKeywordsByDay();\n\nforeach ($keywordData as $row) {\n    echo \"Date: {$row['data_date']}\\n\";\n    echo \"Query: {$row['query']}\\n\";\n    echo \"Position: \".number_format($row['position'], 1).\"\\n\";\n    echo \"Clicks: {$row['clicks']}\\n\";\n    echo \"Impressions: {$row['impressions']}\\n\";\n    echo \"Sum Top Position: {$row['sum_top_position']}\\n\";\n}\n```\n\n### Accessing Returned URL Data\n\nSame assoc result array, but for URLs:\n\n```php\n$urlData = $apiClient-\u003egetTopUrlsByDay();\n\nforeach ($urlData as $row) {\n    echo \"Date: {$row['data_date']}\\n\";\n    echo \"URL: {$row['url']}\\n\";\n    echo \"Position: \".number_format($row['position'], 1).\"\\n\";\n    echo \"Clicks: {$row['clicks']}\\n\";\n    echo \"Impressions: {$row['impressions']}\\n\";\n    echo \"Sum Top Position: {$row['sum_top_position']}\\n\";\n}\n```\n\n## Return Values\n\nThe data structure matches Google's BigQuery schema (thanks Google for at least being consistent here). If you're curious about the details: https://support.google.com/webmasters/answer/12917991?hl=en\n\n### Keyword Data Structure\n\nHere's what you get for each keyword row:\n\n```php\n/* \u003cGenerator\u003e */\n    [\n        'data_date' =\u003e string,         // Format: YYYY-MM-DD\n        'site_url' =\u003e string,          // Property URL\n        'query' =\u003e string,             // Search query\n        'country' =\u003e ?string,          // Optional: ISO-3166-1-Alpha-3 country code\n        'device' =\u003e ?string,           // Optional: DESKTOP, MOBILE, or TABLET\n        'impressions' =\u003e int,          // Total impressions\n        'clicks' =\u003e int,               // Total clicks\n        'position' =\u003e float,           // Average 1-based position\n        'sum_top_position' =\u003e float    // Sum of (position-1)*impressions\n    ],\n    // etc.\n/* \u003c/Generator\u003e */\n```\n\n### URL Data Structure\n\nAnd here is how a result row looks like for URLs:\n\n```php\n/* \u003cGenerator\u003e */\n    [\n        'data_date' =\u003e string,         // Format: YYYY-MM-DD\n        'site_url' =\u003e string,          // Property URL\n        'url' =\u003e string,               // Page URL\n        'country' =\u003e ?string,          // Optional: ISO-3166-1-Alpha-3 country code\n        'device' =\u003e ?string,           // Optional: DESKTOP, MOBILE, or TABLET\n        'impressions' =\u003e int,          // Total impressions\n        'clicks' =\u003e int,               // Total clicks\n        'position' =\u003e float,           // Average 1-based position\n        'sum_top_position' =\u003e float    \n    ],\n    // etc.\n/* \u003c/Generator\u003e */\n```\n\n### Search Performance by URL Data Structure\n\nHere is the rather comprehensive result for the full \"Search Performance by URL\".\n\n```php\n/* \u003cGenerator\u003e */\n    [\n        'data_date' =\u003e string,         // Format: YYYY-MM-DD\n        'site_url' =\u003e string,          // Property URL\n        'url' =\u003e string,               // Page URL\n        'query' =\u003e string,             // Search query that led to the page\n        'country' =\u003e string,           // ISO-3166-1-Alpha-3 country code\n        'device' =\u003e string,            // DESKTOP, MOBILE, or TABLET\n        'impressions' =\u003e int,          // Total impressions\n        'clicks' =\u003e int,               // Total clicks\n        'position' =\u003e float,           // Average 1-based position\n        'sum_top_position' =\u003e float    \n    ],\n    // etc.\n/* \u003c/Generator\u003e */\n```\n\n## API Reference\n\nHere's everything you can do with the `GscApiClient` class. No magic, sadly ;)\n\n| Method Signature | Return Type | Description |\n|-----------------|-------------|-------------|\n| `__construct(Client $client)` | `void` | Initializes a new GSC API client instance |\n| `getBatchSize()` | `int` | Gets the current batch size setting |\n| `setBatchSize(int $batchSize)` | `self` | Sets number of requests to batch (1-1000) |\n| `getProperties()` | `WmxSite[]` | Gets all properties the user has access to |\n| `setProperty(string $siteUrl)` | `self` | Sets the property to work with |\n| `getProperty()` | `string \\| null` | Gets the currently set property URL |\n| `hasProperty()` | `bool` | Checks if a property is set |\n| `isDomainProperty([?string $siteUrl=null])` | `bool` | Checks if URL is a domain property |\n| `setStartDate(DateTimeInterface $date)` | `self` | Sets the start date |\n| `setEndDate(DateTimeInterface $date)` | `self` | Sets the end date |\n| `setDates(DateTimeInterface $startDate, DateTimeInterface $endDate)` | `self` | Sets both start and end dates |\n| `clearStartDate()` | `self` | Clears the start date |\n| `clearEndDate()` | `self` | Clears the end date |\n| `clearDates()` | `self` | Clears both dates |\n| `getStartDate()` | `DateTimeInterface \\| null` | Gets the start date |\n| `getEndDate()` | `DateTimeInterface \\| null` | Gets the end date |\n| `getDates()` | `array{start: DateTimeInterface \\| null, end: DateTimeInterface \\| null}` | Gets both dates |\n| `hasStartDate()` | `bool` | Checks if start date is set |\n| `hasEndDate()` | `bool` | Checks if end date is set |\n| `hasDates()` | `bool` | Checks if both dates are set |\n| `setCountry([?string $countryCode=null])` | `self` | Sets country using ISO-3166-1-Alpha-3 code |\n| `getCountry()` | `string \\| null` | Gets the current country |\n| `hasCountry()` | `bool` | Checks if a country filter is set |\n| `setDevice([DeviceType\\|string\\|null $deviceType=null])` | `self` | Sets device type |\n| `getDevice()` | `string \\| null` | Gets the current device type |\n| `hasDevice()` | `bool` | Checks if a device filter is set |\n| `setSearchType([?string $searchType=null])` | `self` | Sets search type (e.g., 'WEB', 'NEWS') |\n| `getSearchType()` | `string \\| null` | Gets the current search type |\n| `getNewApiDimensionFilterGroup(string $dimension, string $expression, [string $operator=\\'equals\\'])` | `ApiDimensionFilterGroup` | Creates a dimension filter group for custom filtering |\n| `getTopKeywordsByDay([?int $maxRowsPerDay=null])` | `Generator\u003carray{data_date: string, site_url: string, query: string, country: string \\| null, device: string \\| null, impressions: int, clicks: int, sum_top_position: float}\u003e` | Gets top keywords by day |\n| `getTopUrlsByDay([?int $maxRowsPerDay=null])` | `Generator\u003carray{data_date: string, site_url: string, url: string, country: string \\| null, device: string \\| null, impressions: int, clicks: int, sum_top_position: float}\u003e` | Gets top URLs by day |\n| `getSearchPerformanceByUrl()` | `Generator\u003carray{data_date: string, site_url: string, url: string, query: string, country: string, device: string, impressions: int, clicks: int, sum_top_position: float}\u003e` | Gets all available columns from `byPage` aggregated data sources |\n| `getRequestsPerSecond([int $seconds=1])` | `float` | Gets the current average API queries per second |\n| `getTotalRequests([int $seconds=60])` | `int` | Gets the total number of API queries made |\n\n## Speed and Resource Requirements\n\nWe've updated the GSC API Client to use a yield-style implementation because waiting for the entire dataset to load before processing is no fun. Here's what you get:\n\n- Data starts flowing as soon as it's available _(effectively **streaming** it)_\n- The BatchSize config option now allows us to choose of either speed or memory efficiency. _(I'd love to say \"and any point in between\", but in reality even small batch sizes can result in substantial HTTP response sizes. - which unsuprisingly affects the memory footprint our application has.)_\n\n### Tested with Large-ish GSC Accounts\n\nThese numbers are from a local dev machine running who-knows-what in the background - so take them with a grain of salt. But you'll see the pattern.\n\nWe grabbed 16 months of daily data using `getTopKeywordsByDay()`. This function uses the \"byProperty\" aggregation, which seemingly means you get the top 5k entries (keywords) per day. (This behavior is only … \"implicitly\" documented. You'll most likely find numbers around 25k+ rows in the documentation. These exist, just not here.)\n\nThe result is 499 days of data in 2,495,000 rows. Each row contains a keyword with its `impressions`, `clicks`, and `ctr` for a single day.\n\n\n#### Test Results\n\n\u003cins\u003e**NOTE: This data reflects a software version before the implementation of the ThrottlingMiddleware. Consequently, performance metrics may differ from the current version, which enforces API request limits.**\u003c/ins\u003e\n\n![Terminal-rendered bar graphs of the GSC API Client's memory consumption and execution duration for different batch sizes and PHP implementation variants. (See table below for textual representation.)](docs/performance-comparison-gsc-api-with-generator-functions.png)\n\n| Implementation | Batch Size | Peak Memory   | Runtime             |\n|----------------|------------|---------------|---------------------|\n| Array-style    | 1          | 1269 MB       | 307s (5.1m)         |\n| Yield-style    | 1          | 45 MB  (-96%) | 290s (4.8m)         |\n| Yield-style    | 5          | 86 MB         | 188s (3.1m)         |\n| Array-style    | 10         | 1329 MB       | 194s (3.2m)         |\n| Yield-style    | 10         | 145 MB (-89%) | 183s (3.1m)         |\n| Yield-style    | 15         | 205 MB        | 189s (3.2m) // sic! |\n| Array-style    | 1000       | 1917 MB       | 36s  (0.6m)         |\n| Yield-style    | 1000       | 639 MB (-67%) | 38s  (0.6m)         |\n\n##### Batch=1 (the long way round):\n\n- One HTTP request per day = 498 separate, sequential connections with handshakes, headers, waiting for the response from google, the whole deal\n- Array version: **1.2GB RAM**, 5.1min runtime _(congratulations, you now have time to check your unread emails)_\n- Yield version: \u003cins\u003e**45MB RAM**\u003c/ins\u003e, but same glacial speed _(because physics)_\n\n##### Batch=10 (getting somewhere):\n\n- Runtime drops to ~3.2min by bundling into ~50 requests\n- Memory stays manageable with yield (145MB)\n- Array version still hoarding RAM like it's mining crypto (1.3GB)\n\n##### Batch=1000 (now we're cooking):\n\n- 36-38 seconds runtime with just 1-2 connections total\n- Memory jumps to 1.9GB array / 639MB yield\n- If your server has the RAM, this is probably what you want, right?\n\n##### How to find a good BatchSize\n\nThe yield implementation keeps memory in check while matching speed. \nBut note that Google enforces a per-site quota of `20 requests per second` = `120 api calls per minute` (see [Google's QPS Quota](https://developers.google.com/webmaster-tools/limits?hl=en#qps-quota)). Higher batch sizes will make you feel good about some measured metrics, but they're lying to you - the API is just dropping your requests.\n\n**Stick to batch sizes below 20** unless you are fully aware of the implications, as exceeding the quota can lead to unnecessarily long runtimes. Which is the opposite of what you want.\n\n##### Real-World Performance Test\n\n\u003cins\u003e**NOTE: The following performance metrics reflect measurements taken with the \"current\" software version, which includes ThrottlingMiddleware for API request rate limiting. These results supersede the data shown above.**\u003c/ins\u003e\n\nHere is another test fetching 3 months of data using `getSearchPerformanceByUrl()` with various batch sizes. These are the results:\n\n| Batch Size | Total Rows | Peak Memory | Avg Memory | Runtime | Rows/Second | QPS |\n|------------|------------|-------------|------------|---------|-------------|-----|\n| 1          | 4,505,486  | 118.1 MB    | 85.4 MB    | 491.6s  | 9,165      | 0.37 |\n| 20         | 4,505,486  | 707.4 MB    | 539.4 MB   | 171.4s  | 26,283     | 1.07 |\n| 75         | 4,505,486  | 1,362.2 MB  | 1,017.3 MB | 150.3s  | 29,984     | 1.22 |\n| 175        | 4,505,486  | 3,386.8 MB  | 2,229.5 MB | 142.8s  | 31,547     | 1.29 |\n\n- 91 days of data (2024-11-06 to 2025-02-06)\n- ~49,510 rows per day (min: 48,860, max: 49,772) \n- Total data volume: 4.5M rows, ~1.2GB compressed JSON\n\n\n\n## Google's Table Schema\n\nThinking about GSC data can be a real head-scratcher sometimes. At every corner, certain information might be missing or needs to be interpreted in a specific way to arrive at meaningful results. Fortunately, it helps to look at how Google itself handles the same data. _Ooo-wee!_\n\nSo - if you export your GSC data to BigQuery, you will find the following situation in the tables.\n\n### Table `searchdata_site_impression`\n\nThis table contains data aggregated by property. The table contains the following fields:\n\n| Field                | Type    | Description                                                                                                                                                                                                 |\n|----------------------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| data_date            | string  | The day on which the data in this row was generated (Pacific Time).                                                                                                                                         |\n| site_url             | string  | URL of the property. For domain-level properties, this will be `sc-domain:property-name`. For URL-prefix properties, it will be the full URL of the property definition. Examples: `sc-domain:developers.google.com`, `https://developers.google.com/webmaster-tools/`. |\n| query                | string  | The user query. When `is_anonymized_query` is true, this will be a zero-length string.                                                                                                                      |\n| is_anonymized_query  | boolean | Rare queries (called anonymized queries) are marked with this bool. The query field will be null when it's true to protect the privacy of users making the query.                                           |\n| Country              | string  | Country from where the query was made, in ISO-3166-1-Alpha-3 format.                                                                                                                                       |\n| search_type          | string  | One of the following string values: `web`, `image`, `video`, `news`, `discover`, `googleNews`.                                                                                                             |\n| device               | string  | The device from which the query was made.                                                                                                                                                                   |\n| impressions          | integer | The number of impressions for this row.                                                                                                                                                                     |\n| clicks               | integer | The number of clicks for this row.                                                                                                                                                                          |\n| sum_top_position     | float   | The sum of (position-1) * impressions. Allows further aggregation of position data. |\n| position             | float   | The average 1-based position as reported directly by the GSC API. |\n\n### Table `searchdata_url_impression`\n\nThis table contains data aggregated by URL. The table contains the following fields:\n\n| Field                   | Type    | Description                                                                                                                                                                                                 |\n|-------------------------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| data_date               | string  | Same as above.                                                                                                                                                                                              |\n| site_url                | string  | Same as above.                                                                                                                                                                                              |\n| url                     | string  | The fully-qualified URL where the user eventually lands when they click the search result or Discover story.                                                                                               |\n| query                   | string  | Same as above.                                                                                                                                                                                              |\n| is_anonymized_query     | boolean | Same as above.                                                                                                                                                                                              |\n| is_anonymized_discover  | boolean | Whether the data row is under the Discover anonymization threshold. When under the threshold, some other fields (like URL and country) will be missing to protect user privacy.                             |\n| country                 | string  | Same as above.                                                                                                                                                                                              |\n| search_type             | string  | Same as above.                                                                                                                                                                                              |\n| device                  | string  | Same as above.                                                                                                                                                                                              |\n| is_[search_appearance_type] | boolean | There are several boolean fields used to indicate search appearance type, such as `is_amp_top_stories`, `is_job_listing`, and `is_job_details`. A field will be true if the row in question appears for the specific rich result. |\n| impressions             | integer | Same as above.                                                                                                                                                                                              |\n| clicks                  | integer | Same as above.                                                                                                                                                                                              |\n| sum_position            | float   | A zero-based number indicating the topmost position of this URL in the search results for the query. (Zero is the top position in the results.) To calculate average position (which is 1-based), calculate `SUM(sum_position)/SUM(impressions) + 1`. |\n\n## Additional Resources\n\nFor more details on topics discussed in this GSC API Client's Readme file, refer to the official documentation and guidelines provided by Google:\n\n- **Batch Requests:** [Google Search Console API Batch Requests](https://developers.google.com/webmaster-tools/v1/how-tos/batch?hl=en)\n- **API Request Limits:** [Google Search Console API Limits and Quotas](https://developers.google.com/webmaster-tools/limits?hl=en#qps-quota)\n- **Getting Started with the Search Console API:** [Quickstart - Search Console API](https://developers.google.com/webmaster-tools/v3/quickstart)\n- **Setting Up Service Accounts:** [Using Service Accounts](https://developers.google.com/identity/protocols/oauth2/service-account)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabromeit%2Fgsc-api-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabromeit%2Fgsc-api-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabromeit%2Fgsc-api-client/lists"}