メインコンテンツまでスキップ

会員情報登録フォームのカスタマイズ

このページでは、会員情報登録フォーム向けのカスタマイズTipsを順次追加していきます。ファイル名は onboarding.cssonboarding.js を前提とします。

⚠️ コードはあくまでサンプルです。設定しているフォームのメタフィールドの定義、テキストなどに応じて適宜変更ください。

カスタムCSS, JS

プライバシーポリシーをモーダルで表示する

外部リンクではなく、プライバシーポリシーのリンクを押した時にモーダルを開くサンプルです。表示文言は、メインは日本語、それ以外の言語は英語で切り替えています。

onboarding.js
function createPrivacyModal() {
if (document.getElementById("alcms-privacy-modal")) return;

const modal = document.createElement("div");
modal.id = "alcms-privacy-modal";
modal.className = "alcms-modal";
modal.setAttribute("aria-hidden", "true");

modal.innerHTML = `
<div class="alcms-modal__overlay" data-alcms-modal-close></div>

<div class="alcms-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="alcms-privacy-modal-title">
<button type="button" class="alcms-modal__close" aria-label="Close" data-alcms-modal-close>
×
</button>

<h2 id="alcms-privacy-modal-title" class="alcms-modal__title">
Privacy Policy
</h2>

<div class="alcms-modal__body">
<p>
This is a sample privacy policy text.
</p>
<p>
We collect and use your information only for the purpose of providing this service.
Your personal information will be handled appropriately in accordance with applicable laws and regulations.
</p>
<p>
プライバシーポリシーのダミーテキストです。
取得した情報は、サービス提供およびお客様対応のために適切に利用されます。
</p>
</div>

<div class="alcms-modal__footer">
<button type="button" class="alcms-modal__button" data-alcms-modal-close>
Close
</button>
</div>
</div>
`;

document.body.appendChild(modal);

modal.addEventListener("click", (event) => {
if (event.target.matches("[data-alcms-modal-close]")) {
closePrivacyModal();
}
});

document.addEventListener("keydown", (event) => {
if (event.key === "Escape") {
closePrivacyModal();
}
});
}

function openPrivacyModal() {
createPrivacyModal();

const modal = document.getElementById("alcms-privacy-modal");
if (!modal) return;

modal.classList.add("is-open");
modal.setAttribute("aria-hidden", "false");
document.body.classList.add("alcms-modal-open");
}

function closePrivacyModal() {
const modal = document.getElementById("alcms-privacy-modal");
if (!modal) return;

modal.classList.remove("is-open");
modal.setAttribute("aria-hidden", "true");
document.body.classList.remove("alcms-modal-open");
}

function updatePrivacyLabel() {
const privacyCheckbox = document.querySelector(
'input[name="metafield[custom.privacy_policy_consent]"]',
);

if (!privacyCheckbox) return;

const label = privacyCheckbox.closest("label");
if (!label) return;

const params = new URLSearchParams(window.location.search);
const locale = (params.get("locale") || "").toLowerCase();
const htmlLang = (document.documentElement.lang || "").toLowerCase();

const isJapanese = locale === "ja" || htmlLang.startsWith("ja");

label.innerHTML = "";
label.appendChild(privacyCheckbox);

const link = document.createElement("a");
link.href = "#alcms-privacy-modal";
link.style.textDecoration = "underline";

link.addEventListener("click", (event) => {
event.preventDefault();
openPrivacyModal();
});

if (isJapanese) {
link.textContent = " プライバシーポリシー";
label.appendChild(link);
label.appendChild(document.createTextNode(" に同意する"));
} else {
label.appendChild(document.createTextNode(" I agree to the "));
link.textContent = "Privacy Policy";
label.appendChild(link);
}

const requiredSpan = document.createElement("span");
requiredSpan.className = "required";
requiredSpan.textContent = " *";
requiredSpan.style.color = "red";
label.appendChild(requiredSpan);
}

document.addEventListener("DOMContentLoaded", () => {
updatePrivacyLabel();
createPrivacyModal();
});
onboarding.css
.alcms-modal {
display: none;
position: fixed;
inset: 0;
z-index: 9999;
}

.alcms-modal.is-open {
display: block;
}

.alcms-modal__overlay {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.5);
}

.alcms-modal__dialog {
position: relative;
width: calc(100% - 32px);
max-width: 640px;
max-height: calc(100vh - 80px);
margin: 40px auto;
padding: 24px;
background: #fff;
border-radius: 12px;
overflow-y: auto;
box-sizing: border-box;
}

.alcms-modal__close {
position: absolute;
top: 12px;
right: 16px;
border: none;
background: transparent;
font-size: 28px;
line-height: 1;
cursor: pointer;
}

.alcms-modal__title {
margin: 0 32px 16px 0;
font-size: 20px;
line-height: 1.4;
}

.alcms-modal__body {
font-size: 14px;
line-height: 1.7;
}

.alcms-modal__footer {
margin-top: 24px;
text-align: right;
}

.alcms-modal__button {
padding: 10px 18px;
border: 1px solid #222;
border-radius: 6px;
background: #222;
color: #fff;
cursor: pointer;
}

.alcms-modal-open {
overflow: hidden;
}

姓名カナを1行2列で表示する

onboarding.js
function wrapKanaFields() {
const lastNameKanaField = document
.querySelector(
'input[name="metafield[姓(カナ)を取得するメタフィールドのnamespace.key]"]',
)
?.closest(".alcms-field");

const firstNameKanaField = document
.querySelector(
'input[name="metafield[名(カナ)を取得するメタフィールドのnamespace.key]"]',
)
?.closest(".alcms-field");

if (!lastNameKanaField || !firstNameKanaField) return;

const parent = lastNameKanaField.parentElement;
if (!parent) return;

if (parent.classList.contains("alcms-field-group--kana")) return;

const wrapper = document.createElement("div");
wrapper.className = "alcms-field-group alcms-field-group--kana";

parent.insertBefore(wrapper, lastNameKanaField);
wrapper.appendChild(lastNameKanaField);
wrapper.appendChild(firstNameKanaField);
}

document.addEventListener("DOMContentLoaded", () => {
wrapKanaFields();
});
onboarding.css
.alcms-field-group--kana {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
margin-bottom: 1rem;
}

.alcms-field-group--kana .alcms-field {
margin: 0;
min-width: 0;
}

.alcms-field-group--kana .alcms-field__input {
width: 100%;
box-sizing: border-box;
}