こんな時におすすめ
以下のように、実装したい時に検討してみてください!
- WordPress管理画面で、ダウンロードファイルを設定したい。
- 投稿ページのフォームの完了ページに、ダウンロードボタンを表示させたい。(そのボタンは投稿ごとに変えたい)
「固定ページにカスタムフィールドを設置して、フォーム完了ページにダウンロードボタンを実装したい」方は、こちらの記事を参考にしてください。

完成イメージ
ボタンを押すと、ボタンの下にダウンロードのローダー(くるくるするアニメーション)も出てきます。
カスタムフィールドに何も設定されていないと、ボタンは表示されない仕組みです。
実装方法
以下の想定でご紹介します。ご自分で使用する際はアレンジしてお使いください!
- カスタム投稿タイプ(dounload)の記事に、「Contact Form 7のフォーム」を設置。
- 「送信ボタン」をクリックすると、「完了ページ(ディレクトリ名:document-complete)にリダイレクト」。
その時に「パラメーターに記事IDをつける」。
※記事IDをパラメータにつけることで、その記事の「カスタムフィールドの値を引っ張ってくる」ことができます。 - 完了ページに「ボタン」を設置。クリックすると、ポップアップは起動せずにファイルをダウンロードする。
- 1. 完了ページはあらかじめ、固定ページ(ディレクトリ名はdocument-complete)で作成しておきます。
- 2. 完了ページにパラメータをつけた時、URLはこのようになります。
例:https://hogehoge.com/document-complete?post_id=447
この記事では、「Google Driveのファイル(共有URLを使用)」「WordPressにアップロードしたファイル」の2つの方法もご紹介しております。
ご自分が使用する方を参考にしてくださいね。
1. カスタムフィールド Advanced Custom Fields(ACF)を作成
「Google Driveのファイル」と「WordPressにアップロードしたファイル」でACFの設定が変わります。
Google Driveのファイル(共有URL)を使いたい場合
Google Driveの共有URLをクリックすると、普通はGoogle Driveのページが表示されるのですが、
ご紹介する方法では、そのページの表示なしで直接PDFをダウンロードできるようになります。
管理画面での実装イメージ

Advanced Custom Fields(ACF)の設定画面
- フィールドタイプ:URL
- フィールドラベル(任意):
例:資料請求完了ページに載せる、Google Driveの共有URLを入れてください。 - フィールド名(任意):document_download_url

WordPressにアップロードしたファイルを使いたい場合
PDFを想定しています。(WordやExcelも使えるかもしれませんので、テストしてみてください。)
管理画面での実装イメージ

Advanced Custom Fields(ACF)の設定画面
- フィールドタイプ:ファイル
- フィールドラベル(任意):
例:資料請求完了ページに載せる、PDFをアップロードしてください。 - フィールド名(任意):document_file
- 返り値:ファイル配列

2. Contact Form 7独自のショートコードを作成
Contact Form 7に「現在の投稿IDをhiddenフィールドの値(value)にセット」するために、独自のショートコードを作成します。
functions.phpに以下のコードを作成
/**
* Contact Form 7で独自のショートコードを設定
* そのショートコードを使って、現在の投稿IDをhiddenフィールドの値に出力(documentのみ)
* Contact Form 7内に、[post_id your-post-id] を設置。
* 参考サイト:https://rishuntrading.co.jp/blog/wordpress/call_shortcode_in_contactform7/
* wpcf7_add_shortcode の使用は Contact Form 7 バージョン 4.6 から非推奨になったので、wpcf7_add_form_tagに変更。
* 【ショートコード作成の注意点】
* 以下のようにすると、文字列として出力されてしまう。
* ※1 ショートコードは小文字にする。大文字は×。
* ※2 カッコを入れ子に使用できない。例:[hidden your-post-id "[post_id]"]
*/
function cf7_post_id_form_tag_handler($tag) {
if (!is_singular('document')) { // カスタム投稿(document)のみ.
return ''; // 投稿ページまたは固定ページ以外では空を返す.
}
global $post;
$post_id = $post->ID;
$html = sprintf('<input type="hidden" name="%s" value="%s">', esc_attr($tag->name), esc_attr($post_id));
return $html;
}
wpcf7_add_form_tag('post_id', 'cf7_post_id_form_tag_handler', ['name-attr' => true]); // Contact Form 7用のショートコードを追加
3. Contact Form 7の管理画面でショートコードを入れる
<div>[post_id your-post-id]</div>
独自で作ったショートコードに何もタグを囲っていないと、勝手にpタグで囲んでしまうので、
ショートコードをdivタグで囲んでください。
(pタグにCSSが設定されていることが多く、この部分が思わぬ余白として出てしまうのを防ぐためです)
フォームが出力されると、このショートコードはinputタグのtype=”hidden”になります。
なので表示はされないですが、pタグは勝手についちゃいます。
このせいでフォームが崩れる場合は、divタグにclassをつけるなどして、対応してください。
<div>
<p><input type="hidden" name="your-post-id" value="447"></p>
</div>
4. Contact Form 7 送信完了ページに投稿IDを渡しつつ、JavaScriptでリダイレクトする
先ほどのショートコードで設定した、hiddenフィールドの値(value)に投稿IDが入っています。
それを送信完了ページにリダイレクトする時に、投稿IDをパラメータとして付与します。
完了ページのURL例:https://hogehoge.com/document-complete?post_id=447
※447が記事IDになります。
方法は2通りあります。
方法1:JavaScriptファイルに書き込む
「特定のフォームのみに、特定のJavaScriptファイルを読み込むようにしている」場合、こちらを使ってください。
例えば、Contact Form 7のフォームを2種類以上使っている(もう一方はこの記事の仕組みを使わない)」の時に便利です。
// Contact Form 7 送信完了ページにpost_idを渡しつつ、JavaScriptでリダイレクトする(お役立ち資料のみ)-----------
// functions.php内に、独自のショートコード[post_id your-post-id]を設置しています。
document.addEventListener(
"wpcf7mailsent",
function (event) {
var inputs = event.detail.inputs;
var postId;
//inputsはフォーム内全ての入力フィールド(input, select, textareaなど)が入っている
inputs.forEach(function (input) {
if (input.name === "your-post-id") {
postId = input.value; // フォーム内にhiddenに設定した、name="your-post-id"のvalue(現在の投稿ID)を取得.
}
});
// サンクスページにリダイレクト。その時に、クエリパラメータとして現在の投稿IDを渡す.
// locationオブジェクトはグローバルオブジェクトなので、変数の宣言はいらない。
location = "/document-complete/?post_id=" + postId;
},
false
);
方法2:functions.phpに書き込む
方法1が使えない場合は、functions.phpにて条件分岐で該当するページだけ設置する方法もあります。
(フォームを1種類しか使っていない場合も、今後フォームを増やす可能性があるので、条件分岐を設定するをおすすめします。)
/**
* Contact Form 7 送信完了ページにpost_idを渡しつつ、JavaScriptでリダイレクトする(documentのみ)
* functions.php内に、独自のショートコード[post_id your-post-id]を設置しています。
* ここに書くと全ページに適用されるので、特定のページのみに適用する
*/
add_action('wp_footer', 'custom_redirect_for_specific_form');
function custom_redirect_for_specific_form() {
if (is_singular('document')) { // カスタム投稿(document)のみ.
?>
<script type="text/javascript">
document.addEventListener(
"wpcf7mailsent",
function (event) {
var inputs = event.detail.inputs;
var postId;
//inputsはフォーム内全ての入力フィールド(input, select, textareaなど)が入っている
inputs.forEach(function (input) {
if (input.name === "your-post-id") {
postId = input.value; // フォーム内にhiddenに設定した、name="your-post-id"のvalue(現在の投稿ID)を取得.
}
});
// サンクスページにリダイレクト。その時に、クエリパラメータとして現在の投稿IDを渡す.
// locationオブジェクトはグローバルオブジェクトなので、変数の宣言はいらない。
location = "/document-complete/?post_id=" + postId;
},
false
);
</script>
<?php
}
}
5. 完了ページ(page-document-complete.php)の設定
PHP, HTML, Javascriptの部分
「Google Driveのファイル」と「WordPressにアップロードしたファイル」でPHPが変わります。
カスタムフィールドに何も設定されていないと、ボタンは表示されない仕組みです。
どちらも固定ページのPHP(今回は、page-document-complete.php)に記入します。
Google Driveのファイルの場合
<?php // 投稿IDを取得
if(isset($_GET['post_id'])) :
// クエリパラメータから投稿IDを整数として安全に取得
$post_id = intval($_GET['post_id']);
// ACFの値に入った、Google Driveの共有URLを取得
$shared_url = get_field('document_download_url', $post_id);
// Google Driveの共有URLからFILE_IDを抽出
//(/d/ から次の / までにある番号がFILE_ID。
// 例:https://drive.google.com/file/d/1A2B3C4D5E6F7G8H9I/view?usp=sharing")
preg_match('/\/d\/(.+?)\//', $shared_url, $matches);
$file_id = $matches[1] ?? '';
// ダウンロードリンクを作成
$download_link = "https://drive.google.com/uc?export=download&id=" . $file_id;
?>
<!-- ダウンロードボタンのHTML -->
<p class="c-btn-ellipse c-btn-ellipse--download p-complete__download-btn">
<button class="js-download-btn">資料ダウンロード</button>
<span class="loader js-loader"></span>
</p>
<!-- ダウンロード機能を実装するJavaScript -->
<script>
document.addEventListener('DOMContentLoaded', function() {
const btn = document.querySelector('.js-download-btn');
const loader = document.querySelector('.js-loader');
btn.addEventListener('click', () => {
// ローダーを表示
loader.style.display = 'block';
// 一時的なダウンロードリンクを作成
const element = document.createElement('a');
// esc_urlなどの無害化をすると、Googleのエラーが出るのでしない。
element.href = '<?php echo $download_link; ?>';
// PDF名は仮で設定。(ダウンロード時にGoogle Driveのファイル名に置き換わります。)
element.download = 'downloaded_document.pdf';
// ダウンロードリンクをクリック。ダウンロードを実行する
element.click();
// 一定時間後にローダーを非表示
setTimeout(function() {
loader.style.display = 'none';
}, 6000); // 6秒後にローダーを非表示にする(適宜調整)
}, false);
});
</script>
<?php endif; ?>
WordPressにアップロードしたファイルの場合
<?php
// ACFを使用したファイルダウンロード機能
// URLパラメータから投稿IDを取得
if(isset($_GET['post_id'])) :
// GETパラメータから投稿IDを整数として安全に取得
$post_id = intval($_GET['post_id']);
// ACFフィールド 'document_file' から文書ファイルの情報を取得
$document_file = get_field('document_file', $post_id);
// ファイル情報が存在し、配列形式であることを確認
if($document_file && is_array($document_file)) :
// ファイルのURLと元のファイル名を取得
$document_download_url = $document_file['url'];
$document_filename = $document_file['filename'];
// ファイルの内容を取得する関数
function get_file_contents($url) {
if (function_exists('curl_init')) {
// cURLが利用可能な場合、cURLを使用してファイルを取得
// cURLとは様々なプロトコルをサポートしているライブラリ。Local by Flywheelでも使用でき、file_get_contents()よりも高速。
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$file_contents = curl_exec($ch);
curl_close($ch);
return $file_contents;
} else {
// cURLが利用できない場合、file_get_contents()を使用
return file_get_contents($url);
}
}
// ファイルの内容を取得
$file_contents = get_file_contents($document_download_url);
if ($file_contents !== false) {
// ファイルの内容をBase64エンコード
$document_download_url_base64_url = base64_encode($file_contents);
?>
<!-- ダウンロードボタンのHTML -->
<p class="c-btn-ellipse">
<button class="js-download-btn">資料ダウンロード</button>
<span class="c-btn-ellipse__loader js-loader"></span>
</p>
<!-- ダウンロード機能を実装するJavaScript -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// ダウンロードボタンの要素を取得
const btn = document.querySelector('.js-download-btn');
// ボタンクリックイベントのリスナーを追加
btn.addEventListener('click', () => {
// 一時的なa要素を作成
let element = document.createElement('a');
// Base64エンコードされたファイルデータをhref属性に設定
// 'data:application/pdf;base64,' は、ブラウザにこれがBase64エンコードされたPDFであることを伝える
element.href = 'data:application/pdf;base64,<?php echo $document_download_url_base64_url; ?>';
// ダウンロードするファイル名を設定
element.download = '<?php echo $document_filename; ?>';
// a要素のクリックイベントをプログラムから発火
element.click();
}, false);
});
</script>
<?php
} else {
// ファイルの取得に失敗した場合、エラーをログに記録
error_log("Failed to retrieve file contents: " . $document_download_url);
}
endif;
endif;
?>
CSSの部分
HTMLの構造とclass名はこのようにしています。
<p class="c-btn-ellipse">
<!-- ↓ボタン部分 -->
<button class="c-btn-ellipse__link js-download-btn">資料ダウンロード</button>
<!-- ↓ローダー部分 -->
<span class="c-btn-ellipse__loader js-loader"></span>
</p>
CSSはこれを叩き台にカスタマイズしてください。
.c-btn-ellipse{
position: relative; //ローダーを固定する
// ボタン部分--------------
&__link {
background-color: #007eff;
color: #fff;
position: relative;
padding: 0.8em 0.8em 0.8em 0.6em;
font-size: 1.5rem;
font-weight: 600;
line-height: 0.0666666667;
// ボタンのアイコン部分
&:before {
content: "";
display: inline-block;
margin-right: 0.5em;
width: 1em;
height: 1em;
background: url("アイコンのURL") no-repeat center center / contain;
transition: all 0.3s;
}
}
//ローダー部分---------------
&__loader {
// ローダーの位置
position: absolute; //ボタンの下に表示するようにする
bottom: -25px; //ボタンの下に表示するようにする
left: 0;
right: 0;
margin: 0 auto;
display: none; //最初は非表示
// ローダーのデザイン・アニメーション
width: 10px;
padding: 8px;
aspect-ratio: 1;
border-radius: 50%;
background: #007eff;
--_m: conic-gradient(#0000 10%, #000),
linear-gradient(#000 0 0) content-box;
-webkit-mask: var(--_m);
mask: var(--_m);
-webkit-mask-composite: source-out;
mask-composite: subtract;
animation: l3 1s infinite linear;
}
}
注意点
- ファイル名は、「半角英数字」にするようにしてください。
Google Driveファイル名が日本語の時、Safariでダウンロードした時にファイル名が文字化けしました。
他のブラウザでも文字化けしかねないので、ファイル名は半角英数字にするようにしましょう。
(WordPressにアップロードするファイルには、対策として「WP Multibyte Patch」というプラグインを入れておくと、日本語の全角文字(マルチバイト文字)を自動的に半角英数字(1バイト文字)に変換してくれます。) - ダウンロードするファイルの重さですが、あまり重いサイズは設定しないようにしましょう。
(軽ければ軽いに越したことはありません。目安として20MG未満にした方が良さそうです。)
コメント
コメント一覧 (1件)
[…] あわせて読みたい 投稿画面にカスタムフィールドを設置し、フォーム完了ページにダウンロードボタンを実装したい 【こんな時におすすめ】 以下のように、実装したい時に検討し […]