Google Apps Scriptで転送システムや画像バイナリ表示を作りたかったが…そもそも無理だった
てことで、書きました。
できごと
自分のサーバがバレないURL転送が欲しくなった
noteに複数記事書いてると、最後に定型文とか書くよね?
そこに期間限定のメッセージとか載せたりするじゃない?
で思ったのだ。
と…
URL登録しておいて、画像を書き換えたらいいかも…とは思ったし、
PHPで作ろうと思えばカンタンだけど、
複数アカウント運営なので、PHPのURLや画像URLからサーバばれて、本垢バレるじゃん。
ウマくない。
じゃあ、例えばbit.lyとかの短縮サービスを使えば、元のURLは分からないし、使えば良いかなって思うじゃん?
でも後からURL変えられない。
これで画像は解決してないし。
という判断になった。
何がしたかったかまとめ(要件)
- 表形式でURLを管理したい ⇨ スプシ感覚でID・URL・画像などを一元管理
- スクリプトで処理分岐したい ⇨
?id=xxx&type=urlのようにURL間違えにくく - 公開URLがある ⇨ 外部からアクセス・表示・転送
- 無料で使える ⇨ コストゼロは必須
- 別々のURLで管理 ⇨ コピーで複数作れる
Google Apps Scriptで転送・画像読込システムを作ってみよう!
データ管理
スプレッドシートに以下のように登録
| id | url | image |
|---|---|---|
| koudou | https://note.com/kuraeqooga | https://qooga.jb-jk.net/item/image/cover/qooga/2025/koudou-switch.png |
| …以下略… | …以下略… | …以下略… |
idの値を『探索キー』として、データベースのように使う。
API
https://script.google.com/macros/s/なんとかかんとか/exec?id=【探索キー】&type=【urlかimage】
APIアクセス方法
…?id=【探索キー】&type=url ⇨ 302リダイレクト
…?id=【探索キー】&type=image ⇨ 画像バイナリ表示
Apps Scriptコード
function doGet(e) {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
const idParam = e.parameter.id;
const typeParam = e.parameter.type;
const idColumn = sheet.getRange(1, 1, sheet.getLastRow()).getValues().flat();
const rowIndex = idColumn.indexOf(idParam);
if (rowIndex === -1) {
return ContentService.createTextOutput("ID not found").setMimeType(ContentService.MimeType.TEXT);
}
const row = sheet.getRange(rowIndex + 1, 1, 1, 3).getValues()[0];
if (typeParam === "url") {
const redirectUrl = row[1];
if (!redirectUrl || redirectUrl.trim() === "") {
return ContentService.createTextOutput("Invalid URL").setMimeType(ContentService.MimeType.TEXT);
}
return HtmlService.createHtmlOutput(`<script>location.href='${redirectUrl}'</script>`);
}
if (typeParam === "image") {
const imageUrl = row[2];
const response = UrlFetchApp.fetch(imageUrl);
const blob = response.getBlob();
blob.setName("image.png"); // 任意のファイル名
return blob;
}
return ContentService.createTextOutput("Invalid type").setMimeType(ContentService.MimeType.TEXT);
}
appsscript.json対応
設定されてないと、以下のメッセージが出る。
exception: urlfetchapp.fetch を呼び出す権限がありません。
『プロジェクトの設定』⇨『「appsscript.json」マニフェスト ファイルをエディタで表示する』をチェック
エディタに出来た『appsscript.json』に
"oauthScopes": [
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/spreadsheets"
]
を追加しておく。
デプロイして許可を忘れずに
「テストだけでいいやー」て場合でも、1回デプロイして許可しないと使えないから注意。
やりかたは割愛する。
結果
302リダイレクト

あ・・・
画像バイナリ表示

あ・・・
GASで作るとそうになっちゃうよね!
Google Apps Scriptには制約がある
GASには色々制約があるから、作れないものもあるのだ。
もう目に馴染んでて忘れてたけど、iFrameもその1つ。
GAS Webアプリの制約ポイント
おおよそこんな感じ
| 制約 | 詳細 |
|---|---|
| iframe表示 | GASのWebアプリはGoogleドメイン内でiframeタグに包まれる |
window.location.hrefでのリダイレクト |
iframeタグ内なので親ページには効かない。iFrame禁止になってるサイトなら読込禁止になる |
X-Frame-Optionsの制御 |
HtmlService.setXFrameOptionsMode()で一部制御可能ではあるが…制限あり |
| 外部埋め込み不可 | GASのWebアプリは他ドメインからの埋め込みを基本的に拒否する |
他にも画像読み込むのにクロスドメインだとか、GASで読込禁止だーだとかまぁつまり
作ろうと思った方の参考になればいいね!
もう『要件』を叶える方法はないの?
て言われると、そんなことはなくて、代わりになるものは存在する。
GASの代替になるスクリプト環境+公開URL対応サービス
調べるのめんどくさいからCopilotさんにお願いした。
間違ってたらごめんね。
| サービス | 特徴 | 公開URL | 画像/リダイレクト対応 | 備考 |
|---|---|---|---|---|
| Firebase Hosting + Cloud Functions | JS/TSで自由にAPIとページ構築 | 独自URL可 | 完全制御可能 | Google製。GASより自由度高い |
| Vercel / Netlify | HTML/JSをGit連携で即公開 | 独自ドメイン対応 | iframe制限なし | 静的サイト+APIもOK |
| Glitch | ブラウザでNode.js開発可 | 即時公開 | Expressで自由制御 | 学習にも向いてる。無料枠あり |
| Replit | Python/Nodeなど多言語対応 | Web公開可 | Webサーバ構築可能 | GASより柔軟。教育向けにも人気 |
| Cloudflare Pages + Workers | 高速CDN+JSベースAPI | 高速公開 | リダイレクト・画像制御OK | 軽量で爆速。無料枠も強い |
| 管理方法 | 表形式 | スクリプト制御 | 公開URL | 無料枠 | テンプレート化 |
|---|---|---|---|---|---|
| GAS(制限あり) | ✅ | ✅ | ⚠️ iframe制限 | ✅ | ✅ |
| Notion + Vercel(またはReplit) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Airtable + Workers | ✅ | ✅ | ✅ | ✅ | ✅ |
| Firebase + スプレッドシート | ✅ | ✅ | ✅ | ✅ | ✅(やや重) |
けど…いつやろうかな…
Vercelの公開URLについて
- デフォルトURL ⇨
https://your-project-name.vercel.app(無料で発行) - 複製時のURL ⇨ プロジェクト名が違えば `your-copy.vercel.app` など別URLになる
- サブドメイン運用 ⇨
client1.vercel.app、client2.vercel.appのように分けられる - 独自ドメイン ⇨ 任意。使いたければ設定可能(無料枠でもOK)


コメント