GASのWebアプリで、トップ画面と2つのページをリンクで切り替える例です。
Code.gsのdoGetがURLのpを読み、対応するHTMLを返します。
4ファイルを同じプロジェクトに作る
| 条件 | 結果 |
|---|---|
| Code.gs(コード.gs) | doGetと、許可するページ名の一覧 |
| Index.html | トップ画面 |
| Menu1.html | 1つ目の画面 |
| Menu2.html | 2つ目の画面 |
新しいApps Scriptプロジェクトを作り、Code.gsに次のJavaScriptを貼り付けます。
「ファイルを追加」からHTMLを選び、Index、Menu1、Menu2の名前で作成します。
ファイル名の大文字・小文字をコードと揃えてください。
HTMLをCode.gsへ貼り付けると動きません。
Code.gsにはdoGet、各HTMLファイルには対応するHTMLだけを入れます。
Code.gs:pから表示するファイルを選ぶ
const PAGE_FILES = Object.freeze({index: 'Index', menu1: 'Menu1', menu2: 'Menu2'});
function doGet(e) {
const values = e && e.parameters && e.parameters.p;
const page = e && e.parameter && e.parameter.p || 'index';
if ((values && values.length !== 1) ||
!Object.prototype.hasOwnProperty.call(PAGE_FILES, page)) {
return HtmlService.createHtmlOutput(
'<h1>該当するページがありません</h1><p>URLのpをindex、menu1、menu2のいずれかにしてください。</p>'
).setTitle('ページ指定を確認してください');
}
const appUrl = ScriptApp.getService().getUrl();
if (!appUrl) throw new Error('テストデプロイまたはWebアプリのURLから開いてください。');
const template = HtmlService.createTemplateFromFile(PAGE_FILES[page]);
template.appUrl = appUrl;
return template.evaluate().setTitle('ページ遷移の練習:' + page);
}
pの値はindex、menu1、menu2だけを受け付け、指定がない場合はindexを使います。
未知の値やpの重複指定はエラー画面にするため、URLから任意のファイル名を渡して開く構成ではありません。
Webアプリの入口に必要なdoGetとイベントの仕様はGoogle公式のWebアプリガイドを参照してください。
Index.html:トップ画面
<!DOCTYPE html>
<html lang="ja">
<head>
<base target="_top">
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>body{font:18px/1.7 sans-serif;margin:2rem;max-width:42rem}nav{display:flex;gap:1rem;flex-wrap:wrap}a{padding:.5rem;border:1px solid #2768af;border-radius:4px;color:#14569b}a:focus-visible{outline:3px solid #e09319;outline-offset:3px}</style>
</head>
<body>
<h1>Indexページ</h1>
<p>練習用のトップ画面です。Menu1、Menu2へ移動して戻れます。</p>
<nav aria-label="練習ページ">
<a href="<?= appUrl ?>?p=index">トップ</a>
<a href="<?= appUrl ?>?p=menu1">Menu1</a>
<a href="<?= appUrl ?>?p=menu2">Menu2</a>
</nav>
</body>
</html>
Menu1.html:1つ目の画面
<!DOCTYPE html>
<html lang="ja">
<head>
<base target="_top">
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>body{font:18px/1.7 sans-serif;margin:2rem;max-width:42rem}nav{display:flex;gap:1rem;flex-wrap:wrap}a{padding:.5rem;border:1px solid #2768af;border-radius:4px;color:#14569b}a:focus-visible{outline:3px solid #e09319;outline-offset:3px}</style>
</head>
<body>
<h1>Menu1ページ</h1>
<p>最初の練習画面です。トップまたはMenu2へ移動できます。</p>
<nav aria-label="練習ページ">
<a href="<?= appUrl ?>?p=index">トップ</a>
<a href="<?= appUrl ?>?p=menu1">Menu1</a>
<a href="<?= appUrl ?>?p=menu2">Menu2</a>
</nav>
</body>
</html>
Menu2.html:2つ目の画面
<!DOCTYPE html>
<html lang="ja">
<head>
<base target="_top">
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>body{font:18px/1.7 sans-serif;margin:2rem;max-width:42rem}nav{display:flex;gap:1rem;flex-wrap:wrap}a{padding:.5rem;border:1px solid #2768af;border-radius:4px;color:#14569b}a:focus-visible{outline:3px solid #e09319;outline-offset:3px}</style>
</head>
<body>
<h1>Menu2ページ</h1>
<p>2番目の練習画面です。トップまたはMenu1へ移動できます。</p>
<nav aria-label="練習ページ">
<a href="<?= appUrl ?>?p=index">トップ</a>
<a href="<?= appUrl ?>?p=menu1">Menu1</a>
<a href="<?= appUrl ?>?p=menu2">Menu2</a>
</nav>
</body>
</html>
4ファイルと模擬テストをダウンロードできます。
記事中のHTMLは表示用のコードなので、WordPressの記事内で実行せず、Apps ScriptのHTMLファイルへ貼り付けます。
template.appUrlにWebアプリのURLを渡し、evaluateでHTMLを生成します。
通常のHTMLファイル出力とテンプレートの評価を混同しないでください。
公式のHTMLテンプレート仕様を参照してください。
リンクはWebアプリのURLと?p=を組み合わせ、base target=”_top”を設定します。
Apps ScriptのHTMLはIFRAME内で表示されるため、単に相対URLだけを指定する構成とは区別します。
HTMLサービスの制限も確認してください。
自分専用のデプロイで動かす
4ファイルを保存し、「デプロイ→新しいデプロイ」で種類を「ウェブアプリ」にします。
練習では実行者を自分、アクセスできるユーザーを「自分のみ」にしてデプロイします。
表示されたWebアプリの/execで終わるURLを開き、Indexページが表示されることを確認します。
エディタの実行ボタンでdoGetを動かす方法と、ブラウザーでWebアプリのURLを開く方法を区別してください。
初回デプロイ後は「デプロイ→デプロイをテスト」で/devのテストURLを取得できます。
テストURLは編集権限を持つ人向けで、保存した最新コードを使います。
/execはデプロイしたバージョンを使うため、コードの保存だけではそのバージョンに更新されません。
ScriptApp.getService().getUrlは、テスト環境から呼び出した場合はテスト用URLを返します。
デプロイ前はURLが取得できない場合があるため、エディタでの手動実行を表示確認の代わりにしないでください。
Service.getUrlの公式仕様を参照してください。

遷移とエラーを確認する
| 条件 | 結果 |
|---|---|
| URLにpなし、または?p=index | Indexページ |
| ?p=menu1 | Menu1ページ |
| ?p=menu2 | Menu2ページ |
| ?p=unknown、またはpを重複指定 | 該当するページがありません |
トップからMenu1、Menu2へ移動し、トップへ戻れるか確認します。
Tabキーでリンクを選び、Enterキーでも同じページへ進めることを確認してください。
旧版ではMenu1のリンク先やMenu2の見出しに取り違えがありました。
本例ではリンクの表示名、pの値、HTMLの見出しを対応させています。
| 条件 | 結果 |
|---|---|
| doGetが見つからない | Code.gsにJavaScriptを貼り、関数名を確認する |
| HTMLファイルが見つからない | Index・Menu1・Menu2の名前と大文字小文字を確認する |
| 画面が変わらない | devとexec、保存中のコードとデプロイ済みバージョンを確認する |
| リンクが別のフレームに開く | base targetとテンプレートのappUrlを確認する |
| 変更を戻したい | 変更前の4ファイルへ戻し、execを使う場合はデプロイ設定のバージョンも確認する |
ページ遷移のためにXFrameOptionsMode.ALLOWALLを設定する必要はありません。
外部ページへの埋め込みを許可する話と、このWebアプリ内のページ切り替えは別に判断します。
実サービスで確認した範囲
2026年10月3日に、自分専用のWebアプリで3つの画面、トップへの戻り、未知のpのエラー、Enterでの遷移を確認しました。
devのリンクが同じテスト用URLを使うことも確認しています。
この4ファイルはDriveやGmailのデータを読みません。
不特定多数への公開、別アカウントでの利用、外部iframeの埋め込みは試していません。
他の自動化はGoogleの目的別ガイドから確認できます。
さらに学びたい・環境を整えたい方へ
この記事の手順を試したあと、スプレッドシートやGASを体系的に学びたい方に向けた参考書です。
必要なテーマが目次に含まれるか確認して選んでください。
関連記事と旧資料
関連記事は目的が合うものから確認してください。
旧資料や外部ツールの説明は、本稿の練習コード・検証範囲と異なる場合があります。




