Ecco una guida passo-passo per creare un “widget di prenotazione” (booking engine) di Octorate su un sito WordPress, utilizzando Contact Form 7 (CF7) e il plugin Custom CSS & JS.
1. Installazione dei plugin
1.1 Installare Contact Form 7
Accedi alla tua bacheca WordPress.
Vai su Plugin > Aggiungi nuovo.
Cerca Contact Form 7.
Clicca su Installa e poi su Attiva.
1.2 Installare Custom CSS & JS
Dalla bacheca di WordPress, vai su Plugin > Aggiungi nuovo.
Cerca Custom CSS & JS.
Clicca su Installa e poi su Attiva.
Questi due plugin saranno la base per creare e personalizzare il form che fungerà da “widget” per il booking engine.
2. Creazione del form in Contact Form 7
Vai su Contatti > Aggiungi nuovo (oppure modifica un form esistente).
Copia il seguente codice e incollalo nella scheda “Modulo” di CF7:
<div class="form-row form-row-dates">
<div class="form-column">
<label for="data-check-in">Data di arrivo:</label>
[date* data-check-in placeholder "Seleziona la data"]
</div>
<div class="form-column">
<label for="data-check-out">Data di partenza:</label>
[date* data-check-out placeholder "Seleziona la data"]
</div>
<div class="form-column">
<label for="numero-ospiti">Numero ospiti:</label>
[select* numero-ospiti "2" "1" "3" "4" "5" "6"]
</div>
</div>
<div class="form-row form-submit">
[submit class:secondary "Verifica disponibilità"]
</div>
Salva il form. Ora avrai a disposizione uno shortcode (ad esempio [contact-form-7 id="1234" title="Il mio form"]
). Copia questo shortcode e inseriscilo nella pagina (o nel widget) dove desideri che appaia il modulo di prenotazione.
3. Inserimento del CSS personalizzato
Dalla tua bacheca WordPress, vai su Custom CSS & JS (di solito trovi il menu in Aspetto o sotto Impostazioni, a seconda del plugin).
Crea un nuovo file di tipo CSS.
Incolla il seguente codice:
/*
* =========================================================
* Layout desktop (schermi più grandi di 768px)
* =========================================================
*/
/* Contenitore per le date: flex in orizzontale */
.form-row-dates {
display: flex;
gap: 15px; /* Spaziatura orizzontale tra i campi */
justify-content: flex-start;
align-items: flex-start;
}
/* Ogni "colonna" (data-check-in, data-check-out, etc.) */
.form-column {
display: flex;
flex-direction: column; /* Etichetta sopra il campo */
flex: 1; /* I campi occupano lo stesso spazio disponibile */
min-width: 150px; /* Larghezza minima */
}
.form-column label {
font-weight: bold;
margin-bottom: 5px;
}
/* Stile base per input e select */
.form-row input,
.form-row select {
padding: 5px;
font-size: 14px;
}
/* Contenitore del pulsante */
.form-submit {
display: flex;
/*
* Se vuoi centrare il pulsante su desktop, usa:
* justify-content: center;
* Se invece vuoi allinearlo a sinistra su desktop:
* justify-content: flex-start;
*/
justify-content: center;
margin-top: 20px;
width: 100%;
box-sizing: border-box;
}
/* Stile per il pulsante "Verifica Disponibilità" */
.wpcf7-form .secondary {
background-color: #023b91 !important; /* Colore di sfondo */
color: #fff !important; /* Colore del testo */
padding: 6px 16px; /* Spaziatura interna */
border: none; /* Rimuove i bordi */
border-radius: 5px; /* Arrotonda gli angoli */
font-size: 12px; /* Dimensione del testo */
cursor: pointer; /* Cursor a mano */
text-align: center; /* Allinea il testo al centro */
}
input[type=submit] {
margin-right: 0 !important;
}
.wpcf7-form .secondary:hover {
background-color: #022f73 !important; /* Hover più scuro */
}
/*
* =========================================================
* Layout mobile (schermi fino a 768px)
* =========================================================
*/
@media screen and (max-width: 768px) {
/* Campi in colonna sul mobile */
.form-row-dates {
flex-direction: column;
}
.form-column {
width: 100%;
}
.form-row {
width: 100%;
margin-bottom: 10px;
}
/* Pulsante a sinistra su mobile */
.form-submit {
justify-content: flex-start;
}
/* Pulsante "Verifica disponibilità" a tutta larghezza */
.wpcf7-form .secondary {
width: 100% !important;
}
}
/*
* =========================================================
* Spinner (Soluzione 2: nascosto finché non serve)
* =========================================================
*/
.wpcf7-spinner {
display: none !important;
margin: 0 !important;
padding: 0 !important;
width: 24px;
height: 24px;
border: none;
border-radius: 100%;
background-color: #23282d;
opacity: 0.75;
}
Salva il file CSS.
(N.B.: Se il tuo plugin Custom CSS & JS ti chiede di assegnare un “Titolo” o una “Posizione di caricamento”, assicurati di caricarlo sul Front-end, in modo che lo stile sia disponibile per il form.)
4. Inserimento del codice JavaScript
Sempre in Custom CSS & JS, crea un nuovo file di tipo JavaScript.
Incolla il seguente codice:
document.addEventListener("DOMContentLoaded", function () { /** * ------------------------------------------------ * 1) Utility: setToday e calculate (se ti servono) * ------------------------------------------------ */ function setToday(id) { document.getElementById(id).valueAsDate = new Date(); } function calculate() { const startDate = new Date(document.getElementById('date1').value); const endDate = new Date(document.getElementById('date2').value); const exclude = document.getElementById('exclude').value; if (endDate < startDate) { alert("La data fine deve essere dopo la data inizio"); return; } let totalDays = 0; let weekendDays = 0; let currentDate = new Date(startDate); while (currentDate <= endDate) { const dayOfWeek = currentDate.getDay(); if (dayOfWeek === 0 || dayOfWeek === 6) { weekendDays++; if ((exclude === 'sunday' && dayOfWeek === 0) || exclude === 'weekend') { currentDate.setDate(currentDate.getDate() + 1); continue; } } totalDays++; currentDate.setDate(currentDate.getDate() + 1); } document.getElementById('resultTotal').value = totalDays; document.getElementById('resultWeekend').value = weekendDays; } /** * ------------------------------------------------ * 2) Solo date future (min="oggi") * ------------------------------------------------ */ const today = new Date(); const formattedToday = today.toISOString().split("T")[0]; // YYYY-MM-DD const checkInField = document.querySelector('input[name="data-check-in"]'); const checkOutField = document.querySelector('input[name="data-check-out"]'); if (checkInField) { checkInField.setAttribute("min", formattedToday); } if (checkOutField) { checkOutField.setAttribute("min", formattedToday); } /** * ------------------------------------------------ * 3) Controllo check-in < check-out * ------------------------------------------------ */ if (checkInField && checkOutField) { checkInField.addEventListener("change", function () { const checkInDate = new Date(checkInField.value); if (checkInDate) { // Imposta il valore minimo per la data di check-out (il giorno successivo) const minCheckOutDate = new Date(checkInDate); minCheckOutDate.setDate(minCheckOutDate.getDate() + 1); const minDateString = minCheckOutDate.toISOString().split("T")[0]; checkOutField.setAttribute("min", minDateString); // Se la data di check-out è precedente al nuovo minimo, resetta il valore if (checkOutField.value && new Date(checkOutField.value) <= checkInDate) { checkOutField.value = ""; } } }); } /** * ------------------------------------------------ * 4) Formato date (placeholder e default) * ------------------------------------------------ */ // Funzione per ottenere la data nel formato "Lunedì 1 Gennaio 2025" function formatDateForDisplay(date) { const days = ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"]; const months = [ "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre" ]; const dayName = days[date.getDay()]; const day = date.getDate(); const monthName = months[date.getMonth()]; const year = date.getFullYear(); return `${dayName} ${day} ${monthName} ${year}`; } // Funzione per ottenere una data nel formato YYYY-MM-DD function formatDateForInput(date) { return date.toISOString().split("T")[0]; } // Imposta date predefinite (oggi e +7 giorni) const nextWeek = new Date(); nextWeek.setDate(today.getDate() + 7); if (checkInField && checkOutField) { // Valori di default checkInField.value = formatDateForInput(today); checkOutField.value = formatDateForInput(nextWeek); // Placeholder con formato “Lunedì 1 Gennaio 2025” checkInField.placeholder = formatDateForDisplay(today); checkOutField.placeholder = formatDateForDisplay(nextWeek); // Tooltip sul focus checkInField.addEventListener("focus", () => { checkInField.setAttribute("title", "Inserisci la data nel formato GG/MM/AAAA."); }); checkOutField.addEventListener("focus", () => { checkOutField.setAttribute("title", "Inserisci la data nel formato GG/MM/AAAA."); }); } /** * ------------------------------------------------ * 5) Gestione submit del modulo CF7 * ------------------------------------------------ * - Recupera i valori * - Validazione * - Redirezione */ const submitButton = document.querySelector('.wpcf7-submit'); if (submitButton) { submitButton.addEventListener("click", function (event) { event.preventDefault(); // Blocca l'invio del form di CF7 const checkInDate = checkInField ? checkInField.value : ""; const checkOutDate = checkOutField ? checkOutField.value : ""; const guestsField = document.querySelector('select[name="numero-ospiti"]'); const guests = guestsField ? guestsField.value : ""; // Validazione semplice if (!checkInDate || !checkOutDate || !guests) { alert("Per favore, compila tutti i campi."); return; } if (new Date(checkInDate) >= new Date(checkOutDate)) { alert("La data di arrivo deve precedere la data di partenza."); return; } // Formatta le date (da YYYY-MM-DD a DD/MM/YYYY con %2F come separatore) const formatDate = (date) => date.split("-").reverse().join("%2F"); // Inserisci la SITEKEY fornita da Octorate al posto di "SITEKEY_FORNITA_DA_OCTORATE" const url = `https://book.octorate.com/octobook/site/reservation/result.xhtml?siteKey=SITEKEY_FORNITA_DA_OCTORATE&lang=it&ota=false&checkin=${formatDate(checkInDate)}&checkout=${formatDate(checkOutDate)}&pax=${guests}`; // Redirezione window.location.href = url; }); } });
Modifica la stringa
SITEKEY_FORNITA_DA_OCTORATE
inserendo la SiteKey del tuo booking engine Octorate.Salva il file JavaScript.
(Assicurati anche qui che il caricamento sia impostato sul Front-end.)
5. Inserimento del form in una pagina o in un widget
Vai su Pagine (oppure Aspetto > Widget, se desideri un widget nella sidebar).
Incolla lo shortcode di CF7 (ad esempio
[contact-form-7 id="1234" title="Modulo di Prenotazione"]
) nel punto in cui vuoi far apparire il modulo.Aggiorna o salva la pagina/il widget.
6. Test e utilizzo
Apri la pagina dove hai inserito il form.
Compila i campi “Data di arrivo”, “Data di partenza” e “Numero ospiti”.
Clicca su Verifica disponibilità.
Verrai reindirizzato alla pagina di prenotazione di Octorate con i parametri (date e numero di ospiti) già compilati.
Ricorda di sostituire la SITEKEY_FORNITA_DA_OCTORATE
nel JavaScript con la tua chiave personale.
Conclusione
In questo modo hai creato un form in Contact Form 7 che sfrutta uno script personalizzato per reindirizzare i visitatori sul booking engine di Octorate, passando in automatico le date e il numero di ospiti. Il CSS personalizzato migliora l’aspetto del form sia su desktop che su dispositivi mobili.
Ecco alcuni dei principali vantaggi nell’utilizzare un form di prenotazione creato con Contact Form 7, Custom CSS & JS e l’integrazione con Octorate:
Controllo totale sul design e sul layout
Puoi adattare il form allo stile del tuo sito, modificando i colori, i font e la disposizione degli elementi.
Il CSS personalizzato ti permette di ottenere un “look & feel” coerente con il tuo brand senza dover intervenire sulle impostazioni del widget ufficiale Octorate (che è piuttosto ostico).
Esperienza utente migliorata
Grazie ai campi preimpostati (min date “oggi” e placeholder descrittivi), riduci il rischio di errori e faciliti la compilazione.
L’uso di placeholders e tooltip aiuta gli utenti a capire cosa inserire nei campi, velocizzando il processo di prenotazione.
Logica di validazione lato front-end
Il JavaScript personalizzato impedisce che il form venga inviato con dati incompleti o errati (ad esempio, check-in uguale o successivo al check-out).
Integrazione diretta con Octorate
Inserendo la SiteKey fornita da Octorate, puoi reindirizzare automaticamente l’utente alla pagina di prenotazione con le date e il numero di ospiti già impostati.
Facilità di aggiornamento e manutenzione
Con la struttura a plugin, puoi gestire il form e i relativi file CSS/JS in modo separato rispetto al tema, evitando problemi in caso di aggiornamenti del core o del tema.
Se desideri modificare le date di default, aggiungere campi (es. per i bambini o per eventuali codici sconto), puoi intervenire direttamente nei file JS/CF7 senza dover riprogettare l’intero sistema.
Modularità e riutilizzo
Puoi creare moduli diversi per più property o lingue semplicemente duplicando il form e modificando la SiteKey o la lingua nei parametri.
Ottimizzazione responsive
Il CSS incluso prevede già regole specifiche per i dispositivi mobile, garantendo che il form sia facilmente compilabile da smartphone e tablet.
Gli utenti possono prenotare anche in mobilità senza incontrare problemi di usabilità.
Compatibilità con l’ecosistema WordPress
Contact Form 7 è uno dei plugin più diffusi e supportati su WordPress; questo assicura compatibilità e aggiornamenti costanti.
Gestione semplificata di multi-lingua e traduzioni
Se utilizzi plugin di traduzione (come WPML o Polylang), puoi tradurre le etichette del form senza complicazioni.
Flessibilità e scalabilità
Non sei vincolato a un widget statico: il form è evolvibile nel tempo man mano che le tue esigenze crescono.
In sintesi, questa soluzione ti permette di offrire un flusso di prenotazione chiaro, personalizzato e in linea col tuo brand, il tutto con un controllo completo e una gestione semplice grazie a CF7 e ai file CSS/JS personalizzati.
Se hai dubbi o problemi, scrivi pure nei commenti!
Buone prenotazioni con Octorate!