# EasyForma — SEO della vetrina pubblica

Spec operativa per `easyforma.it`. Scritta il 16/09/2026, verificata contro il codice allo stesso giorno.

**Stato reale, da leggere prima del resto.** Una parte della SEO tecnica è già implementata e non va rifatta:
`app/Support/Seo.php` genera title, description, canonical e la direttiva robots per componente Inertia;
`resources/views/app.blade.php` li stampa lato server insieme a Open Graph, Twitter Card, `theme-color` e un blocco
JSON-LD con `Organization` e `SoftwareApplication`; `public/robots.txt` e la rotta `sitemap.xml` esistono.
Questo documento serve quindi a due cose: colmare le lacune che restano (§4 e §5) e dare la parte che il codice non
può contenere, cioè la mappa delle query e i contenuti da scrivere (§1 e §6).

Premessa di realismo. Il volume di ricerca su queste query è basso: poche centinaia di ricerche al mese in tutta
Italia, non decine di migliaia. La SEO qui non è un canale di volume, è un canale di **intercettazione**: chi cerca
«rendicontazione presenze FAD Forma.Temp» ha un problema adesso e un budget. Vale la pena farla bene proprio perché
la concorrenza è quasi assente, non perché porterà traffico di massa.

---

## 1. Mappa delle parole chiave

Quattro gruppi per intento. Il volume è una stima ordinale (alto/medio/basso _relativa a questo mercato_, non
assoluta): non sono dati di uno strumento di keyword research, e vanno confermati con Search Console dopo tre mesi
di indicizzazione.

### Gruppo A — Intento transazionale, il cuore del posizionamento

Chi cerca queste query sta valutando uno strumento. Sono le query che devono portare a `/` e `/prezzi`.

| Query                                          | Volume relativo | Pagina di destinazione | Difficoltà              |
| ---------------------------------------------- | --------------- | ---------------------- | ----------------------- |
| registro presenze FAD sincrona                 | medio           | `/`                    | bassa                   |
| aula virtuale Forma.Temp                       | medio           | `/`                    | bassa                   |
| software registro presenze corsi finanziati    | basso           | `/`                    | bassa                   |
| piattaforma FAD sincrona conforme fondi        | medio           | guida (vedi §6)        | media                   |
| registro presenze automatico corsi online      | basso           | `/`                    | bassa                   |
| aula virtuale con tracciamento presenze        | basso           | `/`                    | media (Jforma presidia) |
| piattaforma aula virtuale requisiti Forma.Temp | basso           | guida                  | bassa                   |

### Gruppo B — Intento informativo vicino all'acquisto

Chi cerca queste query ha il problema ma non sa che esiste uno strumento. Sono le query da guida, e sono le più
difendibili: nessuno risponde bene oggi, tranne il Fondo stesso con dei PDF.

| Query                                                    | Volume relativo | Pagina di destinazione | Difficoltà  |
| -------------------------------------------------------- | --------------- | ---------------------- | ----------- |
| rilevazione presenze digitale Forma.Temp come funziona   | medio           | guida 1                | bassa       |
| frequenza minima 90% Forma.Temp                          | basso           | guida 2                | bassa       |
| rendicontazione fondi interprofessionali presenze FAD    | medio           | guida 3                | media       |
| controlli in itinere aula virtuale Forma.Temp            | basso           | guida 4                | bassa       |
| requisiti piattaforma FAD Dispositivo elenchi Forma.Temp | basso           | guida 4                | bassa       |
| log accesso discenti sostituisce registro cartaceo       | basso           | guida 1                | molto bassa |
| calendario FTWeb fasce orarie come compilare             | basso           | guida 5                | bassa       |

### Gruppo C — Intento comparativo

Chi cerca queste query sta scegliendo fra alternative. Da presidiare con pagine di confronto oneste, non con
pagine «noi contro loro» aggressive: in un mercato di poche centinaia di enti, tutti si conoscono.

| Query                                          | Volume relativo | Pagina di destinazione | Nota                                              |
| ---------------------------------------------- | --------------- | ---------------------- | ------------------------------------------------- |
| alternativa Jforma                             | basso           | confronto              | Jforma è il riferimento, va nominato con rispetto |
| Teams registro presenze corso finanziato       | medio           | guida 6                | l'obiezione numero uno, vale una pagina intera    |
| Zoom presenze corso finanziato rendicontazione | basso           | guida 6                | stessa pagina                                     |
| migliori piattaforme FAD italiane              | medio           | —                      | presidiata da Jforma, non inseguire               |
| BigBlueButton italiano hosting                 | basso           | —                      | attira sviluppatori, non compratori               |

### Gruppo D — Query di marca e coda lunga operativa

| Query                               | Pagina    | Nota                                                                  |
| ----------------------------------- | --------- | --------------------------------------------------------------------- |
| easyforma                           | `/`       | da presidiare subito: il nome è nuovo e adiacente a `Easy Formazione` |
| easyforma prezzi                    | `/prezzi` | —                                                                     |
| easyforma login                     | `/login`  | pagina `noindex`, ma il brand va catturato da `/`                     |
| forma temp aula virtuale quante ore | guida 2   | coda lunga a bassissima concorrenza                                   |

### Parole da non inseguire

`LMS`, `e-learning`, `piattaforma corsi online`, `formazione aziendale`: volume alto, intento sbagliato, e ci
collocano nella categoria in cui perdiamo (aule virtuali a 24 € al mese). Inseguirle porta traffico che non compra
e ci fa scrivere copy da LMS.

---

## 2. Title, meta description, H1, canonical

I valori vivono in `Seo::pages()`, indicizzati per componente Inertia. Il title si compone come
`{heading} · EasyForma`, la description è quella della tabella, il canonical è `route($route)` e le pagine assenti
dalla tabella ricadono su `noindex, nofollow`. Il dominio canonico è `https://easyforma.it`, senza `www`, con
redirect 301 da `www` e da `http` (da configurare sul web server, non in Laravel).

Vincoli: title entro 60 caratteri contando il suffisso ` · EasyForma` (13 caratteri), description fra 140 e 158,
un solo `<h1>` per pagina.

### Valori raccomandati, e cosa cambiare rispetto a oggi

| Pagina      | Campo            | Valore raccomandato                                                                                                                                                          | Stato                                                                                                          |
| ----------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `/`         | heading          | `Il registro presenze si scrive da solo`                                                                                                                                     | già così                                                                                                       |
| `/`         | title risultante | `Il registro presenze si scrive da solo · EasyForma` (50)                                                                                                                    | ok                                                                                                             |
| `/`         | description      | `L'aula virtuale per i corsi finanziati da Forma.Temp: il registro presenze si compila da solo dai log di ingresso e uscita del server, mentre la lezione è in corso.` (164) | **accorciare**: togliendo `del server` scende a 153                                                            |
| `/`         | H1               | `Il registro presenze si scrive da solo.`                                                                                                                                    | oggi l'H1 è `Fai lezione. Il registro presenze lo tiene EasyForma.` → **da cambiare** (vedi `copy-rebrand.md`) |
| `/prezzi`   | heading          | `Prezzi a crediti, da 59 € al mese`                                                                                                                                          | oggi è `Prezzi`, troppo generico per la SERP                                                                   |
| `/prezzi`   | title risultante | `Prezzi a crediti, da 59 € al mese · EasyForma` (45)                                                                                                                         | —                                                                                                              |
| `/prezzi`   | description      | `Un credito vale 4 ore d'aula fino a 30 discenti. Base 59 €, Pro 189 €, Enterprise da 499 € al mese. Paghi le aule che fai, non gli utenti che registri.` (151)              | **da sostituire**                                                                                              |
| `/privacy`  | heading          | `Privacy policy`                                                                                                                                                             | già così                                                                                                       |
| `/privacy`  | description      | attuale, 160 caratteri                                                                                                                                                       | **accorciare sotto 158**: togliere `basato su`                                                                 |
| `/termini`  | heading          | `Termini di servizio`                                                                                                                                                        | già così                                                                                                       |
| `/termini`  | description      | attuale, 144 caratteri                                                                                                                                                       | ok                                                                                                             |
| `/login`    | —                | `noindex, nofollow` dal ramo di fallback                                                                                                                                     | ok, ma vedi §5                                                                                                 |
| `/register` | —                | `noindex, nofollow` dal ramo di fallback                                                                                                                                     | ok, ma vedi §5 e la nota sui parametri                                                                         |

### Due correzioni che il codice oggi non copre

**1. `/register?package=pro` non ha canonical.** La pagina è `noindex`, quindi il problema è contenuto, ma se un
giorno diventasse indicizzabile i tre valori di `package` genererebbero tre URL identici. Quando si toglie il
`noindex`, il canonical deve puntare a `/register` senza query string.

**2. Il title della home non contiene il nome del prodotto in prima posizione.** È una scelta corretta per la query
descrittiva e sbagliata per la query di marca. Il nome è nuovo e adiacente a `Easy Formazione`
(easy-formazione.com), società italiana di formazione attiva dal 2010: chi cerca `easyforma` deve trovarci al primo
posto entro poche settimane. Rimedio, senza toccare il title: il `<h1>` resta la frase, ma la prima riga di testo
della home deve contenere la stringa `EasyForma` in chiaro, e il `sameAs` dell'`Organization` deve puntare alla
pagina LinkedIn appena esiste.

---

## 3. Open Graph e Twitter

Già stampati in `app.blade.php`: `og:type`, `og:site_name`, `og:title`, `og:description`, `og:url`, `og:image`,
`og:locale`, `twitter:card`, `twitter:title`, `twitter:description`, `twitter:image`. Niente da rifare.

### Cosa manca

- **`og:image:width`, `og:image:height` e `og:image:alt`.** Senza dimensioni dichiarate, LinkedIn e WhatsApp a
  volte non rendono l'anteprima grande alla prima condivisione. Tre righe:

```html
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta
    property="og:image:alt"
    content="Registro presenze EasyForma con nomi, orari di entrata e uscita e durata."
/>
```

- **Un'immagine OG dedicata a `/prezzi`.** Oggi `ogImage()` restituisce sempre la stessa. Le pagine sono quattro:
  una seconda immagine per i prezzi, con le tre card e le cifre in IBM Plex Mono, vale il lavoro di mezz'ora.

### Come deve essere fatta l'immagine OG

1200×630, statica, non generata a runtime. Deve mostrare **dati veri di una tabella**: il pannello del registro
dell'hero, ruotato di -1,2°, su fondo `#F3F6F4`, con `EasyForma` in Archivo 700 e sotto la riga
`Il registro presenze si scrive da solo`. In una timeline LinkedIn una tabella con orari si distingue da qualunque
grafica astratta, ed è la stessa prova che convince in demo.

Nessun `twitter:site`: non esiste un account X, e un tag vuoto è peggio di un tag assente.

---

## 4. Dati strutturati

`Seo::structuredData()` emette già un `@graph` con `Organization` e `SoftwareApplication` collegati da `publisher`
e `@id`. L'impianto è corretto. Mancano tre cose, in ordine di valore.

### 4.1 FAQPage sulla home — è la lacuna che vale di più

Le FAQ della landing sono l'unico contenuto del sito che può guadagnare spazio extra nella SERP. L'array esiste già
in `resources/js/pages/marketing/home.tsx`: il JSON-LD va generato da quella stessa sorgente, non riscritto a mano,
altrimenti le due copie divergono al primo ritocco di copy.

Poiché il blocco è stampato lato server e le FAQ vivono lato client, l'unico modo pulito è spostare l'elenco delle
FAQ in PHP (una costante o un file di configurazione) e passarlo sia alla pagina Inertia sia a `structuredData()`.

```json
{
    "@type": "FAQPage",
    "@id": "https://easyforma.it/#faq",
    "mainEntity": [
        {
            "@type": "Question",
            "name": "Come funziona un credito?",
            "acceptedAnswer": {
                "@type": "Answer",
                "text": "Un credito vale 4 ore d'aula fino a 30 discenti: mezza giornata. Un corso da 8 ore con 20 discenti costa 2 crediti; se i discenti diventano 45 la fascia raddoppia e ne costa 4."
            }
        }
    ]
}
```

Due vincoli non negoziabili. Il testo del JSON-LD deve essere **identico** a quello visibile in pagina. E il blocco
`FAQPage` non va pubblicato finché la FAQ sull'invio a Forma.Temp dice ancora «Sì»: renderebbe indicizzabile, e
mostrerebbe direttamente in SERP, un'affermazione che il prodotto oggi non regge. Prima la correzione di
`copy-rebrand.md`, poi il dato strutturato.

### 4.2 `AggregateOffer` incompleto

Oggi l'offerta dichiara `lowPrice` e `offerCount`, senza `highPrice`. Google accetta l'`AggregateOffer` solo con
entrambi gli estremi quando `offerCount` è maggiore di uno. Aggiungere `highPrice` pari al prezzo Enterprise.

La scelta di un `AggregateOffer` invece di tre `Offer` separate è giusta per la home: è più robusta ai cambi di
listino. Su `/prezzi`, però, conviene emettere anche le tre `Offer` per piano, ciascuna con `priceSpecification`
mensile, `valueAddedTaxIncluded: false` e `unitCode: "MON"`, perché è la pagina in cui i prezzi sono visibili e
Google confronta il dato strutturato con quello stampato.

Le ricariche una tantum (10 crediti a 69 €, 50 crediti a 249 €) **non** vanno nelle `offers` della
`SoftwareApplication`: non sono piani, e affiancarle ai piani produce un prezzo minimo sbagliato in SERP.

### 4.3 Campi da aggiungere all'Organization

`sameAs` con la pagina LinkedIn, appena esiste, e `vatID` quando la partita IVA sostituisce il segnaposto del
footer. Vanno aggiunti solo quando sono veri: una chiave con un valore finto è peggio della chiave assente.

### Cosa non aggiungere mai

`aggregateRating` e `review`. Non abbiamo recensioni. Inventarle viola le linee guida di Google ed è il tipo di
cosa che, in un mercato di poche centinaia di enti che si conoscono tutti, si scopre in una telefonata.

---

## 5. robots.txt e sitemap

Entrambi esistono: `public/robots.txt` è servito staticamente e `sitemap.xml` da una rotta. Due problemi reali.

### 5.1 `/login` e `/register` sono bloccati e noindex insieme: si annullano

`robots.txt` contiene `Disallow: /login` e `Disallow: /register`, e le stesse pagine stampano
`noindex, nofollow` dal ramo di fallback di `Seo::forComponent()`. Le due direttive sono in conflitto: un crawler
bloccato da `robots.txt` non scarica la pagina, quindi non legge mai il meta tag. Il risultato è l'opposto di
quello voluto, perché un URL bloccato ma linkato dall'esterno può comparire in SERP come solo indirizzo, senza
titolo né descrizione, e senza che il `noindex` possa impedirlo.

**Correzione**: togliere `Disallow: /login`, `Disallow: /register`, `Disallow: /forgot-password` e
`Disallow: /reset-password` dal `robots.txt` e lasciare che sia il `noindex` a escluderle. Il crawler le scarica,
legge la direttiva, e le tiene fuori davvero.

### 5.2 `/join` e `/m/` vanno protetti con più di un `Disallow`

Sono le pagine dei discenti e contengono nome, cognome e dati di presenza di persone reali. Qui il ragionamento è
opposto al precedente: non vogliamo che vengano scaricate affatto, quindi il `Disallow` resta. Ma va rinforzato
con un'intestazione HTTP `X-Robots-Tag: noindex, nofollow` sulle risposte di quelle rotte, che vale anche per un
URL già noto e non dipende dal fatto che il crawler legga l'HTML.

Le rotte sotto `/dashboard`, `/classrooms`, `/billing` e simili sono dietro autenticazione: il `Disallow` è una
cortesia, non una misura di sicurezza, e va bene così com'è.

### 5.3 Sitemap

La rotta esiste. Va verificato che elenchi esattamente le quattro pagine indicizzabili (`/`, `/prezzi`, `/privacy`,
`/termini`) e che si estenda da sola quando nasceranno le guide di §6. Se oggi è una lista scritta a mano nel
controller, va derivata da `Seo::pages()` filtrando su `indexable`: una sola sorgente di verità per cosa è
pubblico.

### 5.4 Cambio di dominio

Se `easyform` ha già avuto pagine indicizzate su un dominio pubblico, servono redirect 301 uno a uno verso gli URL
corrispondenti di `easyforma.it`, non un redirect globale alla home, che farebbe perdere il segnale di ogni pagina.
Se il vecchio dominio non è mai stato pubblico, non serve nulla.

### 5.5 Cose da fare una volta sola

- Proprietà su Google Search Console e Bing Webmaster Tools, verificate via record DNS.
- Invio della sitemap su entrambe.
- Analytics senza cookie (Plausible o equivalente) invece di Google Analytics: evita il banner cookie, che è fuori
  perimetro nella spec della vetrina, e in questo mercato la sobrietà sui dati è un argomento di vendita.
- Misura del CLS sulla home: l'animazione del pannello registro parte al caricamento e va controllata.

---

## 6. Sei guide che possono posizionarsi

Criterio di selezione: query con intento chiaro, nessun risultato buono oggi in italiano, e un argomento su cui
abbiamo qualcosa di vero da dire. Ognuna è una pagina lunga in `/guide/<slug>`, non un post di blog cronologico.
Ognuna finisce con un richiamo alla home, mai con un modulo di iscrizione a una newsletter che non esiste.

**1. Come funziona la rilevazione digitale delle presenze di Forma.Temp**

- Query obiettivo: `rilevazione presenze digitale Forma.Temp come funziona`
- Angolo: la guida operativa che il Fondo non ha scritto. Cosa cambia fra app mobile e applicazione web, chi deve
  essere referente della rilevazione, cosa succede se il docente sbaglia una fascia, e il punto che quasi nessuno
  conosce: il PDF dei log d'accesso sostituisce il documento cartaceo in fase di inserimento delle frequenze.
- Perché può posizionarsi: oggi la risposta esiste solo dentro PDF del Fondo, che non si posizionano su query
  in linguaggio naturale.
- Rischio: va aggiornata se il Fondo cambia le regole. Datare la pagina e citare la circolare.

**2. Il 90% di frequenza minima: cosa succede a un discente sotto soglia**

- Query obiettivo: `frequenza minima 90% Forma.Temp`, `forma temp quante ore minimo corso`
- Angolo: il conto in euro. Quante ore sono il 90% di un corso da 40, 80, 250 ore; cosa comporta scendere sotto;
  come accorgersene a metà corso invece che alla rendicontazione. È la guida che vende il pilastro 2 senza
  nominare il prodotto per tre quarti della pagina.
- Perché può posizionarsi: query specifica, risposta oggi sepolta in una pagina istituzionale.

**3. Rendicontare le presenze della FAD sincrona: cosa chiedono i fondi interprofessionali**

- Query obiettivo: `rendicontazione fondi interprofessionali presenze FAD`
- Angolo: tabella comparativa dei requisiti di registro presenze di Forma.Temp, Fondimpresa, FonARCom e For.Te.
  È anche ricerca di mercato utile a noi: scrivendola scopriamo quale fondo vale come secondo connettore.
- Perché può posizionarsi: query con volume relativo alto per il settore e nessuna pagina neutrale che risponda.
  Tutte le pagine esistenti appartengono a un fornitore che vende un solo export.
- Avvertenza: da scrivere onesta, perché metà dei lettori userà un fondo che non serviamo.

**4. Requisiti di una piattaforma per l'aula virtuale nei corsi Forma.Temp**

- Query obiettivo: `requisiti piattaforma FAD Dispositivo elenchi Forma.Temp`, `controlli in itinere aula virtuale`
- Angolo: i requisiti minimi obbligatori uno per uno, citati testualmente, con accanto cosa significano in pratica
  per chi sceglie uno strumento. Include il vincolo dei 5 minuti per far entrare il funzionario del Fondo in caso
  di accesso su invito, che quasi nessun fornitore generalista soddisfa.
- Perché può posizionarsi: è la query dell'ente che sta per scegliere, cioè la più vicina all'acquisto di tutte.
- Nota: questa pagina è anche la scheda di conformità tecnica che il commerciale allega in trattativa. Si scrive
  una volta, si usa due.

**5. Costruire il calendario FTWeb senza sbagliare le fasce orarie**

- Query obiettivo: `calendario FTWeb fasce orarie come compilare`
- Angolo: il registro presenze è per fascia oraria e non per giornata, e questo è l'errore che costa di più.
  Come far coincidere le lezioni con le fasce, cosa succede se una lezione sfora, come si indica l'URL della
  piattaforma quando cambia a ogni sessione.
- Perché può posizionarsi: coda lunga operativa, zero concorrenza, e chi la cerca è già dentro FTWeb.

**6. Teams e Zoom vanno bene per un corso finanziato?**

- Query obiettivo: `Teams registro presenze corso finanziato`, `Zoom presenze corso finanziato rendicontazione`
- Angolo: risposta onesta, che è «per fare lezione sì, per il registro dipende». Dove arriva il report di
  partecipazione di Teams, perché il nome visualizzato non è il nome anagrafico, cosa manca rispetto ai requisiti
  minimi del Fondo. Nessun attacco: chi cerca questa query usa Teams e va rispettato.
- Perché può posizionarsi: è la domanda che tutti si fanno prima di cercare un'alternativa, ed è la stessa
  obiezione numero uno in vendita. Posizionarla qui la disinnesca prima della chiamata.

### Ordine di scrittura

1, 2, 4 per prime: sono quelle in cui abbiamo una citazione ufficiale e il minimo rischio di dire cose sbagliate.
6 subito dopo, perché ha il volume più alto del gruppo. 3 e 5 quando c'è tempo, o quando il primo cliente chiede
esattamente quella cosa.

Cadenza realistica per un fondatore solo: una guida ogni due settimane, non una alla settimana. Meglio quattro
pagine che restano valide per due anni che dodici che invecchiano in tre mesi.

---

## 7. Fonti

- [FAQ Aula virtuale — Forma.Temp](https://www.formatemp.it/documenti/politiche-attive/FAQ_Aula%20virtuale-PAl_2021-02-08.pdf?language_id=3)
- [FAQ Aula virtuale/FaD sincrona — Forma.Temp](https://www.formatemp.it/documenti/politiche-attive/FAQ_AulaVirtuale_2021-03-04.pdf?language_id=3)
- [Forma.Temp — Formazione di Base](https://www.formatemp.it/formazione-di-base)
- [Jforma — Exporter fondi](https://www.jforma.it/exporter/)
- [Jforma — formazione sincrona / Jmeet](https://www.jforma.it/formazione-sincrona/)
