1. スニペットを貼る
生成されたコードを、すべてのページで閉じるbodyタグの直前に置きます。依存関係はなく、ネットワークリクエストも増えません。
無料ツール
Cookieのカテゴリを選び、文言を書き、見た目を選ぶだけで、どのサイトにも貼り付けられる依存関係なしの同意バナーをコピーできます。訪問者の選択を保存し、タグ付けしたスクリプトはカテゴリが許可されるまでブロックし、フッターのリンクから再表示もできます。
あなたの同意バナー
すべてのページで、閉じるbodyタグの直前に貼り付けてください。
<!-- Cookie consent banner - paste this just before </body> -->
<script>
(function () {
var CFG = {
"storageKey": "cookie_consent",
"position": "bar",
"theme": "light",
"accent": "#a6144d",
"title": "Cookieを使用しています",
"message": "当サイトの運営、利用状況の把握、改善のためにCookieを使用しています。すべて許可する、任意のものを拒否する、カテゴリごとに選ぶ、のいずれも可能です。",
"policyUrl": "https://example.com/privacy",
"policyLabel": "プライバシーポリシーを読む",
"accept": "すべて許可",
"reject": "任意を拒否",
"prefs": "設定",
"save": "選択を保存",
"categories": [
{
"id": "necessary",
"label": "必須",
"desc": "サイトの動作に必要です。常に有効で、同意を求めません。",
"required": true
},
{
"id": "analytics",
"label": "分析",
"desc": "サイトの利用状況を計測し、改善に役立てます。",
"required": false
},
{
"id": "marketing",
"label": "マーケティング",
"desc": "広告のパーソナライズとキャンペーンの計測に使用します。",
"required": false
}
]
};
var KEY = CFG.storageKey;
var doc = document;
var box = null;
function read() {
try { return JSON.parse(localStorage.getItem(KEY) || 'null'); } catch (e) { return null; }
}
function save(consent) {
consent.necessary = true;
consent.date = new Date().toISOString();
try { localStorage.setItem(KEY, JSON.stringify(consent)); } catch (e) {}
unblock(consent);
window.dispatchEvent(new CustomEvent('consentchange', { detail: consent }));
if (typeof window.onConsentChange === 'function') window.onConsentChange(consent);
}
// Scripts the site parked behind a category run only once it is granted. Park
// one by giving its tag type="text/plain" and data-consent="analytics".
// (Deliberately described, not shown: a literal script tag written out here
// would close this one early and truncate everything below it.)
function unblock(consent) {
var parked = doc.querySelectorAll('script[type="text/plain"][data-consent]');
for (var i = 0; i < parked.length; i++) {
var old = parked[i];
if (!consent[old.getAttribute('data-consent')]) continue;
var next = doc.createElement('script');
for (var a = 0; a < old.attributes.length; a++) {
var at = old.attributes[a];
if (at.name !== 'type' && at.name !== 'data-consent') next.setAttribute(at.name, at.value);
}
next.text = old.text;
old.parentNode.replaceChild(next, old);
}
}
function styles() {
var dark = CFG.theme === 'dark';
var bg = dark ? '#161622' : '#ffffff';
var fg = dark ? '#f4f4f8' : '#141a47';
var muted = dark ? 'rgba(244,244,248,.72)' : 'rgba(20,26,71,.7)';
var line = dark ? 'rgba(255,255,255,.14)' : 'rgba(20,26,71,.12)';
var el = doc.createElement('style');
el.textContent = [
'.cc-root{position:fixed;z-index:2147483000;font:400 14px/1.55 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:' + fg + ';box-sizing:border-box}',
'.cc-root *,.cc-root *::before,.cc-root *::after{box-sizing:inherit}',
'.cc-card{background:' + bg + ';border:1px solid ' + line + ';box-shadow:0 18px 48px rgba(0,0,0,.18);border-radius:14px;padding:20px}',
'.cc-bar{left:0;right:0;bottom:0;padding:16px}',
'.cc-bar .cc-card{display:flex;flex-wrap:wrap;gap:16px;align-items:center;justify-content:space-between;max-width:1120px;margin:0 auto}',
'.cc-box{left:16px;bottom:16px;max-width:400px}',
'.cc-modal{inset:0;display:flex;align-items:center;justify-content:center;padding:16px;background:rgba(10,10,20,.5)}',
'.cc-modal .cc-card{max-width:520px;width:100%}',
'.cc-title{margin:0 0 6px;font-size:16px;font-weight:700}',
'.cc-text{margin:0;color:' + muted + '}',
'.cc-text a{color:' + CFG.accent + ';font-weight:600}',
'.cc-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}',
'.cc-bar .cc-actions{margin-top:0}',
'.cc-btn{appearance:none;cursor:pointer;border:1px solid ' + line + ';border-radius:999px;padding:9px 18px;font:600 14px inherit;background:transparent;color:' + fg + '}',
'.cc-btn-main{background:' + CFG.accent + ';border-color:' + CFG.accent + ';color:#fff}',
'.cc-btn:focus-visible{outline:2px solid ' + CFG.accent + ';outline-offset:2px}',
'.cc-cats{display:none;margin:14px 0 0;padding:14px 0 0;border-top:1px solid ' + line + '}',
'.cc-cats.cc-open{display:block}',
'.cc-cat{display:flex;gap:10px;align-items:flex-start;margin-bottom:12px}',
'.cc-cat input{margin:3px 0 0;accent-color:' + CFG.accent + '}',
'.cc-cat strong{display:block;font-size:14px}',
'.cc-cat span{display:block;color:' + muted + ';font-size:13px}',
'@media(max-width:640px){.cc-bar .cc-card{display:block}.cc-bar .cc-actions{margin-top:14px}.cc-btn{flex:1 1 auto}}'
].join('');
doc.head.appendChild(el);
}
function build() {
var stored = read() || {};
var root = doc.createElement('div');
root.className = 'cc-root cc-' + CFG.position;
root.setAttribute('role', CFG.position === 'modal' ? 'dialog' : 'region');
root.setAttribute('aria-label', CFG.title);
if (CFG.position === 'modal') root.setAttribute('aria-modal', 'true');
var card = doc.createElement('div');
card.className = 'cc-card';
var copy = doc.createElement('div');
var h = doc.createElement('p');
h.className = 'cc-title';
h.textContent = CFG.title;
var p = doc.createElement('p');
p.className = 'cc-text';
p.textContent = CFG.message + ' ';
if (CFG.policyUrl) {
var link = doc.createElement('a');
link.href = CFG.policyUrl;
link.textContent = CFG.policyLabel;
p.appendChild(link);
}
copy.appendChild(h);
copy.appendChild(p);
var cats = doc.createElement('div');
cats.className = 'cc-cats';
var inputs = {};
for (var i = 0; i < CFG.categories.length; i++) {
var c = CFG.categories[i];
var row = doc.createElement('label');
row.className = 'cc-cat';
var cb = doc.createElement('input');
cb.type = 'checkbox';
cb.checked = c.required || stored[c.id] === true;
cb.disabled = !!c.required;
var txt = doc.createElement('div');
var name = doc.createElement('strong');
name.textContent = c.label;
var desc = doc.createElement('span');
desc.textContent = c.desc;
txt.appendChild(name);
txt.appendChild(desc);
row.appendChild(cb);
row.appendChild(txt);
cats.appendChild(row);
inputs[c.id] = cb;
}
copy.appendChild(cats);
var actions = doc.createElement('div');
actions.className = 'cc-actions';
function button(label, main, onClick) {
var b = doc.createElement('button');
b.type = 'button';
b.className = 'cc-btn' + (main ? ' cc-btn-main' : '');
b.textContent = label;
b.addEventListener('click', onClick);
actions.appendChild(b);
return b;
}
function decide(granted) {
var consent = {};
for (var i = 0; i < CFG.categories.length; i++) {
var c = CFG.categories[i];
consent[c.id] = c.required ? true : granted === null ? !!inputs[c.id].checked : granted;
}
save(consent);
close();
}
var prefsBtn = button(CFG.prefs, false, function () {
var open = cats.classList.toggle('cc-open');
prefsBtn.setAttribute('aria-expanded', open ? 'true' : 'false');
saveBtn.style.display = open ? '' : 'none';
});
prefsBtn.setAttribute('aria-expanded', 'false');
button(CFG.reject, false, function () { decide(false); });
button(CFG.accept, true, function () { decide(true); });
var saveBtn = button(CFG.save, false, function () { decide(null); });
saveBtn.style.display = 'none';
card.appendChild(copy);
card.appendChild(actions);
root.appendChild(card);
doc.body.appendChild(root);
box = root;
}
function close() {
if (box && box.parentNode) box.parentNode.removeChild(box);
box = null;
}
function open() {
if (!box) build();
}
function start() {
styles();
var stored = read();
if (stored) unblock(stored);
else build();
window.showConsentPreferences = open;
}
if (doc.readyState === 'loading') doc.addEventListener('DOMContentLoaded', start);
else start();
})();
</script> 使い方
生成されたコードを、すべてのページで閉じるbodyタグの直前に置きます。依存関係はなく、ネットワークリクエストも増えません。
トラッキングタグのtypeをtext/plainに変え、data-consent="analytics"を追加します。バナーはそのカテゴリが許可された瞬間に実行し、それ以前には決して実行しません。
window.showConsentPreferences()を呼び出すリンクをフッターに追加すれば、訪問者はパネルを開き直せます。選択のたびにconsentchangeイベントも発火するので、購読できます。
よくある質問
規制当局が求める仕組みは備えています。同意前に任意のCookieを置かない、拒否を許可と同じ手軽さにする、カテゴリごとに選べる、後から変更できる、という点です。ただし準拠は実際に何を実行しているか、ポリシーに何を書いているか、訪問者がどこにいるかにも左右されます。生成されたコードは法的助言ではなく、確かな出発点として扱ってください。
スクリプトタグに type="text/plain" と、カテゴリ名を指定した data-consent 属性を付けます。ブラウザはそれを実行せず、そのカテゴリが許可された時点でバナーが本物のスクリプトタグに書き換えます。今回の訪問でも、保存された選択に基づく次回の訪問でも同様です。
指定したキーのlocalStorageに、カテゴリごとのフラグと日付を持つ小さなJSONとして保存されます。バナー自体はCookieを設定せず、サーバーにも何も送らないため、完全な静的サイトでも動作します。
はい。表示位置、テーマ、アクセントカラーはここで選べます。生成されるCSSの要素はすべてcc-で始まるため、スニペットに手を加えずに自分のスタイルシートから上書きできます。
カテゴリが少ない1サイトなら、このスニペットで十分なことがほとんどです。同意ログ、複数ドメイン、選択を自動的に尊重する分析が必要になったら、PulsePandaに組み込まれた同意マネージャーがまるごと引き受けます。
関連
PulsePandaには同意マネージャーが標準搭載。既定でCookieを使わず、オプトアウトされた瞬間に収集を停止します。2つ目のベンダーも、つなぎのコードも不要です。
無料で始める