{"id":651669,"date":"2025-01-31T10:20:19","date_gmt":"2025-01-31T07:20:19","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/"},"modified":"2025-01-31T10:20:19","modified_gmt":"2025-01-31T07:20:19","slug":"automate-seo-analysis-with-google-sheets-gsc-chatgpt-api","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/","title":{"rendered":"#Automate SEO analysis with Google Sheets, GSC &#038; ChatGPT API"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a2df2fb87cce\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a2df2fb87cce\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/#Automate_site_audits_analyze_pages_and_generate_AI-driven_optimization_insights_all_within_Google_Sheets\" >Automate site audits, analyze pages and generate AI-driven optimization insights all within Google Sheets.<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/#What_SEO_analysis_are_we_automating\" >What SEO analysis are we automating?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/#8_steps_to_set_up_your_own_GSC_custom_tool_script\" >8 steps to set up your own GSC custom tool + script<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/#Step_1_Create_the_Google_Sheet_for_your_tool\" >Step 1: Create the Google Sheet for your tool<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/#Step_2_Populate_your_sheet\" >Step 2: Populate your sheet<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/#Step_3_Create_a_Google_Cloud_project\" >Step 3: Create a Google Cloud project<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/#Step_4_Create_an_App_Script\" >Step 4: Create an App Script<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/#Step_5_Add_access_credentials\" >Step 5: Add access credentials<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/#Step_6_Change_to_a_Google_Cloud_project_for_GSC_data\" >Step 6: Change to a Google Cloud project for GSC data<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/#Step_7_Name_your_Google_Apps_Script\" >Step 7: Name your Google Apps Script<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/#Step_8_Edit_the_manifest_file\" >Step 8: Edit the manifest file<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/buradabiliyorum.com\/en\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api\/#Putting_our_Sheets_GSC_and_ChatGPT_tool_together\" >Putting our Sheets, GSC and ChatGPT tool together<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"subhead\" itemprop=\"alternativeHeadline\"><span class=\"ez-toc-section\" id=\"Automate_site_audits_analyze_pages_and_generate_AI-driven_optimization_insights_all_within_Google_Sheets\"><\/span>Automate site audits, analyze pages and generate AI-driven optimization insights all within Google Sheets.<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><\/p>\n<div class=\"bialty-container\">\n<p>SEO analysis can be time-consuming, but automating the process helps eliminate repetitive tasks and speeds up important website optimizations.\u00a0<\/p>\n<p>This guide will show you how to build a custom tool using Google Sheets, Google Search Console (GSC), and the ChatGPT API to streamline SEO audits and gain AI-powered insights.<\/p>\n<p>With this tool, you\u2019ll be able to:<\/p>\n<ul class=\"wp-block-list\">\n<li>Automate GSC data retrieval for faster analysis.<\/li>\n<li>Use AI to generate actionable SEO recommendations.<\/li>\n<\/ul>\n<p>The plan? You\u2019ll select a URL from a GSC-connected domain, enter your ChatGPT API key, inspect the page, and run an AI-driven analysis \u2013 all within Google Sheets.<\/p>\n<h2 class=\"wp-block-heading\" id=\"h-what-seo-analysis-are-we-automating\"><span class=\"ez-toc-section\" id=\"What_SEO_analysis_are_we_automating\"><\/span>What SEO analysis are we automating?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Once set up, this tool will allow you to quickly access key SEO data from GSC, including keyword rankings, referring URLs, last crawl date, and indexing status in robots.txt.<\/p>\n<p>ChatGPT enhances the process by analyzing and providing recommendations for:<\/p>\n<ul class=\"wp-block-list\">\n<li>Title tags.<\/li>\n<li>Meta de<a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">script<\/a>ions.<\/li>\n<li>Heading tags.<\/li>\n<li>Content.<\/li>\n<li>Keyword placement.<\/li>\n<li>Internal linking.<\/li>\n<li>Mobile optimization.<\/li>\n<li>Local SEO.<\/li>\n<li>Schema markup.<\/li>\n<\/ul>\n<p>While this script won\u2019t cover everything, it delivers detailed page insights in seconds, saving you hours of manual work.\u00a0<\/p>\n<p>You can then review the recommendations and decide which optimizations to implement.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1556\" height=\"784\" alt=\"Sample SEO analysis automation with Google Sheets\" class=\"wp-image-451310\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets.png.webp 1556w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets-600x302.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets-800x403.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets-200x101.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets-768x387.png.webp 768w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets-1536x774.png 1536w\" data-lazy-sizes=\"(max-width: 1556px) 100vw, 1556px\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets.png.webp\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1556\" height=\"784\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets.png.webp\" alt=\"Sample SEO analysis automation with Google Sheets\" class=\"wp-image-451310\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets.png.webp 1556w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets-600x302.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets-800x403.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets-200x101.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets-768x387.png.webp 768w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Sample-SEO-analysis-automation-with-Google-Sheets-1536x774.png 1536w\" sizes=\"(max-width: 1556px) 100vw, 1556px\"><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\" id=\"h-8-steps-to-set-up-your-own-gsc-custom-tool-script\"><span class=\"ez-toc-section\" id=\"8_steps_to_set_up_your_own_GSC_custom_tool_script\"><\/span>8 steps to set up your own GSC custom tool + script<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Setting up your script may initially feel overwhelming, but follow each step carefully and copy the script to ensure everything works.\u00a0<\/p>\n<p>You\u2019ll need a few things to get started:<\/p>\n<ul class=\"wp-block-list\">\n<li><a rel=\"nofollow\" target=\"_blank\" href=\"https:\/\/openai.com\/api\/\" target=\"_blank\" rel=\"noopener\">ChatGPT API key<\/a><strong>.<\/strong><\/li>\n<li><a rel=\"nofollow\" target=\"_blank\" href=\"https:\/\/drive.google.com\/\" target=\"_blank\" rel=\"noopener\">Google Sheets<\/a>.<\/li>\n<li><a rel=\"nofollow\" target=\"_blank\" href=\"https:\/\/search.google.com\/search-console\/\" target=\"_blank\" rel=\"noopener\">Google Search Console<\/a> (with linked properties).<\/li>\n<li><a rel=\"nofollow\" target=\"_blank\" href=\"https:\/\/console.cloud.google.com\/?pli=1\" target=\"_blank\" rel=\"noopener\">Google Cloud Console<\/a> data project.<\/li>\n<\/ul>\n<p>Next, I\u2019ll guide you through my eight-step process to get this \u201ctool\u201d up and running.<\/p>\n<h3 class=\"wp-block-heading\" id=\"h-step-1-create-the-google-sheet-for-your-tool\"><span class=\"ez-toc-section\" id=\"Step_1_Create_the_Google_Sheet_for_your_tool\"><\/span>Step 1: Create the Google Sheet for your tool<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>If you have a Google account, this is as simple as following these steps:<\/p>\n<ul class=\"wp-block-list\">\n<li>Open Google Drive.<\/li>\n<li>Go to the folder where you want to place your tool.<\/li>\n<li>Right-click<strong> <\/strong>on the background.<\/li>\n<li>Choose<strong> <\/strong><em>Google Sheets &gt; Blank spreadsheet<\/em>.<\/li>\n<\/ul>\n<p>You can rename the Sheet to anything you like, but I chose the following: GSC Custom Tool.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"902\" height=\"222\" alt=\"GSC Custom Tool - Google Sheets\" class=\"wp-image-451311\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets.png.webp 902w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-600x148.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-800x197.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-200x49.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-768x189.png.webp 768w\" data-lazy-sizes=\"(max-width: 902px) 100vw, 902px\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets.png.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"902\" height=\"222\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets.png.webp\" alt=\"GSC Custom Tool - Google Sheets\" class=\"wp-image-451311\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets.png.webp 902w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-600x148.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-800x197.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-200x49.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-768x189.png.webp 768w\" sizes=\"auto, (max-width: 902px) 100vw, 902px\"><\/figure>\n<\/div>\n<h3 class=\"wp-block-heading\" id=\"h-step-2-populate-your-sheet\"><span class=\"ez-toc-section\" id=\"Step_2_Populate_your_sheet\"><\/span>Step 2: Populate your sheet<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Populate the sheet by following these steps carefully:<\/p>\n<ul class=\"wp-block-list\">\n<li>Add the words \u201cSelect GSC property\u201d to <code>A1<\/code>.<\/li>\n<li>Add the words \u201cSelect a URL\u201d to <code>A2<\/code>.<\/li>\n<\/ul>\n<p>Move to <code>A15<\/code> and add \u201cInspection Results.\u201d Underneath this, in order from <code>A15<\/code> to <code>A25<\/code>, add the following:<\/p>\n<ul class=\"wp-block-list\">\n<li>URL:<\/li>\n<li>Coverage:<\/li>\n<li>Robots.txt:<\/li>\n<li>Indexing State:<\/li>\n<li>Last Crawled:<\/li>\n<li>Google Canonical:<\/li>\n<li>User Canonical:<\/li>\n<li>Mobile Usability:<\/li>\n<li>Rich Results Eligibility:<\/li>\n<li>Referring URLs:<\/li>\n<\/ul>\n<p>In <code>D1<\/code>, you\u2019ll paste your ChatGPT API<strong> <\/strong>key. If you don\u2019t have this key, please go to the link above and be sure to get one for this tool to work.<\/p>\n<p>Add \u201cAI Analysis Result\u201d to <code>F1<\/code> and \u201cPrompt Sent to ChatGPT\u201d to <code>G1<\/code>.<\/p>\n<p>Now, we need to merge a few rows in both of these columns. You\u2019ll merge <code>F2<\/code> \u2013 <code>F30<\/code> and <code>G2<\/code> \u2013 <code>G30<\/code> separately, by following these steps:<\/p>\n<ul class=\"wp-block-list\">\n<li>Select the rows to merge.<\/li>\n<li>Go to <em>Format &gt; Merge cells &gt; Merge vertically<\/em>.<\/li>\n<\/ul>\n<p>Repeat this step for the F and G rows you need to merge.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"917\" height=\"540\" alt=\"GSC Custom Tool - Google Sheets - Merging cells\" class=\"wp-image-451312\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Merging-cells.png.webp 917w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Merging-cells-574x338.png.webp 574w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Merging-cells-800x471.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Merging-cells-192x113.png.webp 192w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Merging-cells-768x452.png.webp 768w\" data-lazy-sizes=\"(max-width: 917px) 100vw, 917px\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Merging-cells.png.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"917\" height=\"540\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Merging-cells.png.webp\" alt=\"GSC Custom Tool - Google Sheets - Merging cells\" class=\"wp-image-451312\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Merging-cells.png.webp 917w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Merging-cells-574x338.png.webp 574w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Merging-cells-800x471.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Merging-cells-192x113.png.webp 192w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Merging-cells-768x452.png.webp 768w\" sizes=\"auto, (max-width: 917px) 100vw, 917px\"><\/figure>\n<\/div>\n<h3 class=\"wp-block-heading\" id=\"h-step-3-create-a-google-cloud-project\"><span class=\"ez-toc-section\" id=\"Step_3_Create_a_Google_Cloud_project\"><\/span>Step 3: Create a Google Cloud project<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Create a <a rel=\"nofollow\" target=\"_blank\" href=\"https:\/\/console.cloud.google.com\/welcome\/new?inv=1&amp;invt=AboJ5w\" target=\"_blank\" rel=\"noopener\">Google Cloud Console data project<\/a> for the tool.\u00a0<\/p>\n<p>Once set up, create a new project named \u201cGSC Custom Tool.\u201d<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"878\" height=\"433\" alt=\"Google Cloud project - GSC Custom Tool\" class=\"wp-image-451313\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool.png.webp 878w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-600x296.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-800x395.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-200x99.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-768x379.png.webp 768w\" data-lazy-sizes=\"(max-width: 878px) 100vw, 878px\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool.png.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"878\" height=\"433\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool.png.webp\" alt=\"Google Cloud project - GSC Custom Tool\" class=\"wp-image-451313\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool.png.webp 878w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-600x296.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-800x395.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-200x99.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-768x379.png.webp 768w\" sizes=\"auto, (max-width: 878px) 100vw, 878px\"><\/figure>\n<\/div>\n<p>You can do this by going to <em>Select Project &gt; New Project<\/em> and filling in the information just like in the screenshot above.\u00a0<\/p>\n<p>Click <em>Create<\/em> when you\u2019re done naming the project.<\/p>\n<p>Now, let\u2019s connect the Google Search Console API to your project.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"887\" height=\"659\" alt=\"Google Cloud project - GSC API\" class=\"wp-image-451314\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-API.png.webp 887w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-API-455x338.png.webp 455w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-API-800x594.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-API-152x113.png.webp 152w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-API-768x571.png.webp 768w\" data-lazy-sizes=\"(max-width: 887px) 100vw, 887px\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-API.png.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"887\" height=\"659\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-API.png.webp\" alt=\"Google Cloud project - GSC API\" class=\"wp-image-451314\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-API.png.webp 887w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-API-455x338.png.webp 455w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-API-800x594.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-API-152x113.png.webp 152w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-API-768x571.png.webp 768w\" sizes=\"auto, (max-width: 887px) 100vw, 887px\"><\/figure>\n<\/div>\n<p>Go to the search bar and type \u201cGoogle Search Console API,\u201d select it, and then hit <em>Enable<\/em> on the next screen.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"876\" height=\"297\" alt=\"Google Cloud project - Enabling GSC API\" class=\"wp-image-451315\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Enabling-GSC-API.png.webp 876w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Enabling-GSC-API-600x203.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Enabling-GSC-API-800x271.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Enabling-GSC-API-200x68.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Enabling-GSC-API-768x260.png.webp 768w\" data-lazy-sizes=\"(max-width: 876px) 100vw, 876px\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Enabling-GSC-API.png.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"876\" height=\"297\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Enabling-GSC-API.png.webp\" alt=\"Google Cloud project - Enabling GSC API\" class=\"wp-image-451315\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Enabling-GSC-API.png.webp 876w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Enabling-GSC-API-600x203.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Enabling-GSC-API-800x271.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Enabling-GSC-API-200x68.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Enabling-GSC-API-768x260.png.webp 768w\" sizes=\"auto, (max-width: 876px) 100vw, 876px\"><\/figure>\n<\/div>\n<p>We still have a lot to do and will revisit this project shortly.<\/p>\n<h3 class=\"wp-block-heading\" id=\"h-step-4-create-an-app-script\"><span class=\"ez-toc-section\" id=\"Step_4_Create_an_App_Script\"><\/span>Step 4: Create an App Script<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Integrate Apps Script into your newly created Google Sheets file.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"773\" height=\"307\" alt=\"GSC Custom Tool - Google Sheets Apps Script\" class=\"wp-image-451316\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Apps-Script.png.webp 773w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Apps-Script-600x238.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Apps-Script-200x79.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Apps-Script-768x305.png.webp 768w\" data-lazy-sizes=\"(max-width: 773px) 100vw, 773px\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Apps-Script.png.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"773\" height=\"307\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Apps-Script.png.webp\" alt=\"GSC Custom Tool - Google Sheets Apps Script\" class=\"wp-image-451316\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Apps-Script.png.webp 773w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Apps-Script-600x238.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Apps-Script-200x79.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/GSC-Custom-Tool-Google-Sheets-Apps-Script-768x305.png.webp 768w\" sizes=\"auto, (max-width: 773px) 100vw, 773px\"><\/figure>\n<\/div>\n<p>To do so, open your file, then go to <em>Extensions &gt; Apps Script. <\/em>Copy and paste the code I\u2019ve created below.\u00a0<\/p>\n<p>(You can do this by selecting the code inside the window and hitting CTRL + C. Go back into your Apps Script and hit CTRL + V to paste the code in.)<\/p>\n<p>Hit <em>OK &gt; Save project &gt; Run.<\/em><\/p>\n<p>Google will prompt you to review all permissions and select the corresponding account with all your Google Search Console data linked.<\/p>\n<p><strong><em>Dig deeper: 5 Python scripts for automating SEO tasks<\/em><\/strong><\/p>\n<p><!-- START INLINE FORM --><\/p>\n<p><!-- END INLINE FORM --><\/p>\n<hr class=\"wp-block-separator has-text-color has-cyan-bluish-gray-color has-css-opacity has-cyan-bluish-gray-background-color has-background\">\n<h3 class=\"wp-block-heading\" id=\"h-step-5-add-access-credentials\"><span class=\"ez-toc-section\" id=\"Step_5_Add_access_credentials\"><\/span>Step 5: Add access credentials<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Return to your Google Cloud Console to make further adjustments.\u00a0<\/p>\n<p>Click on <em>Credentials<\/em> on the left side of the screen:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"883\" height=\"654\" alt=\"Google Cloud project - GSC Custom Tool credentials\" class=\"wp-image-451317\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-credentials.png.webp 883w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-credentials-456x338.png.webp 456w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-credentials-800x593.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-credentials-153x113.png.webp 153w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-credentials-768x569.png.webp 768w\" data-lazy-sizes=\"(max-width: 883px) 100vw, 883px\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-credentials.png.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"883\" height=\"654\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-credentials.png.webp\" alt=\"Google Cloud project - GSC Custom Tool credentials\" class=\"wp-image-451317\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-credentials.png.webp 883w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-credentials-456x338.png.webp 456w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-credentials-800x593.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-credentials-153x113.png.webp 153w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-GSC-Custom-Tool-credentials-768x569.png.webp 768w\" sizes=\"auto, (max-width: 883px) 100vw, 883px\"><\/figure>\n<\/div>\n<p>Click on <em>+ Create Credentials<\/em> at the top of the screen and select <em>OAuth client ID<\/em>.\u00a0<\/p>\n<p>Go to <em>Configure Consent Screen<\/em><strong> <\/strong>and select <em>External<\/em>. Create the screen and then enter your:<\/p>\n<ul class=\"wp-block-list\">\n<li>App name.<\/li>\n<li>Support email (linked to the GSC account).<\/li>\n<li>Developer contact information.<\/li>\n<\/ul>\n<p>Save and continue to the next screen, which says<em> Add or Remove Scopes<\/em>.\u00a0<\/p>\n<p>Select <em>Google Search Console API scopes<\/em> and update.<strong> <\/strong>Then, <em>Save and continue<\/em>.\u00a0<\/p>\n<p>Add the users you want to grant access to, then click <em>Save and continue<\/em>.<\/p>\n<h3 class=\"wp-block-heading\" id=\"h-step-6-change-to-a-google-cloud-project-for-gsc-data\"><span class=\"ez-toc-section\" id=\"Step_6_Change_to_a_Google_Cloud_project_for_GSC_data\"><\/span>Step 6: Change to a Google Cloud project for GSC data<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Click the hamburger icon and go to <em>Cloud overview &gt; Dashboard<\/em>.<\/p>\n<p>You want to copy over your <em>Project number<\/em>, which is on the page.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"835\" height=\"340\" alt=\"Google Cloud project - Cloud overview &gt; Dashboard\" class=\"wp-image-451318\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Cloud-overview-Dashboard.png.webp 835w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Cloud-overview-Dashboard-600x244.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Cloud-overview-Dashboard-800x326.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Cloud-overview-Dashboard-200x81.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Cloud-overview-Dashboard-768x313.png.webp 768w\" data-lazy-sizes=\"(max-width: 835px) 100vw, 835px\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Cloud-overview-Dashboard.png.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"835\" height=\"340\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Cloud-overview-Dashboard.png.webp\" alt=\"Google Cloud project - Cloud overview &gt; Dashboard\" class=\"wp-image-451318\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Cloud-overview-Dashboard.png.webp 835w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Cloud-overview-Dashboard-600x244.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Cloud-overview-Dashboard-800x326.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Cloud-overview-Dashboard-200x81.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Google-Cloud-project-Cloud-overview-Dashboard-768x313.png.webp 768w\" sizes=\"auto, (max-width: 835px) 100vw, 835px\"><\/figure>\n<\/div>\n<p>Navigate to the Project number, select it and copy it using CTRL + C.\u00a0<\/p>\n<p>Head over to your Google Sheet file and click on the gear icon that says <em>Project Settings<\/em>.\u00a0<\/p>\n<p>Paste your project number into the text box and click <em>Set project<\/em>.<\/p>\n<h3 class=\"wp-block-heading\" id=\"h-step-7-name-your-google-apps-script\"><span class=\"ez-toc-section\" id=\"Step_7_Name_your_Google_Apps_Script\"><\/span>Step 7: Name your Google Apps Script<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Add a name for your script to keep things organized.\u00a0<\/p>\n<p>To do this, go to <em>Project History<\/em>, click on the <em>Untitled project <\/em>toward the top of the screen, and enter \u201cGSC Custom Tool.\u201d<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1600\" height=\"704\" alt=\"Name your Apps Script\" class=\"wp-image-451319\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script.png.webp 1600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script-600x264.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script-800x352.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script-200x88.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script-768x338.png.webp 768w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script-1536x676.png 1536w\" data-lazy-sizes=\"(max-width: 1600px) 100vw, 1600px\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script.png.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1600\" height=\"704\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script.png.webp\" alt=\"Name your Apps Script\" class=\"wp-image-451319\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script.png.webp 1600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script-600x264.png.webp 600w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script-800x352.png.webp 800w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script-200x88.png.webp 200w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script-768x338.png.webp 768w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Name-your-Apps-Script-1536x676.png 1536w\" sizes=\"auto, (max-width: 1600px) 100vw, 1600px\"><\/figure>\n<\/div>\n<h3 class=\"wp-block-heading\" id=\"h-step-8-edit-the-manifest-file\"><span class=\"ez-toc-section\" id=\"Step_8_Edit_the_manifest_file\"><\/span>Step 8: Edit the manifest file<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>You\u2019ll now return to your <em>Project Settings <\/em>and click <em>Show<\/em><strong> <\/strong><em>\u201cappsscript.json\u201d<\/em> in the editor.\u00a0<\/p>\n<p>Inside the Editor, go to appsscript.json and replace everything in the file with the code below:<\/p>\n<pre class=\"wp-block-code\"><code>{\n  \"timeZone\": \"America\/New_York\",\n  \"dependencies\": {},\n  \"exceptionLogging\": \"STACKDRIVER\",\n  \"oauthScopes\": [\n    \"https:\/\/www.googleapis.com\/auth\/webmasters\",\n    \"https:\/\/www.googleapis.com\/auth\/webmasters.readonly\",\n    \"https:\/\/www.googleapis.com\/auth\/script.external_request\",\n    \"https:\/\/www.googleapis.com\/auth\/spreadsheets\",\n    \"https:\/\/www.googleapis.com\/auth\/spreadsheets.currentonly\"\n  ],\n  \"runtimeVersion\": \"V8\"\n}<\/code><\/pre>\n<p>Once you\u2019ve pasted everything in, you\u2019ll go to the Code.js file and paste this code:<\/p>\n<pre class=\"wp-block-code\"><code>\/\/ Store the OAuth token and logs in script properties\nconst scriptProperties = PropertiesService.getScriptProperties();\nconst OPENAI_URL = \"https:\/\/api.openai.com\/v1\/chat\/completions\";\nconst SYSTEM_MESSAGE = { role: \"system\", content: \"You are a helpful SEO expert.\" };\n\n\nfunction log(message) {\n  Logger.log(message); \/\/ Regular Apps Script logging\n  const logs = scriptProperties.getProperty('customLogs') || '';\n  scriptProperties.setProperty('customLogs', logs + '\\n' + message); \/\/ Append message to logs\n}\n\n\nfunction resetLogs() {\n  scriptProperties.deleteProperty('customLogs'); \/\/ Clear logs for a new execution\n}\n\n\nfunction getLogs() {\n  return scriptProperties.getProperty('customLogs') || 'No logs available.';\n}\n\n\nfunction fetchOAuthToken() {\n  let token = scriptProperties.getProperty('oauthToken');\n  if (!token) {\n    token = ScriptApp.getOAuthToken();\n    scriptProperties.setProperty('oauthToken', token);\n    log('OAuth token fetched and stored.');\n  }\n  return token;\n}\n\n\nfunction onOpen() {\n  const ui = SpreadsheetApp.getUi();\n  ui.createMenu('Search Console')\n    .addItem('Authorize GSC', 'promptReauthorization')\n    .addItem('Fetch GSC Properties', 'fetchGSCProperties')\n    .addItem('Inspect URL', 'inspectUrl') \/\/ Add the Inspect URL button\n    .addItem('AI Analyze', 'aiAnalyze') \/\/ Add the AI Analyze button\n    .addToUi();\n}\n\n\nfunction promptReauthorization() {\n  const ui = SpreadsheetApp.getUi();\n  const response = ui.alert(\n    'Re-authorize Script',\n    'Re-authorizing will revoke current permissions and require you to authorize again. Do you want to continue?',\n    ui.ButtonSet.YES_NO\n  );\n\n\n  if (response === ui.Button.YES) {\n    try {\n      scriptProperties.deleteProperty('oauthToken'); \/\/ Clear old token\n      const token = fetchOAuthToken(); \/\/ Fetch and store new token\n      log(\"OAuth Token: \" + token);\n      ui.alert('Authorization successful. No further action is required.');\n    } catch (e) {\n      ui.alert('Authorization failed: ' + e.toString());\n    }\n  } else {\n    ui.alert('Re-authorization canceled.');\n  }\n}\n\n\nfunction fetchGSCProperties() {\n  resetLogs();\n  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();\n  const oauthToken = fetchOAuthToken();\n\n\n  const sites = getSitesListFromGSC(oauthToken);\n\n\n  if (!sites || sites.length === 0) {\n    SpreadsheetApp.getUi().alert('No GSC properties found. Please ensure you have access to GSC properties.');\n    return;\n  }\n\n\n  const siteUrls = ['Select a property'].concat(\n    sites.map(site =&gt; site.siteUrl).sort()\n  );\n\n\n  sheet.getRange('A1').setValue('Select GSC property').setFontWeight('bold');\n  sheet.getRange('B1').setDataValidation(\n    SpreadsheetApp.newDataValidation()\n      .requireValueInList(siteUrls, true)\n      .build()\n  );\n  sheet.getRange('B1').setValue('Select a property').setFontWeight('bold');\n  sheet.setColumnWidth(1, 150);\n  sheet.setColumnWidth(2, 350);\n}\n\n\nlet isProcessing = false; \/\/ Global flag to prevent recursive triggering\n\n\nfunction onEdit(e) {\n  if (isProcessing) return; \/\/ Prevent re-entry during execution\n  isProcessing = true; \/\/ Set flag to true\n\n\n  try {\n    resetLogs();\n    const sheet = e.source.getActiveSheet();\n    const range = e.range;\n\n\n    \/\/ Always clear A3:D30 on edits to B1 or B2\n    if (range.getA1Notation() === 'B1' || range.getA1Notation() === 'B2') {\n      sheet.getRange('A3:D30').clearContent();\n      sheet.getRange('F1:G30').clearContent();\n\n\n      if (range.getA1Notation() === 'B1') {\n        const selectedProperty = range.getValue();\n\n\n        \/\/ Clear A2 and set loading state\n        sheet.getRange('A2').setValue('Loading results...').setFontWeight('bold');\n        sheet.getRange('B2').clearContent();\n\n\n        if (selectedProperty === 'Select a property') {\n          sheet.getRange('A2').clearContent();\n          sheet.getRange('B2').clearContent();\n          return;\n        }\n\n\n        const oauthToken = fetchOAuthToken();\n        const urls = getUrlsForProperty(selectedProperty, oauthToken);\n\n\n        if (!urls || urls.length === 0) {\n          sheet.getRange('A2').setValue('No URLs found').setFontWeight('bold');\n          sheet.getRange('B2').clearContent();\n          log(`No URLs found for property ${selectedProperty}`);\n          return;\n        }\n\n\n        sheet.getRange('A2').setValue('Select a URL').setFontWeight('bold');\n        sheet.getRange('B2').setDataValidation(\n          SpreadsheetApp.newDataValidation()\n            .requireValueInList(['Select a URL'].concat(urls), true)\n            .build()\n        );\n        sheet.getRange('B2').setValue('Select a URL').setFontWeight('bold');\n      }\n\n\n      if (range.getA1Notation() === 'B2') {\n        const selectedProperty = sheet.getRange('B1').getValue();\n        const selectedUrl = range.getValue();\n\n\n        if (selectedUrl === 'Select a URL') {\n          return;\n        }\n\n\n        sheet.getRange('A3').setValue('Loading keywords...').setFontWeight('bold');\n\n\n        const oauthToken = fetchOAuthToken();\n        const keywords = getTopKeywordsForUrl(selectedProperty, selectedUrl, oauthToken);\n\n\n        if (!keywords || keywords.length === 0) {\n          sheet.getRange('A3').setValue('No keywords found').setFontWeight('bold');\n          log(`No keywords found for URL ${selectedUrl}`);\n          return;\n        }\n\n\n        \/\/ Populate keywords and metrics\n        sheet.getRange('A3:D12').clearContent(); \/\/ Clear any loading message\n        keywords.forEach((keyword, index) =&gt; {\n          if (index &lt; 10) {\n            sheet.getRange(`A${3 + index}`).setValue(keyword.query).setFontWeight('bold');\n            sheet.getRange(`B${3 + index}`).setValue(keyword.clicks);\n            sheet.getRange(`C${3 + index}`).setValue(keyword.impressions);\n            sheet.getRange(`D${3 + index}`).setValue(keyword.ctr);\n          }\n        });\n      }\n    }\n  } catch (error) {\n    log(`Error in onEdit: ${error}`);\n  } finally {\n    isProcessing = false; \/\/ Reset the flag after execution\n  }\n}\n\n\nfunction getApiRequestDetails(selectedProperty) {\n  const payload = {\n    startDate: getThreeMonthsAgo(),\n    endDate: getToday(),\n    dimensions: [\"page\"],\n    rowLimit: 100,\n    orderBy: [{ fieldName: \"clicks\", sortOrder: \"DESCENDING\" }]\n  };\n\n\n  const apiUrl = `https:\/\/www.googleapis.com\/webmasters\/v3\/sites\/${encodeURIComponent(selectedProperty)}\/searchAnalytics\/query`;\n  return { url: apiUrl, payload: payload };\n}\n\n\nfunction getSitesListFromGSC(oauthToken) {\n  try {\n    const url=\"https:\/\/www.googleapis.com\/webmasters\/v3\/sites\";\n\n\n    const headers = {\n      'Authorization': 'Bearer ' + oauthToken,\n      'Content-Type': 'application\/json'\n    };\n\n\n    const options = {\n      method: 'get',\n      headers: headers,\n      muteHttpExceptions: true\n    };\n\n\n    const response = UrlFetchApp.fetch(url, options);\n    log(`Response Code: ${response.getResponseCode()}`);\n    log(`Response Content: ${response.getContentText()}`);\n\n\n    if (response.getResponseCode() === 200) {\n      const json = JSON.parse(response.getContentText());\n      return json.siteEntry || [];\n    } else {\n      throw new Error(`Error fetching data: ${response.getResponseCode()} - ${response.getContentText()}`);\n    }\n  } catch (e) {\n    log(`Error: ${e.toString()}`);\n    return [];\n  }\n}\n\n\nfunction getUrlsForProperty(property, oauthToken) {\n  try {\n    const apiUrl = `https:\/\/www.googleapis.com\/webmasters\/v3\/sites\/${encodeURIComponent(property)}\/searchAnalytics\/query`;\n\n\n    log(`API URL: ${apiUrl}`);\n    log(`OAuth Token: ${oauthToken}`);\n\n\n    const payload = {\n      startDate: getThreeMonthsAgo(),\n      endDate: getToday(),\n      dimensions: [\"page\"],\n      rowLimit: 100,\n      orderBy: [{ fieldName: \"clicks\", sortOrder: \"DESCENDING\" }]\n    };\n\n\n    log(`Payload: ${JSON.stringify(payload)}`);\n\n\n    const headers = {\n      Authorization: `Bearer ${oauthToken}`,\n      \"Content-Type\": \"application\/json\"\n    };\n\n\n    const options = {\n      method: \"post\",\n      contentType: \"application\/json\",\n      headers: headers,\n      payload: JSON.stringify(payload),\n      muteHttpExceptions: true\n    };\n\n\n    const response = UrlFetchApp.fetch(apiUrl, options);\n\n\n    log(`Response Code: ${response.getResponseCode()}`);\n    log(`Response: ${response.getContentText()}`);\n\n\n    if (response.getResponseCode() === 200) {\n      const json = JSON.parse(response.getContentText());\n      return json.rows ? json.rows.map(row =&gt; row.keys[0]) : [];\n    } else {\n      throw new Error(`Failed to fetch data: ${response.getResponseCode()} - ${response.getContentText()}`);\n    }\n  } catch (e) {\n    log(`Error: ${e.toString()}`);\n    return [];\n  }\n}\n\n\nfunction getTopKeywordsForUrl(property, url, oauthToken) {\n  try {\n    const apiUrl = `https:\/\/www.googleapis.com\/webmasters\/v3\/sites\/${encodeURIComponent(property)}\/searchAnalytics\/query`;\n\n\n    log(`API URL: ${apiUrl}`);\n    log(`OAuth Token: ${oauthToken}`);\n\n\n    const payload = {\n      startDate: getThreeMonthsAgo(),\n      endDate: getToday(),\n      dimensions: [\"query\"],\n      dimensionFilterGroups: [\n        {\n          filters: [\n            {\n              dimension: \"page\",\n              operator: \"equals\",\n              expression: url\n            }\n          ]\n        }\n      ],\n      rowLimit: 10,\n      orderBy: [{ fieldName: \"clicks\", sortOrder: \"DESCENDING\" }]\n    };\n\n\n    log(`Payload: ${JSON.stringify(payload)}`);\n\n\n    const headers = {\n      Authorization: `Bearer ${oauthToken}`,\n      \"Content-Type\": \"application\/json\"\n    };\n\n\n    const options = {\n      method: \"post\",\n      contentType: \"application\/json\",\n      headers: headers,\n      payload: JSON.stringify(payload),\n      muteHttpExceptions: true\n    };\n\n\n    const response = UrlFetchApp.fetch(apiUrl, options);\n    log(`Response Code: ${response.getResponseCode()}`);\n    log(`Response: ${response.getContentText()}`);\n\n\n    if (response.getResponseCode() === 200) {\n      const json = JSON.parse(response.getContentText());\n      return json.rows ? json.rows.map(row =&gt; ({\n        query: row.keys[0],\n        clicks: row.clicks,\n        impressions: row.impressions,\n        ctr: row.ctr\n      })) : [];\n    } else {\n      throw new Error(`Failed to fetch data: ${response.getResponseCode()} - ${response.getContentText()}`);\n    }\n  } catch (e) {\n    log(`Error: ${e.toString()}`);\n    return [];\n  }\n}\n\n\nfunction getToday() {\n  const today = new Date();\n  return today.toISOString().split(\"T\")[0];\n}\n\n\nfunction getThreeMonthsAgo() {\n  const date = new Date();\n  date.setMonth(date.getMonth() - 3);\n  return date.toISOString().split(\"T\")[0];\n}\n\n\nfunction inspectUrl() {\n  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();\n  const url = sheet.getRange('B2').getValue();\n  const property = sheet.getRange('B1').getValue();\n\n\n  \/\/ Clear previous inspection results in A15:D30\n  sheet.getRange('A15:D30').clearContent();\n  sheet.getRange('A15').setValue('Inspecting...').setFontWeight('bold');\n\n\n  if (!url || url === 'Select a URL') {\n    SpreadsheetApp.getUi().alert('Please select a valid URL in cell B2 before inspecting.');\n    sheet.getRange('A15').setValue('No URL selected').setFontWeight('bold');\n    return;\n  }\n\n\n  const oauthToken = fetchOAuthToken();\n\n\n  try {\n    const result = callUrlInspectionApi(property, url, oauthToken);\n\n\n    \/\/ Extract fields from the response\n    const indexStatus = result.indexStatusResult || {};\n    const mobileUsability = result.mobileUsabilityResult || {};\n    const richResults = result.richResultsInfo || {};\n    const referringUrls = indexStatus.referringUrls?.join(', ') || 'None';\n\n\n    \/\/ Populate inspection results in the sheet\n    sheet.getRange('A15').setValue(`Inspection Results`).setFontWeight('bold');\n    sheet.getRange('A16').setValue(`URL:`).setFontWeight('bold');\n    sheet.getRange('B16').setValue(url);\n\n\n    sheet.getRange('A17').setValue(`Coverage:`).setFontWeight('bold');\n    sheet.getRange('B17').setValue(indexStatus.coverageState || 'Unknown');\n\n\n    sheet.getRange('A18').setValue(`Robots.txt:`).setFontWeight('bold');\n    sheet.getRange('B18').setValue(indexStatus.robotsTxtState || 'Unknown');\n\n\n    sheet.getRange('A19').setValue(`Indexing State:`).setFontWeight('bold');\n    sheet.getRange('B19').setValue(indexStatus.indexingState || 'Unknown');\n\n\n    sheet.getRange('A20').setValue(`Last Crawled:`).setFontWeight('bold');\n    sheet.getRange('B20').setValue(indexStatus.lastCrawlTime || 'Not Available');\n\n\n    sheet.getRange('A21').setValue(`Google Canonical:`).setFontWeight('bold');\n    sheet.getRange('B21').setValue(indexStatus.googleCanonical || 'Unknown');\n\n\n    sheet.getRange('A22').setValue(`User Canonical:`).setFontWeight('bold');\n    sheet.getRange('B22').setValue(indexStatus.userCanonical || 'Unknown');\n\n\n    sheet.getRange('A23').setValue(`Mobile Usability:`).setFontWeight('bold');\n    sheet.getRange('B23').setValue(mobileUsability.verdict || 'Unknown');\n\n\n    sheet.getRange('A24').setValue(`Rich Results Eligibility:`).setFontWeight('bold');\n    sheet.getRange('B24').setValue(richResults.verdict || 'Unknown');\n\n\n    sheet.getRange('A25').setValue(`Referring URLs:`).setFontWeight('bold');\n    sheet.getRange('B25').setValue(referringUrls);\n\n\n    \/\/ Log and alert full response for debugging\n    const fullResponse = JSON.stringify(result, null, 2);\n    log(`Full Inspection Result: ${fullResponse}`);\n    \/\/SpreadsheetApp.getUi().alert(`Inspection Completed. Full Response:\\n\\n${fullResponse}`);\n  } catch (error) {\n    sheet.getRange('A15').setValue('Inspection Failed').setFontWeight('bold');\n    log(`Error inspecting URL: ${error.message}`);\n    SpreadsheetApp.getUi().alert(`Error inspecting URL: ${error.message}\\n\\nLogs:\\n${getLogs()}`);\n  }\n}\n\n\nfunction callUrlInspectionApi(property, url, oauthToken) {\n  const apiUrl=\"https:\/\/searchconsole.googleapis.com\/v1\/urlInspection\/index:inspect\";\n\n\n  const payload = {\n    siteUrl: property,\n    inspectionUrl: url,\n    languageCode: 'en-US'\n  };\n\n\n  const headers = {\n    Authorization: `Bearer ${oauthToken}`,\n    'Content-Type': 'application\/json'\n  };\n\n\n  const options = {\n    method: 'post',\n    contentType: 'application\/json',\n    headers: headers,\n    payload: JSON.stringify(payload),\n    muteHttpExceptions: true\n  };\n\n\n  log(`API URL: ${apiUrl}`);\n  log(`Payload: ${JSON.stringify(payload)}`);\n\n\n  try {\n    const response = UrlFetchApp.fetch(apiUrl, options);\n    const responseCode = response.getResponseCode();\n    const responseText = response.getContentText();\n\n\n    log(`Response Code: ${responseCode}`);\n    log(`Response Content: ${responseText}`);\n\n\n    if (responseCode === 200) {\n      const jsonResponse = JSON.parse(responseText);\n\n\n      if (jsonResponse &amp;&amp; jsonResponse.inspectionResult) {\n        return jsonResponse.inspectionResult;\n      } else {\n        log(`Unexpected API Response Structure: ${responseText}`);\n        throw new Error('Unexpected API response format. \"inspectionResult\" field is missing.');\n      }\n    } else {\n      log(`Failed API Call: ${responseText}`);\n      throw new Error(`Failed to inspect URL. Response Code: ${responseCode}. Response: ${responseText}`);\n    }\n  } catch (error) {\n    log(`Error during API call: ${error}`);\n    throw new Error(`Error inspecting URL: ${error.message}`);\n  }\n}\n\n\nfunction callChatGPT(prompt, temperature = 0.9, maxTokens = 800, model = \"gpt-3.5-turbo\") {\n  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();\n  const secretKey = sheet.getRange('D1').getValue().trim(); \/\/ Retrieve the OpenAI API key from D1\n\n\n  if (!secretKey) {\n    throw new Error(\"API Key is missing in cell D1. Please provide a valid OpenAI API key.\");\n  }\n\n\n  const payload = {\n    model: model,\n    messages: [\n      SYSTEM_MESSAGE,\n      { role: \"user\", content: prompt }\n    ],\n    temperature: temperature,\n    max_tokens: maxTokens\n  };\n\n\n  const options = {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application\/json\",\n      \"Authorization\": \"Bearer \" + secretKey\n    },\n    payload: JSON.stringify(payload)\n  };\n\n\n  try {\n    const response = UrlFetchApp.fetch(OPENAI_URL, options);\n    const responseData = JSON.parse(response.getContentText());\n\n\n    if (responseData.choices &amp;&amp; responseData.choices[0] &amp;&amp; responseData.choices[0].message) {\n      return responseData.choices[0].message.content.trim();\n    } else {\n      log(\"Unexpected response format from OpenAI: \" + JSON.stringify(responseData));\n      return \"Sorry, I couldn't process the request.\";\n    }\n  } catch (error) {\n    log(\"Error calling OpenAI API: \" + error);\n    return \"Sorry, there was an error processing your request.\";\n  }\n}\n\n\nfunction aiAnalyze() {\n  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();\n  const url = sheet.getRange('B2').getValue();\n  const keywords = sheet.getRange('A3:A12').getValues().flat().filter(Boolean); \/\/ Get non-empty keywords\n  const inspectionData = sheet.getRange('A16:B20').getValues();\n\n\n  \/\/ Validate input fields\n  if (!url || keywords.length === 0 || inspectionData.some(row =&gt; row.length &lt; 2 || !row[0].trim() || !row[1].trim())) {\n    SpreadsheetApp.getUi().alert(\"Ensure the following are filled before running AI Analyze:\\n- URL in B2\\n- Keywords in A3:A12\\n- Inspection data in A16:B20\");\n    return;\n  }\n\n\n  \/\/ Prepare the prompt for ChatGPT\n  const prompt = `\n    Analyze this URL: ${url}\n    Also the view-source version from: ${url}\n    against these keywords: ${keywords.join(\", \")}\n    Considering the URL inspection data from Google Search Console:\n    ${inspectionData.map(row =&gt; `${row[0]}: ${row[1]}`).join(\"\\n\")}\n    Suggest a short list of specific recommendations on how I can improve the page's SEO. Make sure the recommendations include details such as change this to that, or add something, etc... Be concrete with SEO recommendations.\n  `;\n\n\n  \/\/ Display the prompt in G1\n  sheet.getRange('G1').setValue(\"Prompt Sent to ChatGPT\").setFontWeight(\"bold\");\n  sheet.getRange('G2:G30').clearContent(); \/\/ Clear previous content in column G\n  sheet.getRange('G2:G30').merge(); \/\/ Merge cells G2:G30\n  sheet.getRange('G2').setValue(prompt).setVerticalAlignment(\"top\"); \/\/ Add the prompt and align to top\n  sheet.setColumnWidth(7, 400); \/\/ Set column G width to 400px\n\n\n  \/\/ Call ChatGPT API\n  const analysisResult = callChatGPT(prompt);\n\n\n  \/\/ Display the result in the spreadsheet (Column F)\n  sheet.getRange('F1').setValue(\"AI Analysis Result\").setFontWeight(\"bold\");\n  sheet.getRange('F2:F30').clearContent(); \/\/ Clear previous content\n  sheet.getRange('F2:F30').merge(); \/\/ Merge the cells\n  sheet.getRange('F2').setValue(analysisResult).setVerticalAlignment(\"top\"); \/\/ Add the AI result and align to top\n  sheet.setColumnWidth(6, 400); \/\/ Set column F width to 400px\n\n\n  \/\/ Log the response\n  log(\"AI Analysis Completed: \" + analysisResult);\n}<\/code><\/pre>\n<p>Once done, go back to your sheets, refresh and use the new <em>Search Console &gt; Fetch GSC Properties<\/em>.<\/p>\n<p>Follow the prompts until it asks you to select the account you\u2019re using and to ultimately select the app you plan on using.<\/p>\n<p>If everything goes well, you can move on to the exciting part of putting it together and running your first SEO analysis using your new script.<\/p>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Putting_our_Sheets_GSC_and_ChatGPT_tool_together\"><\/span>Putting our Sheets, GSC and ChatGPT tool together<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>You\u2019ve done a lot until now, but it\u2019s time to see the tool in action. Here\u2019s how it works:\u00a0<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"414\" height=\"229\" alt=\"Putting our Sheets, GSC and ChatGPT tool together\" class=\"wp-image-451320\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Putting-our-Sheets-GSC-and-ChatGPT-tool-together.png.webp 414w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Putting-our-Sheets-GSC-and-ChatGPT-tool-together-200x111.png.webp 200w\" data-lazy-sizes=\"(max-width: 414px) 100vw, 414px\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Putting-our-Sheets-GSC-and-ChatGPT-tool-together.png.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"414\" height=\"229\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Putting-our-Sheets-GSC-and-ChatGPT-tool-together.png.webp\" alt=\"Putting our Sheets, GSC and ChatGPT tool together\" class=\"wp-image-451320\" srcset=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Putting-our-Sheets-GSC-and-ChatGPT-tool-together.png.webp 414w,https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Putting-our-Sheets-GSC-and-ChatGPT-tool-together-200x111.png.webp 200w\" sizes=\"auto, (max-width: 414px) 100vw, 414px\"><\/figure>\n<\/div>\n<ul class=\"wp-block-list\">\n<li>Go to <em>Search Console &gt; Authorize GSC.<\/em><\/li>\n<\/ul>\n<p>Be sure that you\u2019re using the account to which the domain\u2019s GSC is connected; otherwise, it will not work.<\/p>\n<ul class=\"wp-block-list\">\n<li>Go to<em> Search Console &gt; Fetch GSC properties.<\/em><\/li>\n<\/ul>\n<p>You\u2019ll now notice that the <em>Select GSC property<\/em> at <code>B1<\/code> on the Sheet is populated. Select the domain you want to analyze and then select the URL from <code>B1<\/code> on the Sheet.\u00a0<\/p>\n<ul class=\"wp-block-list\">\n<li>Go to <em>Search Console &gt; Inspect URL.<\/em><\/li>\n<\/ul>\n<p>The<strong> <\/strong>Inspection Results on the Sheet will populate and offer you a wealth of information about the page, such as the coverage, last crawl date, and more.\u00a0<\/p>\n<p>Finally, we\u2019ll go back one last time and do the following:<\/p>\n<ul class=\"wp-block-list\">\n<li>Go to <em>Search Console &gt; AI Analyze.<\/em><\/li>\n<\/ul>\n<p>All of the information in the \u201cAI Analysis Result\u201d will now populate, offering you insights into the page\u2019s key elements and telling you the exact steps that you can take to improve the page.<\/p>\n<p>I don\u2019t recommend following the directions blindly, but they do offer actionable steps that you can follow to strengthen the page.<\/p>\n<p>If you want to change the ChatGPT prompt to add your own custom data, go to cell <code>G2<\/code><strong>,<\/strong> right underneath the heading that says \u201cPrompt Sent to ChatGPT.\u201d<\/p>\n<p>Bravo! You have a working script that can speed up your SEO analysis and make your day more actionable.\u00a0<\/p>\n<p>Combining Sheets, GSC and ChatGPT has helped me become more efficient and allows me to spend more time optimizing and less analyzing thousands of pages.<\/p>\n<p>Experiment with the script and find new ways to make it your own.<\/p>\n<p><strong><em>Dig deeper: <\/em><\/strong><strong><em>15 AI tools you should use for SEO<\/em><\/strong><\/p>\n<\/div>\n<p><\/p>\n<div class=\"about-author\">\n<p>About the author<\/p>\n<div class=\"information\">\n<div class=\"author-module\">\n<div class=\"row\">\n<div class=\"col-12 col-lg-3 text-center\">\n<div class=\"avatar\">\n\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" class=\"img-fluid rounded-circle avatar-border\" alt=\"Ludwig Makhyan\" width=\"140\" height=\"140\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2022\/03\/Ludwig.Mahkyan-1.png.webp\"><img loading=\"lazy\" decoding=\"async\" class=\"img-fluid rounded-circle avatar-border\" src=\"https:\/\/searchengineland.com\/wp-content\/seloads\/2022\/03\/Ludwig.Mahkyan-1.png.webp\" alt=\"Ludwig Makhyan\" width=\"140\" height=\"140\">\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\n<\/p><\/div>\n<div class=\"col-12 col-lg-9\">\n<div class=\"about\">\n<div class=\"name\">\n\t\t\t\t\t\t\t<strong>Ludwig Makhyan<\/strong>\n\t\t\t\t\t\t<\/div>\n<div class=\"row g-2 pt-2\">\n<div class=\"col-auto twitter\">\n\t\t\t\t\t\t\t\t\t<a rel=\"nofollow\" target=\"_blank\" href=\"https:\/\/twitter.com\/intent\/follow?original_referer=https%3A%2F%2Fsearchengineland.com%2F&amp;region=follow_link&amp;screen_name=makhyan&amp;tw_p=followbutton&amp;variant=2.0\" rel=\"me\" target=\"_blank\" aria-label=\"opens in a new tab\"><i class=\"fab fa-x-twitter\"><\/i><\/a>\n\t\t\t\t\t\t\t<\/div>\n<div class=\"col-auto\">\n\t\t\t\t\t\t\t\t\t<a rel=\"nofollow\" target=\"_blank\" href=\"https:\/\/www.linkedin.com\/in\/makhyan\/\" target=\"_blank\" aria-label=\"opens in a new tab\"><i class=\"fab fa-linkedin\"><\/i><\/a>\n\t\t\t\t\t\t\t\t<\/div>\n<\/p><\/div>\n<p>\t\t\t\t\t\tLudwig Makhyan is a contributor for Search Engine Land, covering organic and technical SEO. His background is in web development and digital marketing. Ludwig has over 20 years of experience in website design, coding and promotion. He is the co-founder at <a rel=\"nofollow\" target=\"_blank\" href=\"https:\/\/www.mazeless.com\/\">MAZELESS<\/a>, an enterprise SEO agency.\t\t\t\t\t<\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<p><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/p>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMN63nwsw68G3Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span>\u00a0too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/category\/technology\/\" target=\"_blank\" >Technology<\/a><\/span> category.<\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/searchengineland.com\/automate-seo-analysis-with-google-sheets-gsc-chatgpt-api-451306\" target=\"_blank\" >Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Automate site audits, analyze pages and generate AI-driven optimization insights all within Google Sheets. SEO analysis can be time-consuming, but automating the process helps eliminate repetitive tasks and speeds up important website optimizations.\u00a0 This guide will show you how to build a custom tool using Google Sheets, Google Search Console (GSC), and the ChatGPT API&#8230;<\/p>\n","protected":false},"author":1,"featured_media":651670,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/searchengineland.com\/wp-content\/seloads\/2025\/01\/Automate-SEO-analysis-with-Google-Sheets-GSC-and-ChatGPT-API.png","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[26293,78070,148084],"class_list":["post-651669","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology","tag-google","tag-seo","tag-technical-optimization"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/651669","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=651669"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/651669\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/651670"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=651669"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=651669"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=651669"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}