Skip to content

Kaikki WordPressistä, web-kehityksestä — ja paljon muuta

📤 Lomakkeiden lähetys headless WordPressissä: REST API Contact Form 7:lle ja Gravity Formsille

📤 Lomakkeiden lähetys headless WordPressissä: REST API Contact Form 7:lle ja Gravity Formsille

Rakennat sivustoa WordPressillä, ja yhteydenottolomake on jo hoidossa. Lisäosat kuten Contact Form 7 antavat sinulle valmiin HTML:n, validoinnin, lähetysten tallennuksen ja kymmeniä integraatioita. Klikkaa "Asenna", liitä shortcode, ja olet valmis kahdessa minuutissa.

Mutta kaikki muuttuu, kun WordPressistä tulee headless CMS. Olet vastuussa koko frontendistä: React, Vue, pelkkä HTML/JS. Ja lomakelisäosa, joka ennen tuotti merkinnät puolestasi, ei enää hallitse asiakaspuolta. Sen REST API on kuitenkin yhä olemassa. Lähetä vain POST oikeaan päätepisteeseen, ja kaikki lisäosan voima (kenttien validointi, tallennus, integraatiot) pysyy käytettävissäsi.

Käytännössä voit kattaa myös puhtaasti "perinteiset" tapaukset lomakelisäosien REST API:n kautta. Oletetaan, että rakennat räätälöityä teemaa Tailwindilla, ja CF7:n kiinteä merkintä jäykkine luokkarakenteineen näyttää sopimattomalta. API:n kautta lähettäminen antaa sinun hallita lomakkeen jokaista pikseliä hylkäämättä lisäosan vakiintunutta ekosysteemiä.

💡 Pikakatsaus:

  • Mitä päätepisteitä Contact Form 7 ja Gravity Forms tarjoavat ja miten ne aktivoidaan headless-ympäristössä.
  • Missä muodossa kentät lähetetään, jotta lisäosa hyväksyy tiedot oikein ja palauttaa tuloksen.
  • Miten rakennat HTML-lomakkeen, liität fetch-pyynnön ja näytät käyttäjälle onnistumisviestin tai validointivirheet.
  • Miten yhdistät CF7:n ja Gravity Formsin toisistaan poikkeavat vastausmuodot yhdeksi käteväksi rakenteeksi.

Mitä sinun tulee tietää päätepisteistä

Tietojen lähettäminen REST API:n kautta on teknisesti yksinkertainen osuus. Molemmat lisäosat odottavat POST-pyyntöä päätepisteeseen, jossa dynaaminen URL-segmentti on tietyn lomakkeen tunniste.

Contact Form 7 tarjoaa REST API:n heti aktivoinnin jälkeen. Päätepiste näyttää tältä:

1https://your-site.tld/wp-json/contact-form-7/v1/contact-forms/<FORM_ID>/feedback

Versiosta 5.8 (elokuu 2023) alkaen Contact Form 7 siirtyi SHA-1-tiivisteellisiin lomaketunnisteisiin. Vanhat numeeriset ID:t toimivat yhä, mutta uusille lomakkeille sinun täytyy poimia tunniste lomakkeen muokkaussivun URL-osoitteesta hallintapaneelissa (viimeinen segmentti post=-kohdan jälkeen). Huhtikuussa 2026 lisäosalla on yli 10 miljoonaa aktiivista asennusta, ja se on testattu WordPress 7.0:aan asti.

Gravity Forms käyttää REST API v2:ta (saatavilla versiosta 2.4 alkaen):

1https://your-site.tld/wp-json/gf/v2/forms/<FORM_ID>/submissions

Tärkeä huomio: Gravity Formsin REST API on oletuksena pois käytöstä. Aktivoidaksesi sen, mene lisäosan asetuksiin → REST API -välilehti → valitse "Salli pääsy API:in". API-avainta ei tarvita lomakkeen lähetyspäätepisteelle; se on suunnitellusti julkinen. Lomakkeen tunniste Gravity Formsissa on numeerinen ja näkyy hallintapaneelissa lomaketta muokatessa.

Pyynnön rungon rakenne

Otetaan esimerkkilomake, jossa on viisi kenttää: pakollinen teksti, sähköposti ja päivämäärä (ennen 4. lokakuuta 1957), valinnainen tekstialue ja pakollinen valintaruutu.

Esimerkki yhteydenottolomakkeesta, jossa on viisi syöttökenttää

Contact Form 7 odottaa avaimia muodossa, joka määritellään lomaketagien syntaksilla. Avain vastaa vastaavan HTML-kentän name-attribuuttia:

1{
2 "somebodys-name": "Marian Kenney",
3 "any-email": "[email protected]",
4 "before-space-age": "1922-03-11",
5 "optional-message": "",
6 "fake-terms": "1"
7}

Gravity Forms käyttää erilaista lähestymistapaa: automaattisesti luotuja juoksevia tunnisteita input_-etuliitteellä. Kentän ID näkyy suoraan hallintapaneelissa, kun muokkaat tiettyä kenttää.

Gravity Forms -kentän muokkaus, jossa näkyvä tunniste input_3

Samalle lomakkeelle Gravity Formsin pyynnön runko näyttää erilaiselta:

1{
2 "input_1": "Marian Kenney",
3 "input_2": "[email protected]",
4 "input_3": "1922-03-11",
5 "input_4": "",
6 "input_5_1": "1"
7}

Tärkein oivallus: jos annat HTML-syötteillesi name-attribuutit, jotka vastaavat liitännäisen odottamia avaimia, yhdistäminen tapahtuu automaattisesti ja FormData kerää tiedot oikeassa muodossa ilman manuaalista mappausta.

HTML:n rakentaminen ja pyynnön lähettäminen

Contact Form 7:lle HTML-merkintä näyttää tältä (huomaa, että action on päätepiste ja kenttien name-attribuutit vastaavat yllä olevia avaimia):

1<form action="https://your-site.tld/wp-json/contact-form-7/v1/contact-forms/<FORM_ID>/feedback" method="post">
2 <label for="somebodys-name">Your name</label>
3 <input id="somebodys-name" type="text" name="somebodys-name" required>
4
5 <label for="any-email">Email</label>
6 <input id="any-email" type="email" name="any-email" required>
7
8 <label for="before-space-age">Date</label>
9 <input id="before-space-age" type="date" name="before-space-age" max="1957-10-04" required>
10
11 <label for="optional-message">Message</label>
12 <textarea id="optional-message" name="optional-message"></textarea>
13
14 <label>
15 <input type="checkbox" name="fake-terms" value="1" required>
16 I accept the terms
17 </label>
18
19 <button type="submit">Submit</button>
20</form>

Gravity Formsille vain action ja name-attribuutit muuttuvat:

1<form action="https://your-site.tld/wp-json/gf/v2/forms/<FORM_ID>/submissions" method="post">
2 <label for="input_1">Your name</label>
3 <input id="input_1" type="text" name="input_1" required>
4 <!-- ... -->
5</form>

Sitten lähetys JavaScriptillä: FormData kerää arvot name-attribuutin perusteella automaattisesti, joten mappausta ei tarvita:

1const formSubmissionHandler = (event) => {
2 event.preventDefault();
3
4 const formElement = event.target;
5 const { action, method } = formElement;
6 const body = new FormData(formElement);
7
8 fetch(action, { method, body })
9 .then((response) => response.json())
10 .then((response) => {
11 if (isFormSubmissionError(response)) {
12 // Handle validation errors
13 handleValidationErrors(response);
14 return;
15 }
16 // Successful submission
17 handleSuccess(response);
18 })
19 .catch((error) => {
20 // Network error or server unavailable
21 handleNetworkError(error);
22 });
23};
24
25const formElement = document.querySelector("form");
26formElement.addEventListener("submit", formSubmissionHandler);

Tiedot lähetetään. Mutta se ei riitä käyttäjälle; hän tarvitsee palautetta: onnistumisviestin, virheellisten kenttien korostuksen, yleisen ilmoituksen. Onneksi molemmat liitännäiset palauttavat nämä tiedot vastauksessa.

Validointi: palvelin päättää, selain näyttää

Sisäänrakennetun HTML5-validoinnin (attribuutit kuten required, type="email" ja max) lisäksi on järkevää luottaa palvelinpuolen sääntötarkistuksiin, jotka liitännäiset tarjoavat. Miksi: säännöt määritellään keskitetysti WordPressin hallinnassa, ja niiden kopioiminen selainpuolelle tarkoittaa tuplatyötä ja epäjohdonmukaisuuksien lähdettä.

Sekä Contact Form 7 että Gravity Forms palauttavat validointivirheet suoraan vastauksen rungossa. Monimutkaisissa tilanteissa (ehdolliset kentät, riippuvainen validointi) palvelinpuolen validointiin luottaminen on erityisen edullista: logiikkaa ei tarvitse synkronoida frontendin ja liitännäisen asetusten välillä.

Tehtävä tiivistyy kolmeen vaiheeseen: jäsennä JSON-vastaus, poimi virheilmoitukset ja lisää ne DOM:iin vastaavien kenttien viereen.

Vastausmuodot ja normalisointi

Contact Form 7:n vastaus validointivirheen sattuessa:

1{
2 "into": "#",
3 "status": "validation_failed",
4 "message": "One or more fields have an error. Please check and try again.",
5 "posted_data_hash": "",
6 "invalid_fields": [
7 {
8 "into": "span.wpcf7-form-control-wrap.somebodys-name",
9 "message": "The field is required.",
10 "idref": null,
11 "error_id": "-ve-somebodys-name"
12 }
13 ]
14}

Onnistuessa vastaus on tiiviimpi:

1{
2 "into": "#",
3 "status": "mail_sent",
4 "message": "Thank you for your message. It has been sent.",
5 "posted_data_hash": "d52f9f9de995287195409fe6dcde0c50"
6}

Gravity Formsin vastaus validointivirheeseen on rakenteeltaan erilainen:

1{
2 "is_valid": false,
3 "validation_messages": {
4 "1": "This field is required.",
5 "2": "This field is required.",
6 "3": "This field is required.",
7 "5": "This field is required."
8 },
9 "page_number": 1,
10 "source_page_number": 1
11}

Ja onnistunut vastaus sisältää vahvistuksen HTML:n sisällä:

1{
2 "is_valid": true,
3 "page_number": 0,
4 "source_page_number": 1,
5 "confirmation_message": "<div>Thanks for contacting us! We will get in touch with you shortly.</div>",
6 "confirmation_type": "message"
7}

Ero lähestymistavoissa on selvä: CF7 upottaa virheet olioiden taulukkoon CSS-valitsimilla, kun taas Gravity Forms käyttää litteää oliota numeropohjaisilla avaimilla ilman input_-etuliitettä. Gravity Formsin onnistumisviesti tulee HTML:ään käärittynä. CF7-vastausten kenttäavaimet on upotettu valitsimiin (esim. span.wpcf7-form-control-wrap.somebodys-name) ja ne täytyy erottaa regexillä.

Sen sijaan, että tekisit jokaiselle lisäosalle oman haarautuvan logiikan, on kätevämpää normalisoida molemmat vastaukset yhtenäiseen muotoon:

1{
2 "isSuccess": false,
3 "message": "One or more fields have an error. Please check and try again.",
4 "validationError": {
5 "somebodys-name": "The field is required.",
6 "any-email": "The field is required.",
7 "input_3": "The field is required.",
8 "input_5": "This field is required."
9 }
10}

Onnistuessa isSuccess asetetaan arvoon true ja validationError on tyhjä olio.

Normalisointikoodi Contact Form 7:lle:

1const normalizeContactForm7Response = (response) => {
2 const isSuccess = response.status === 'mail_sent';
3 const message = isSuccess
4 ? response.message
5 : response.message || 'One or more fields have an error.';
6
7 const validationError = isSuccess
8 ? {}
9 : Object.fromEntries(
10 response.invalid_fields.map((error) => {
11 const key = /cf7[-a-z]*.(.*)/.exec(error.into)[1];
12 return [key, error.message];
13 })
14 );
15
16 return { isSuccess, message, validationError };
17};

Normalisointikoodi Gravity Formsille (huom: virheavaimiin lisätään input_-etuliite, jotta ne vastaavat pyynnön avaimia):

1const normalizeGravityFormsResponse = (response) => {
2 const isSuccess = response.is_valid;
3 const message = isSuccess
4 ? stripHtml(response.confirmation_message)
5 : 'There was a problem with your submission.';
6
7 const validationError = isSuccess
8 ? {}
9 : Object.fromEntries(
10 Object.entries(response.validation_messages).map(([key, value]) => [
11 `input_${key}`,
12 value,
13 ])
14 );
15
16 return { isSuccess, message, validationError };
17};

Nyt sinulla on yhtenäinen vastausolio lisäosasta riippumatta. Jäljellä on enää virhenäytön ja luokkien vaihdon kirjoittaminen DOM-elementeille, ja lomake on valmis toimintaan.

Normalisoinnista elävään käyttöliittymään

Kun vastaus on muunnettu yhtenäiseen rakenteeseen, palautteen näyttäminen on pelkkää DOM-manipulaatiota. Virheviestin lisääminen kentän viereen, luokan vaihtaminen kääreelementillä ja yleisen ilmoituksen näyttäminen: nämä kolme toimenpidettä riittävät valtaosaan tilanteista.

Reaktiivisiin käyttöliittymäpäivityksiin kevyet deklaratiiviset kirjastot, kuten Alpine.js, ovat käteviä. Minimaalinen syntaksi, ei build-vaihetta ja luonteva integraatio palvelinvastausten kanssa tekevät siitä käytännöllisen valinnan lomakkeille headless-ympäristössä. Alpine.js-lähestymistapa käsiteltiin yksityiskohtaisesti CSS-Tricksissä; kyseisen materiaalin koodi toimii lähes muuttumattomana edellä saamamme normalisoidun vastauksen kanssa.

Lopputulos

Asiakaspuolen toiminnallisuuden toisintaminen, jonka lomakelisäosat tarjoavat "suoraan paketista", vie yksinkertaisilla lomakkeilla pari tuntia. Mukava lisäetu: kun vastaus käsitellään normalisointifunktion kautta, saat vaihdettavan taustajärjestelmän. Siirtyminen Contact Form 7:stä Gravity Formsiin (tai päinvastoin) onnistuu ilman frontend-muutoksia; vaihda vain päätepiste ja normalisointifunktio.

Monisivuiset lomakkeet, ladattujen kuvien esikatselut, hintalaskurit: kyllä, se on vaativaa kehitystyötä. Mutta mitä ainutlaatuisemmat projektin vaatimukset ovat, sitä vahvemmat perusteet on räätälöidyn frontendin rakentamiselle REST API:n päälle: et tappele jonkun toisen merkintäkielen kanssa etkä kierrä valmiin renderöinnin rajoituksia.

Päätön lähestymistapa lomakkeisiin ei ole hypoteettista tulevaisuutta. Jo tänään lisäosat, kuten Contact Form 7 ja Gravity Forms, tarjoavat täysiveriset REST API:t, ja frontend-kehykset mahdollistavat lomakkeen rakentamisen tunneissa päivien sijaan. Kokeile sitä seuraavassa projektissasi, jossa lomakkeen ulkoasu on kriittinen: käytä CF7:ää tai GF:ää taustajärjestelmänä ja rakenna käyttöliittymä alusta alkaen. Tulet todennäköisesti yllättymään siitä, kuinka suoraviivaista se on.

⁉️🤔 Usein kysytyt kysymykset

Toimiiko Contact Form 7:n REST API ilmaisversiossa?

Kyllä, REST API on käytettävissä heti ilmaisen lisäosan aktivoinnin jälkeen; lisämäärityksiä ei tarvita. Huhtikuussa 2026 Contact Form 7:llä on yli 10 miljoonaa aktiivista asennusta, ja REST API on ollut vakaa osa lisäosan ydintä versiosta 4.8 lähtien.

Miten tiivistetyt lomaketunnisteet eroavat Contact Form 7:n uudemmissa versioissa?

Versiosta 5.8 (elokuu 2023) alkaen CF7 luo SHA-1-tiivisteen lomakkeen tunnisteeksi numeerisen ID:n sijaan. Vanhat numeeriset ID:t toimivat edelleen. Tiivisteen löydät lomakkeen muokkaussivun URL-osoitteesta hallintapaneelissa: /wp-admin/admin.php?page=wpcf7&post=<HASH>&action=edit. Se sijoitetaan päätepisteeseen samalla tavalla kuin numeerinen ID.

Tarvitaanko API-avain lomakkeiden lähettämiseen Gravity Forms REST API:n kautta?

Ei, /gf/v2/forms/<ID>/submissions-päätepiste ei vaadi tunnistautumista lähetykseen. Gravity Forms REST API on kuitenkin oletuksena pois käytöstä; se täytyy ottaa käyttöön lisäosan asetuksista (Lomakkeet → Asetukset → REST API → Ota API-käyttö käyttöön).

Voiko samaa JavaScript-koodia käyttää sekä Contact Form 7:lle että Gravity Formsille?

Kyllä, juuri sitä varten vastauksen normalisointi on. Molemmat normalisointifunktiot (CF7:lle ja GF:lle) palauttavat olion, jolla on sama rakenne: isSuccess-, message- ja validationError-kentät. Kytke sopiva funktio lisäosan mukaan, ja kaikki jäljelle jäävä koodi (virheiden näyttö, kenttien korostus, yleinen ilmoitus) toimii muutoksitta.

Mitä teen, jos lomake ei lähetä ja palvelin palauttaa 404-virheen?

Tarkista kolme asiaa: onko lisäosan REST API käytössä (erityisen olennaista Gravity Formsille), onko lomakkeen tunniste päätepisteen URL-osoitteessa oikein ja estetäänkö REST API palvelintasolla tai tietoturvalisäosan toimesta. Contact Form 7:n kohdalla varmista myös, että WordPressin REST API on globaalisti aktiivinen; ilman sitä CF7 ei pysty käsittelemään AJAX-lähetyksiä.