Formulaire de contact sur un site statique

Formulaire de contact sur un site statique7 min de lecture

Ajouter un formulaire de contact à un site GitHub Pages

GitHub Pages n'exécute pas de code serveur, un POST de formulaire reçoit donc 405 Not Allowed ; envoyez vers un backend et réglez bien les redirections.

Preet SutharFondateur, Ikiform

GitHub Pages ne sert que des fichiers statiques : un formulaire qui envoie vers votre propre site reçoit 405 Not Allowed et le message est perdu. Faites pointer l'action du formulaire vers un endpoint Ikiform, ajoutez username.github.io et votre éventuel domaine personnalisé aux Allowed domains, et redirigez vers une page de remerciement qui inclut le chemin de votre site de projet. Rien ne change dans votre dépôt ni dans les réglages de Pages, et aucun secret ne finit dans le dépôt public.

Ce qui change sur GitHub Pages

GitHub Pages publie ce que construit votre dépôt ou votre workflow Actions, et rien d'autre. Jekyll s'exécute au build si vous l'utilisez, puis le résultat n'est que des fichiers. Il n'y a pas de gestionnaire de requêtes : mail() de PHP, un script Node ou un formulaire CGI en Python ne s'exécuteront pas, quoi que vous commitiez.

Vous pouvez constater l'échec depuis un terminal. Un POST vers n'importe quelle page d'un site Pages reçoit ceci :

Terminal
curl -i -X POST -d "message=hello" https://ada.github.io/notebook/contact.html
Réponse
HTTP/2 405
server: Varnish
content-length: 131

<html>
<head><title>405 Not Allowed</title></head>

Quatre autres points distinguent Pages des autres hébergeurs statiques, et chacun touche au formulaire de contact :

Particularité de PagesConséquence pour le formulaire
Les sites de projet vivent sous un chemin, username.github.io/repo/Une URL de remerciement /thanks.html pointe vers le site utilisateur, pas vers votre projet. Chaque URL a besoin de la partie /repo/
Aucun réglage pour les en-têtes de réponse personnalisésUne Content-Security-Policy ne peut venir que d'une balise <meta> dans la page
Le dépôt est souvent publicTout ce qu'il contient est public. L'id du formulaire peut y être ; une clé d'API secrète ou un mot de passe de messagerie, jamais
GitHub indique que les sites Pages ne doivent pas servir à des transactions sensibles comme l'envoi de mots de passe ou de numéros de carte bancaireLimitez le formulaire de contact à un formulaire de contact. N'y collectez ni coordonnées bancaires ni mots de passe de compte
Ce qu'exécute GitHub Pages, et où doit aller l'envoi d'un formulaire de contactce qu'exécute GitHub Pagesce que touche l'envoi du visiteurgit pushsur la branche PagesbuildJekyll ou un workflowActionsfichiersstatiquessurusername.github.io/repocontact.htmlservi par PagesIkiformstocke, vous écritrepo/thanks.htmlservi par Pages405 Not Allowedrien n'est stockédéploiementPOST303action="/contact"Ce qu'exécute GitHub Pages, et où doit aller l'envoi d'un formulaire de contactce qu'exécute GitHub Pagesce que touche l'envoi du visiteurgit pushsur la branchePagesbuildJekyll ou unworkflow Actionsfichiersstatiquessurusername.github.io/repocontact.htmlservi par PagesIkiformstocke, vous écritrepo/thanks.htmlservi par Pages405 NotAllowedrien n'eststockédéploiementPOST303action="/contact"
  1. Vous poussez sur la branche que Pages publie.
  2. Jekyll ou votre workflow Actions construit le site une fois.
  3. Pages sert le résultat sous forme de fichiers statiques sur github.io ou votre domaine personnalisé.
  4. Un visiteur envoie le formulaire de contact. Si son action pointe vers votre propre site, Pages répond 405 Not Allowed.
  5. Avec l'action réglée sur votre endpoint Ikiform, Ikiform stocke le message et vous l'envoie par e-mail.
  6. Ikiform redirige le navigateur vers la page de remerciement, que Pages sert comme n'importe quel fichier.
Le code s'exécute chez GitHub une fois par push. Rien de chez vous ne s'exécute quand un visiteur clique sur Envoyer : c'est pourquoi l'envoi doit quitter github.io.

Le formulaire

Pour un site écrit à la main, ajoutez contact.html à côté d'index.html. Celui-ci est pour un site de projet à ada.github.io/notebook, la redirection inclut donc /notebook/ :

contact.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; form-action 'self' https://ikiform.com; connect-src 'self' https://ikiform.com"
    />
    <title>Contact</title>
  </head>
  <body>
    <h1>Get in touch</h1>
    <form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
      <label for="name">Name</label>
      <input id="name" name="name" autocomplete="name" required />

      <label for="email">Email</label>
      <input id="email" name="email" type="email" autocomplete="email" required />

      <label for="about">What is it about?</label>
      <select id="about" name="about">
        <option value="question">A question about the project</option>
        <option value="hire">Work together</option>
        <option value="other">Something else</option>
      </select>

      <label for="message">Message</label>
      <textarea id="message" name="message" rows="6" minlength="10" required></textarea>

      <input type="hidden" name="page" value="docs-home" />
      <input type="hidden" name="_redirect" value="https://ada.github.io/notebook/thanks.html" />
      <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
      <button type="submit">Send</button>
    </form>
  </body>
</html>
  • La Content-Security-Policy en <meta> est facultative. Gardez-la si vous en avez une, et vérifiez que form-action et connect-src incluent https://ikiform.com. Pages ne peut pas envoyer l'en-tête à votre place.
  • Le select about vous dit pourquoi quelqu'un a écrit avant même d'ouvrir le message. Adaptez les options à ce pour quoi les gens vous écrivent réellement.
  • L'input masqué page enregistre la page où se trouvait le formulaire, ce qui est utile quand le même formulaire figure sur plusieurs pages de documentation.
  • Gardez email comme nom de champ. Les e-mails de notification l'utilisent comme adresse de réponse.

Si le même HTML est déployé sous plusieurs chemins, ou si vous n'êtes pas sûr du chemin final, construisez la redirection dans le navigateur à partir de l'adresse de la page. Placez ceci après le formulaire :

contact.html
<script>
  document.querySelectorAll('input[name="_redirect"]').forEach((input) => {
    input.value = new URL("thanks.html", document.baseURI).href;
  });
</script>

Vous utilisez Jekyll ? Ne codez pas du tout l'URL en dur. Le guide Jekyll propose un include qui la construit avec absolute_url, lequel ajoute votre baseurl pour les sites de projet. Vous construisez avec Astro, Vite ou Hugo via un workflow Actions ? Réglez le chemin de base du framework sur /repo/ pour que les ressources du formulaire se chargent, et utilisez le guide Hugo ou celui du framework pour le formulaire lui-même.

Domaines autorisés sur github.io

Ajoutez ada.github.io, avec votre propre nom d'utilisateur. Cela couvre votre site utilisateur et tous vos sites de projet, car ils partagent le même hôte. Ajoutez aussi votre domaine personnalisé si vous en utilisez un ; example.com couvre aussi www.example.com.

N'ajoutez jamais github.io seul. Tous les sites Pages correspondraient, y compris des copies de votre formulaire sur les sites d'autres personnes. Avec des domaines autorisés définis, un _redirect vers https://ada.github.io/notebook/thanks.html est suivi ; sans eux, Ikiform l'ignore et affiche sa page de remerciement hébergée.

Activez Enforce HTTPS dans les réglages Pages du dépôt. Ikiform ne suit que les valeurs _redirect qui commencent par https:, et un domaine personnalisé encore sans certificat sert des pages http:.

Remplacer un lien mailto :

Beaucoup de sites Pages démarrent avec un lien mailto: dans le pied de page. Le remplacer par le formulaire empêche les nouveaux scrapers de lire votre adresse dans la page, et les visiteurs sans appli de messagerie configurée peuvent enfin vous joindre. Deux choses à savoir avant de le supprimer :

  • L'adresse reste dans l'historique de votre dépôt, et dans tout fork ou archive de l'ancienne page. Le formulaire aide à partir de maintenant ; il ne rend pas privée une adresse publique depuis des années.
  • Les réponses partent de votre propre boîte. Les e-mails de notification définissent l'expéditeur comme adresse de réponse : cliquer sur Reply fonctionne donc comme le lien mailto:, mais dans l'autre sens.

Ikiform n'envoie jamais d'e-mail au visiteur : indiquez donc sur la page de remerciement quand il peut attendre une réponse. Si vous recevez plus de messages que vous ne pouvez en traiter par e-mail, un webhook peut déposer chacun dans Slack ou Discord.

Vérifiez que tout fonctionne

Faites ceci sur l'adresse github.io en ligne. Pages n'a pas de déploiements de préproduction : testez donc d'abord en local avec un serveur local.

  1. Ajoutez localhost et username.github.io dans Allowed domains, plus votre domaine personnalisé si vous en avez un.
  2. Commitez contact.html et thanks.html, attendez la fin du déploiement Pages dans l'onglet Actions du dépôt, puis ouvrez la page en ligne.
  3. Envoyez le formulaire. Vous devez arriver sur votre propre thanks.html, avec le chemin du projet dans la barre d'adresse.
  4. Ouvrez Submissions dans le tableau de bord. La nouvelle soumission y est, avec tous les champs envoyés.
  5. Vérifiez la boîte de réception de chaque destinataire des notifications. Chacun reçoit un e-mail avec les champs, et Reply répond à l'expéditeur quand le formulaire a un champ email.
  6. Rien n'est arrivé ? Passez le filtre de statut du tableau de bord sur Spam. Le spam reçoit la même réponse de succès qu'une vraie soumission.

Pièges

ProblèmeQue faire
405 Not Allowed après avoir cliqué sur EnvoyerLe formulaire déployé envoie toujours vers votre propre site. Affichez le code source de la page sur github.io et vérifiez l'action ; un ancien build en cache peut rester en ligne quelques minutes.
La page de remerciement d'Ikiform au lieu de la vôtreLa valeur de _redirect n'a pas le chemin du dépôt, est en http:, ou le formulaire n'a pas de domaines autorisés. Ajoutez username.github.io et utilisez l'URL https: complète.
403 origin_not_allowed, ou tous les envois finissent en spamLe domaine de la page n'est pas dans les Allowed domains du formulaire. Ajoutez-le, plus localhost pour les tests en local. Les sous-domaines d'un domaine listé sont autorisés.
Les envois fonctionnent en local mais la console affiche une erreur CSP sur github.ioUne Content-Security-Policy en <meta> dans votre layout n'inclut pas https://ikiform.com dans form-action ou connect-src.

Questions

Une étape vous bloque, ou vous voulez un guide pour votre cas ? Écrivez à hello@ikiform.com.