質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Q&A

1回答

203閲覧

GASでサーチコンソールのデータを取りたいが403エラーが出る

shion13

総合スコア1

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

0グッド

1クリップ

投稿2024/10/14 08:27

実現したいこと

Googleサーチコンソールから、2日前のサイト全体の以下のデータを取得し、スプレッドシートに出力したい。

  • 表示回数
  • クリック数

発生している問題・分からないこと

54行目のthrow new Errorにてエラーが発生しました。
43行目の「response = UrlFetchApp.fetch(apiURL, options);」にて取得したresponseの中身に問題があるようです。

エラーメッセージによると、このサイトの権限を持っていないと書かれています。しかし、実際には、GASを実行しているGoogleアカウントがサーチコンソールのオーナーです。サーチコンソールの「ユーザーと権限」というページを見て確認しました。

エラーメッセージ

error

1Error: API request failed with status 403: { 2 "error": { 3 "code": 403, 4 "message": "User does not have sufficient permission for site 'https://hoge-hoge.com/'. See also: https://support.google.com/webmasters/answer/2451999.", 5 "errors": [ 6 { 7 "message": "User does not have sufficient permission for site 'https://hoge-hoge.com/'. See also: https://support.google.com/webmasters/answer/2451999.", 8 "domain": "global", 9 "reason": "forbidden" 10 } 11 ] 12 } 13}

該当のソースコード

Google

1function getSearchConsoleApi(){ 2 3 //GASスクリプトに紐づくスプレッドシートのアクティブなシート読み込み 4 const mySheet = SpreadsheetApp.getActiveSheet(); 5 6 //サーチコンソールの取得する開始日・終了日を定義※取得したい期間を設定 7 const startDate = "2024-10-01"; 8 const endDate = "2024-10-10"; 9 10 // サーチコンソールから取得するドメイン名を定義※書き換え必須 11 const siteDomain = "https://hoge-hoge.com/"; 12 13 // ドメインを正しくエンコードする 14 const encodedDomain = encodeURIComponent(siteDomain); 15 16 // リクエストするAPIのURLを設定する 17 const apiURL = `https://www.googleapis.com/webmasters/v3/sites/${encodedDomain}/searchAnalytics/query`; 18 19 20 //サーチコンソールから取得する最大クエリ数を設定する 21 const maxQuery = 1000; 22 23 //APIリクエスト時にセットするペイロード値を設定する 24 const payload = { 25 'startDate': startDate, 26 'endDate': endDate, 27 "dimensions": ["page", "query"], // ディメンションの設定方法はまだわかっていない。 28 "rowLimit": maxQuery 29 }; 30 31 const options = { 32 'payload': JSON.stringify(payload), 33 'method': 'POST', 34 'muteHttpExceptions': true, 35 'headers': { "Authorization": "Bearer " + checkAndRefreshToken() }, 36 'contentType': 'application/json' 37 }; 38 39 //APIリクエストを行った結果のJSONデータを変換する 40 let response; 41 42 try { 43 response = UrlFetchApp.fetch(apiURL, options); 44 const responseCode = response.getResponseCode(); 45 const responseBody = response.getContentText(); 46 console.log(`Response Code: ${responseCode}`); 47 console.log(`Response Body: ${responseBody}`); 48 49 // レスポンスの内容を確認 50 let responseText = response.getContentText(); 51 Logger.log("API Response: " + responseText); // デバッグ用ログ 52 53 if (response.getResponseCode() !== 200) { 54 throw new Error(`API request failed with status ${responseCode}: ${responseBody}`); 55 } 56 57 // json = JSON.parse(responseText); 58 let json = JSON.parse(responseBody); 59 60 if (!json.rows || json.rows.length === 0) { 61 throw new Error("No data returned from the API"); 62 } 63 } catch (error) { 64 Logger.log("Error: " + error.message); 65 return; // エラーが発生した場合、ここで処理を終了 66 } 67 68 //JSONデータを処理してqueryを配列に保存する処理をforループで行う 69 let queryData = []; 70 for (i = 0; i < maxQuery; i++) { 71 //queryDataを2次元配列に拡張する 72 queryData[i] = []; 73 //json変数のデータをqueryDataの配列に格納する 74 queryData[i][0] = json["rows"][i]["keys"][1]; 75 queryData[i][1] = json["rows"][i]["keys"][0]; 76 queryData[i][2] = json["rows"][i]["clicks"]; 77 queryData[i][3] = json["rows"][i]["impressions"]; 78 queryData[i][4] = json["rows"][i]["position"]; 79 queryData[i][5] = json["rows"][i]["ctr"]; 80 } 81 82 //スプレッドシートにqueryデータを書き込み 83 mySheet.getRange(2, 1, queryData.length, queryData[0].length).setValues(queryData); 84 //スプレッドシートのデータの順番を表示回数で降順で並び替え 85 mySheet.getRange(2, 1, queryData.length, queryData[0].length).sort({ column: 4, ascending: false }); 86 //クリック率のCTRの数値フォーマットを%に設定 87 mySheet.getRange(2, 6, queryData.length).setNumberFormat('0.00%'); 88} 89 90 91function checkAndRefreshToken() { 92 let token = ScriptApp.getOAuthToken(); 93 94 // トークンの有効性をテストする簡単なAPIコール 95 const testUrl = "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=" + token; 96 const response = UrlFetchApp.fetch(testUrl, {'muteHttpExceptions': true}); 97 98 if (response.getResponseCode() !== 200) { 99 // トークンが無効な場合、新しいトークンを取得 100 ScriptApp.invalidateAuth(); 101 token = ScriptApp.getOAuthToken(); 102 } 103 104 return token; 105}

Google

1{ 2 "timeZone": "Asia/Tokyo", 3 "exceptionLogging": "STACKDRIVER", 4 "runtimeVersion": "V8", 5 "dependencies": { 6 "enabledAdvancedServices": [ 7 { 8 "userSymbol": "AnalyticsData", 9 "serviceId": "analyticsdata", 10 "version": "v1beta" 11 } 12 ], 13 "libraries": [ 14 { 15 "userSymbol": "OAuth2", 16 "version": "43", 17 "libraryId": "1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF" 18 } 19 ] 20 }, 21 "oauthScopes": [ 22 "https://www.googleapis.com/auth/spreadsheets", 23 "https://www.googleapis.com/auth/webmasters.readonly", 24 "https://www.googleapis.com/auth/script.external_request" 25 ] 26}

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

このコード自体は、このページを参考にしました。
https://auto-worker.com/blog/?p=3294

このページの以下の箇所でエラー(内容は失念しました)が出たので、ChatGPTやClaudeに質問しつつコードを改善していきました。
json = JSON.parse(response);

補足

  • GPCのGoogle Search Console APIは設定済み
  • ライブラリから「OAuth2」を追加済み
  • Apps Scriptエディターのプロジェクトの設定画面で、GCPのプロジェクト番号を設定済み
  • Apps Scriptエディターのプロジェクトの設定画面で、以下の箇所にチェックマークを入れました。その結果、appsscript.jsonというスクリプトファイルが生成されました。そのスクリプトファイルには「oauthScopes」情報を追記しました。

「appsscript.json」マニフェスト ファイルをエディタで表示する

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ちょっと実験してみました。
Google Search Consoleにプロパティ(情報を取得するURL)を追加し情報を確認できる状態の場合は提示されたコードを変更せず(当然情報を取得するURL部分は変更)エラーが出ずに実行できました。
そして登録したプロパティを削除し実行したところ提示されているエラー(403)が発生しました。

まずはGASではなくGoogle Search ConsoleにてそのURLの情報が見れるのかを確認してはどうでしょうか。

追記

追加で試したところドメイン プロパティの場合は
こちらにあるようにsc-domain:ドメイン名と指定しないと403エラーとなりました。
プロパティがドメインプロパティの場合は

javascript

1 // 追加したドメインプロパティがhoge-hoge.comの場合 2 const siteDomain = "sc-domain:hoge-hoge.com";

としてください。

投稿2024/10/15 02:05

編集2024/10/15 06:39
YAmaGNZ

総合スコア10469

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問