feat: Add Privacy Policy acceptance to contact form and client-side validation to contact-form.js
This commit is contained in:
@@ -108,16 +108,37 @@ pageScripts:
|
||||
<fieldset class="message-field">
|
||||
<legend>Message</legend>
|
||||
<label for="message">Questions or Feedback</label>
|
||||
<textarea id="message" name="message" rows="15" placeholder="What questions or feedback do you have for me?" required aria-describedby="message-error"></textarea>
|
||||
<textarea id="message" name="message" rows="10" placeholder="What questions or feedback do you have for me?" required aria-describedby="message-error"></textarea>
|
||||
<span class="error-message" id="message-error" aria-live="polite"></span>
|
||||
</fieldset>
|
||||
|
||||
|
||||
<div class="checks">
|
||||
<div class="h-captcha" data-sitekey="b63e5b64-c6f2-4154-b5a6-77169a924022"></div>
|
||||
|
||||
<div id="privacy" class="privacy-checkbox">
|
||||
<div role="group" aria-labelledby="privacy-policy-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="privacy-policy"
|
||||
name="privacyPolicyAgreed"
|
||||
required
|
||||
aria-required="true"
|
||||
aria-describedby="privacy-policy-description"
|
||||
>
|
||||
<label id="privacy-policy-label" for="privacy-policy">
|
||||
I agree to the site's
|
||||
<a href="/privacy-policy" target="_blank" rel="noopener noreferrer">Privacy Policy</a>.<span classs="req-ask">*</span>
|
||||
</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="submit-reset">
|
||||
<button type="submit">Send Message</button>
|
||||
<button type="reset">Reset Form</button>
|
||||
</div>
|
||||
|
||||
<div class="h-captcha" data-sitekey="b63e5b64-c6f2-4154-b5a6-77169a924022"></div>
|
||||
|
||||
<div class="honeypot-field" aria-hidden="true">
|
||||
<label for="url">Website URL</label>
|
||||
|
@@ -11,7 +11,7 @@ isLandingPage: false
|
||||
|
||||
<strong>Last updated: August 25, 2025</strong>
|
||||
|
||||
<p>This Privacy Policy describes my policies and procedures on the collection and use of your information when you use my Service. I use your personal data to communicate with you regarding your inquiries.</p>
|
||||
<p>This <strong>Privacy Policy</strong> describes my policies and procedures on the collection and use of your information when you use my Service. I use your personal data to communicate with you regarding your inquiries.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
@@ -49,7 +49,7 @@ isLandingPage: false
|
||||
<section id="data-collection">
|
||||
<h2>What Information I Collect</h2>
|
||||
<p>I collect information that you voluntarily provide to me when you express an interest in obtaining information about my Services or otherwise contact me. The personal information I collect includes:</p>
|
||||
<ul>
|
||||
<ul class="data-collected">
|
||||
<li>First name and last name</li>
|
||||
<li>Phone number</li>
|
||||
<li>Email address</li>
|
||||
@@ -58,8 +58,8 @@ isLandingPage: false
|
||||
<li>Your message</li>
|
||||
</ul>
|
||||
<p>I may also collect certain technical information automatically, such as the date and time when a form is submitted, for the purpose of diagnostics and usage analysis.</p>
|
||||
<p class="highlight-statement">I do not collect any information from third parties.<br>
|
||||
I do not collect or process sensitive personal information.</p>
|
||||
<p class="highlight-statement"><strong>I do not collect any information from third parties.<br>
|
||||
I do not collect or process sensitive personal information.</strong></p>
|
||||
</section>
|
||||
<a class="back-to-top" href="./#top" aria-label="Back to top of page">Back to Top</a>
|
||||
|
||||
@@ -75,7 +75,7 @@ isLandingPage: false
|
||||
<li>To prevent spam or abuse</li>
|
||||
<li>To comply with legal obligations, if necessary</li>
|
||||
</ul>
|
||||
<p>I do not sell, rent, or share your personal information with any third parties. I may disclose information only when required by law (such as a subpoena or legal process).</p>
|
||||
<p><strong>I do not sell, rent, or share your personal information with any third parties.</strong> I may disclose information only when required by law (such as a subpoena or legal process).</p>
|
||||
</section>
|
||||
<section id="no-tracking">
|
||||
<h2>No Cookies or Tracking</h2>
|
||||
@@ -88,8 +88,8 @@ isLandingPage: false
|
||||
</section>
|
||||
<section id="data-protection">
|
||||
<h2>How I Protect Your Information</h2>
|
||||
<p>I have implemented reasonable technical and organizational security measures to protect your personal data. Your information is transmitted from the contact form using HTTPS encryption, which is enforced by default on this .dev domain.</p>
|
||||
<p>Submitted data undergoes multiple security checks to prevent spam and abuse, including the use of hCaptcha and rate limiting to verify the user is a human and minimize the risk of unauthorized access to stored data. The data is also validated and sanitized to ensure its integrity before it is stored in my database.</p>
|
||||
<p>I have implemented reasonable technical and organizational security measures to protect your personal data. Your information is transmitted from the contact form using <a href="https://developers.google.com/search/docs/crawling-indexing/https" target="_blank" rel="noopener noreferrer">HTTPS encryption</a>, which is enforced by default on this .dev domain.</p>
|
||||
<p>Submitted data undergoes multiple security checks to prevent spam and abuse, including the use of <a href="https://www.hcaptcha.com/" target="_blank" rel="noopener noreferrer">hCaptcha</a> and rate limiting to verify the user is a human and minimize the risk of unauthorized access to stored data. The data is also validated and sanitized to ensure its integrity before it is stored in my database.</p>
|
||||
<p>However, security is an ongoing practice, and no method of electronic transmission or storage is ever absolutely secure. While I strive to protect your data, I cannot guarantee its absolute security.</p>
|
||||
</section>
|
||||
<a class="back-to-top" href="./#top" aria-label="Back to top of page">Back to Top</a>
|
||||
@@ -117,6 +117,7 @@ isLandingPage: false
|
||||
<li>By email: <a href="mailto:contact@dlseitz.dev">contact@dlseitz.dev</a></li>
|
||||
<li>Or via the contact form on my website: <a href="https://dlseitz.dev/about/#contact" target="_blank" rel="noopener noreferrer">https://dlseitz.dev/about/#contact</a></li>
|
||||
</ul>
|
||||
<p>I aim to respond to all privacy-related requests within 5 business days.</p>
|
||||
</section>
|
||||
<a class="back-to-top" href="./#top" aria-label="Back to top of page">Back to Top</a>
|
||||
</div>
|
||||
|
@@ -52,11 +52,9 @@ form.addEventListener("submit", function(event) {
|
||||
const honeypotField = document.getElementById("url").value.trim();
|
||||
if (honeypotField.length > 0) {
|
||||
console.warn("Honeypot field was filled. Blocking submission.");
|
||||
// Fail silently to avoid alerting the bot.
|
||||
return;
|
||||
}
|
||||
|
||||
// Get values, including the hCaptcha response token
|
||||
const firstName = document.getElementById("first-name").value.trim();
|
||||
const lastName = document.getElementById("last-name").value.trim();
|
||||
const organization = document.getElementById("organization").value.trim();
|
||||
@@ -64,7 +62,8 @@ form.addEventListener("submit", function(event) {
|
||||
const phone = document.getElementById("phone").value.trim();
|
||||
const contactMethod = document.querySelector('input[name="contact-method"]:checked')?.value;
|
||||
const message = document.getElementById("message").value.trim();
|
||||
// Get the hCaptcha token from the global hcaptcha object
|
||||
const privacyAccepted = document.getElementById("privacy").checked;
|
||||
|
||||
let hasErrors = false;
|
||||
|
||||
// Validation logic...
|
||||
@@ -114,6 +113,11 @@ form.addEventListener("submit", function(event) {
|
||||
hasErrors = true;
|
||||
}
|
||||
|
||||
if (!privacyAccepted) {
|
||||
showMessage("Privacy Policy must be accepted before submitting.", true);
|
||||
hasErrors = true;
|
||||
}
|
||||
|
||||
|
||||
if (!hasErrors) {
|
||||
// Package the form data, including the hCaptcha token
|
||||
@@ -126,7 +130,8 @@ form.addEventListener("submit", function(event) {
|
||||
contactMethod: contactMethod,
|
||||
message: message,
|
||||
url: honeypotField,
|
||||
hCaptchaResponse: hCaptchaResponse // <-- THIS IS THE NEW PART
|
||||
hCaptchaResponse: hCaptchaResponse,
|
||||
privacyAccepted: privacyAccepted
|
||||
};
|
||||
|
||||
// Send the data to the backend using fetch()
|
||||
|
@@ -205,6 +205,19 @@ textarea:focus {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.checks {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.privacy-checkbox > div {
|
||||
display: flex;
|
||||
align-items: center; /* Vertically aligns items in the center */
|
||||
gap: 10px; /* Adds space between the checkbox and the text */
|
||||
}
|
||||
|
||||
/* Button */
|
||||
.submit-reset {
|
||||
display: flex;
|
||||
|
@@ -94,6 +94,12 @@ hr {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Correctly indents all other lists */
|
||||
#data-collection ul, #privacy-rights ul, #contact ul, #data-use ul {
|
||||
list-style: disc; /* Re-enable bullet points for all lists inside the module */
|
||||
padding-left: 20px; /* Indent the entire list */
|
||||
margin-left: 10px; /* Adds additional margin */
|
||||
}
|
||||
|
||||
.highlight-statement {
|
||||
color: var(--primary-color);
|
||||
|
Reference in New Issue
Block a user