Google Tag Manager(GTM)のカスタムHTMLタグを使えば、サイトにコードを直書きせずにチャットウィジェットを埋め込むことができます。今回は、Anthropic の Claude API を利用したシンプルなチャットボットを、Google Apps Script(GAS)をプロキシとして構築し、GTM経由でサイトに設置する方法を紹介します。
💡 なぜGASをプロキシにするのか
フロントエンドのJavaScriptに直接APIキーを書いてしまうと、ブラウザの開発者ツールから誰でもキーを盗み見ることができてしまいます。そこで、APIキーはGASのスクリプトプロパティに保存し、GTMのカスタムHTMLタグからはGASのWebアプリURLだけを呼び出す構成にします。これにより、キーをブラウザ側に一切露出させずにClaude APIを利用できます。
🛠 設定方法
-
GASプロジェクトの作成
新規のGoogle Apps Scriptプロジェクトを作成し、後述のコードを貼り付けます。 -
スクリプトプロパティの設定
[プロジェクトの設定] ⚙️ > [スクリプト プロパティ] で、プロパティ名CLAUDE_API_KEYを追加し、Anthropicコンソールで発行したAPIキーを値に設定します。 -
Webアプリとしてデプロイ
「デプロイ」>「新しいデプロイ」からWebアプリとして公開し、「アクセスできるユーザー」を全員に設定します。発行されたURLを控えておきます。 -
GTMでカスタムHTMLタグを作成
GTMの管理画面で新規タグを作成し、チャットUIのHTML/CSS/JavaScriptを記述します。fetchのエンドポイントには、手順3で取得したGAS WebアプリURLを指定します。
📜 実装コード(GAS側)
/**
* GTMのカスタムHTMLタグから呼び出され、Claude APIへ中継するWebアプリ。
* APIキーはスクリプトプロパティにのみ保持し、フロントエンドには公開しない。
*
* 事前準備:
* - [プロジェクトの設定] → [スクリプト プロパティ] に
* CLAUDE_API_KEY を登録しておく(コードに直書きしない)
*/
function doPost(e) {
try {
const apiKey = PropertiesService.getScriptProperties().getProperty('CLAUDE_API_KEY');
if (!apiKey) {
throw new Error('CLAUDE_API_KEY が設定されていません。');
}
const contents = JSON.parse(e.postData.contents);
const userMessage = contents.message;
const url = 'https://api.anthropic.com/v1/messages';
const payload = {
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
messages: [
{ role: 'user', content: userMessage }
]
};
const options = {
method: 'post',
contentType: 'application/json',
headers: {
'x-api-key': apiKey,
'anthropic-version': '2023-06-01'
},
payload: JSON.stringify(payload),
muteHttpExceptions: true
};
const response = UrlFetchApp.fetch(url, options);
const json = JSON.parse(response.getContentText());
return ContentService
.createTextOutput(JSON.stringify(json))
.setMimeType(ContentService.MimeType.JSON);
} catch (err) {
return ContentService
.createTextOutput(JSON.stringify({ error: String(err) }))
.setMimeType(ContentService.MimeType.JSON);
}
}
/**
* 動作確認用ヘルスチェックエンドポイント
*/
function doGet(e) {
return ContentService
.createTextOutput(JSON.stringify({ status: 'ok' }))
.setMimeType(ContentService.MimeType.JSON);
}
⚠️ 注意点
GASのWebアプリは公開URLになるため、誰でもPOSTリクエストを送れる状態になります。想定外の利用やAPI利用料の急増を防ぐため、リクエスト元のオリジンチェックや簡易的なレート制限をdoPost内に追加することをおすすめします。また、Anthropicの利用規約や料金プランも事前に確認しておくと安心です。
