diff --git a/backend/app/helpers/legal_helper.rb b/backend/app/helpers/legal_helper.rb index 678dc2c..c31ef69 100644 --- a/backend/app/helpers/legal_helper.rb +++ b/backend/app/helpers/legal_helper.rb @@ -3,6 +3,10 @@ module LegalHelper "20 agosto 2026" end + def terms_last_updated + "31 agosto 2026" + end + def cookie_policy_last_updated "3 giugno 2026" end diff --git a/backend/app/views/layouts/marketing.html.erb b/backend/app/views/layouts/marketing.html.erb index 2904ce0..c2ec624 100644 --- a/backend/app/views/layouts/marketing.html.erb +++ b/backend/app/views/layouts/marketing.html.erb @@ -10,7 +10,7 @@ <%= render "shared/analytics_suppress" %> <%= yield :head %> - + data-ga-id="<%= MatchLiveTv.google_analytics_measurement_id %>"<% end %>> <%= render "shared/cookie_banner" %> @@ -27,7 +27,7 @@ - + diff --git a/backend/app/views/layouts/marketing_live.html.erb b/backend/app/views/layouts/marketing_live.html.erb index 277e89b..c56588c 100644 --- a/backend/app/views/layouts/marketing_live.html.erb +++ b/backend/app/views/layouts/marketing_live.html.erb @@ -8,7 +8,7 @@ <%= render "shared/meta_tags" %> <%= render "shared/analytics_suppress" %> - + <%= yield :head %> @@ -22,7 +22,7 @@ <%= render "shared/marketing_footer" %> - + diff --git a/backend/app/views/public/club_billing/profile.html.erb b/backend/app/views/public/club_billing/profile.html.erb index 95466de..d3104b9 100644 --- a/backend/app/views/public/club_billing/profile.html.erb +++ b/backend/app/views/public/club_billing/profile.html.erb @@ -21,6 +21,9 @@ <%= hidden_field_tag :plan, plan_return if plan_return %> <%= hidden_field_tag :interval, params[:interval] if params[:interval].present? %> <%= render "shared/billing_profile_fields", record: @club %> + <% if plan_return %> + <%= render "shared/refund_guarantee", variant: "checkout" %> + <% end %> <%= submit_tag t("billing.profile.submit"), class: "btn btn-primary" %> <% end %> diff --git a/backend/app/views/public/clubs/billing.html.erb b/backend/app/views/public/clubs/billing.html.erb index fd99db2..3cf69be 100644 --- a/backend/app/views/public/clubs/billing.html.erb +++ b/backend/app/views/public/clubs/billing.html.erb @@ -21,6 +21,9 @@ <%= render "shared/quoted_price_banner", quote: @quote, subscription: @subscription %> <% elsif MatchLiveTv.stripe_enabled? %> <%= render "shared/stripe_secure_payment" %> + <% if @subscription.blank? || @subscription.plan&.slug == "free" || !@subscription.active? %> + <%= render "shared/refund_guarantee", variant: "checkout" %> + <% end %> <% end %> <%= render "shared/pending_bank_transfer", order: @pending_transfer %> <% if MatchLiveTv.stripe_enabled? && @quote.blank? %> diff --git a/backend/app/views/public/clubs/new.html.erb b/backend/app/views/public/clubs/new.html.erb index a392dc6..ec7c17b 100644 --- a/backend/app/views/public/clubs/new.html.erb +++ b/backend/app/views/public/clubs/new.html.erb @@ -26,6 +26,9 @@ [t("club.new.plan_full"), "premium_full"] ], params[:plan] || "free") %>

<%= t("club.new.plan_hint") %>

+ <% if params[:plan].presence_in(%w[premium_light premium_full]) %> + <%= render "shared/refund_guarantee", variant: "checkout" %> + <% end %> <%= submit_tag t("club.new.submit"), class: "btn btn-primary" %> <% end %> diff --git a/backend/app/views/public/pages/faq.html.erb b/backend/app/views/public/pages/faq.html.erb index 40add72..0a22057 100644 --- a/backend/app/views/public/pages/faq.html.erb +++ b/backend/app/views/public/pages/faq.html.erb @@ -70,7 +70,24 @@ <%= t("pages.faq.q8_answer") %>

+ +
+ <%= t("pages.faq.q9_question") %> +

+ <%= raw t( + "pages.faq.q9_answer_html", + terms_link: link_to(t("pages.faq.q9_terms_link"), public_termini_path(anchor: "garanzia-rimborso")) + ) %> +

+
+

<%= link_to t("pages.faq.cta_signup"), public_signup_path, class: "btn btn-primary" %> diff --git a/backend/app/views/public/pages/home.html.erb b/backend/app/views/public/pages/home.html.erb index 1d96b68..418ea51 100644 --- a/backend/app/views/public/pages/home.html.erb +++ b/backend/app/views/public/pages/home.html.erb @@ -101,6 +101,7 @@ <%= image_tag "/home-piani-ecosistema.png?v=1", alt: t("home.plans_alt"), class: "plans-teaser-img", loading: "lazy" %> <%= link_to t("home.plans_cta"), public_prezzi_path, class: "btn btn-primary" %> + <%= render "shared/refund_guarantee", variant: "cta" %>

diff --git a/backend/app/views/public/pages/terms.html.erb b/backend/app/views/public/pages/terms.html.erb index 6b7ef70..6a1b6e6 100644 --- a/backend/app/views/public/pages/terms.html.erb +++ b/backend/app/views/public/pages/terms.html.erb @@ -4,7 +4,7 @@ <% end %> + +<% if local_assigns.fetch(:show_guarantee_banner) { !billing_mode || current_slug.to_s == "free" } %> + <%= render "shared/refund_guarantee", variant: "pricing" %> +<% end %> diff --git a/backend/app/views/shared/_refund_guarantee.html.erb b/backend/app/views/shared/_refund_guarantee.html.erb new file mode 100644 index 0000000..3067b30 --- /dev/null +++ b/backend/app/views/shared/_refund_guarantee.html.erb @@ -0,0 +1,35 @@ +<%# locals: (variant: "pricing") %> +<% variant = local_assigns.fetch(:variant, "pricing").to_s %> + +<% if variant == "pricing" %> + +<% elsif variant == "compact" %> +

+ + <%= t("guarantee.compact") %> +

+<% elsif variant == "cta" %> +

+ + <%= t("guarantee.home_note") %> +

+<% elsif variant == "checkout" %> +
+ +

<%= t("guarantee.checkout") %>

+
+<% end %> diff --git a/backend/config/locales/legal.de.yml b/backend/config/locales/legal.de.yml index 9f30033..c7d78ce 100644 --- a/backend/config/locales/legal.de.yml +++ b/backend/config/locales/legal.de.yml @@ -111,6 +111,13 @@ de: s3_pricing_link_text: Preise s3_p2_html: "Zahlungen für kostenpflichtige Pakete werden über Stripe abgewickelt. Mit Abschluss des Checkouts akzeptieren Sie auch die Zahlungsbedingungen von Stripe. Der Anbieter speichert keine vollständigen Kartendaten." s3_p3: Verlängerungen, Kündigung und Widerrufsrecht richten sich nach den beim Kauf mitgeteilten Angaben und den geltenden Rechtsvorschriften. + s3b_title: 3-bis. Garantie „Zufrieden oder Geld zurück“ + s3b_p1: Die Pakete Premium Light und Premium Full sind durch eine Garantie „Zufrieden oder Geld zurück“ von 30 Tagen ab dem Aktivierungsdatum des ersten von dem Verein (Kunden) erworbenen Match-Live-TV-Abos abgedeckt. + s3b_p2: Wenn Sie in diesem Zeitraum der Auffassung sind, dass der Dienst den Bedürfnissen des Vereins nicht entspricht, können Sie die Erstattung von 100 % des tatsächlich für dieses erste Abo gezahlten Betrags beantragen. Der erstattete Betrag entspricht der vollständig gezahlten Summe; etwaige Zahlungsgebühren trägt der Anbieter. + s3b_p3_html: "Der Antrag ist innerhalb von 30 Tagen nach der Aktivierung zu stellen, per E-Mail an %{email_link} oder über die auf der Website angegebenen Support-Kanäle, unter Angabe des Vereins und der Abo-Daten." + s3b_p4: Die Erstattung erfolgt, soweit technisch möglich, auf dasselbe Zahlungsmittel, das beim Kauf verwendet wurde. Die Gutschriftzeiten hängen auch vom Zahlungsnetz ab; der Anbieter leitet die Bearbeitung in der Regel innerhalb von 14 Tagen nach Bestätigung des Antrags ein. + s3b_p5: Die Garantie gilt nur einmal, für das erste vom Verein erworbene Match-Live-TV-Abo. Sie verlängert sich nicht automatisch auf spätere Zeiträume und darf nicht wiederholt von demselben Verein durch Anlegen neuer Konten in Anspruch genommen werden. + s3b_p6: Die Garantie soll dem Verein ermöglichen, Match Live TV in den ersten 30 Tagen im normalen Gebrauch zu prüfen. Der Anbieter behält sich vor, ihre Anwendung ausschließlich bei Nutzungen auszuschließen, die diesem Zweck eindeutig fremd sind, etwa einer vorübergehenden Aktivierung allein zur intensiven Abdeckung eines einzelnen Events oder Turniers, gefolgt von einem Erstattungsantrag. s4_title: 4. Livestreams, Inhalte und Schutz Minderjähriger s4_lead1: Verantwortung des Sportvereins s4_p1_html: "Der Verein, der einen Livestream startet, ist verantwortlich für die übertragenen Inhalte (Bilder, Audio, Kommentare) sowie für die Einhaltung der Gesetze, des Verbandsreglements und der erforderlichen Einwilligungen, insbesondere wenn minderjährige Athleten gefilmt werden." diff --git a/backend/config/locales/legal.en.yml b/backend/config/locales/legal.en.yml index 4c549d5..7df24e1 100644 --- a/backend/config/locales/legal.en.yml +++ b/backend/config/locales/legal.en.yml @@ -111,6 +111,13 @@ en: s3_pricing_link_text: Pricing s3_p2_html: "Payments for paid plans are handled by Stripe. By completing checkout, you also accept Stripe's terms for payment. The Provider does not store full card details." s3_p3: Renewals, cancellation and the right of withdrawal follow what was communicated at the time of purchase and applicable law. + s3b_title: 3-bis. Satisfied or refunded guarantee + s3b_p1: Premium Light and Premium Full plans are covered by a “Satisfied or refunded” guarantee lasting 30 days from the activation date of the first Match Live TV subscription purchased by the club (customer). + s3b_p2: If within that period you consider the service is not suitable for the club’s needs, you may request a refund of 100% of the amount actually paid for that first subscription. The refunded amount equals the full sum paid; any payment processing fees remain borne by the Provider. + s3b_p3_html: "The request must be sent within 30 days of activation, by writing to %{email_link} or via the support channels indicated on the site, stating the club and the subscription details." + s3b_p4: The refund is made, where technically possible, to the same payment method used for the purchase. Credit times also depend on the payment network; the Provider normally starts processing within 14 days of confirming the request. + s3b_p5: The guarantee applies only once, to the first Match Live TV subscription purchased by the club. It does not automatically renew for later periods and cannot be used repeatedly by the same club through the creation of new accounts. + s3b_p6: The guarantee is intended to allow the club to evaluate Match Live TV in normal use during the first 30 days. The Provider reserves the right to exclude its application solely in cases of use clearly unrelated to that purpose, such as a temporary activation aimed exclusively at intensive coverage of a single event or tournament, followed by a refund request. s4_title: 4. Live broadcasts, content and protection of minors s4_lead1: Responsibility of the sports club s4_p1_html: "The club that starts a live broadcast is responsible for the content transmitted (images, audio, comments) and for compliance with the law, federation regulations and the necessary consents, in particular when minor athletes are filmed." diff --git a/backend/config/locales/legal.es.yml b/backend/config/locales/legal.es.yml index b04c5ff..ceec3c1 100644 --- a/backend/config/locales/legal.es.yml +++ b/backend/config/locales/legal.es.yml @@ -111,6 +111,13 @@ es: s3_pricing_link_text: Precios s3_p2_html: "Los pagos de los planes de pago se gestionan a través de Stripe. Al aceptar el checkout, también aceptas los términos de Stripe para el pago. El Proveedor no almacena los datos completos de la tarjeta." s3_p3: Las renovaciones, la baja y el derecho de desistimiento siguen lo comunicado en el momento de la compra y la normativa aplicable. + s3b_title: 3-bis. Garantía Satisfechos o reembolsados + s3b_p1: Los planes Premium Light y Premium Full están cubiertos por una garantía «Satisfechos o reembolsados» de 30 días desde la fecha de activación de la primera suscripción Match Live TV adquirida por el club (cliente). + s3b_p2: Si en ese periodo consideras que el servicio no se adapta a las necesidades del club, puedes solicitar el reembolso del 100% del importe efectivamente pagado por esa primera suscripción. El importe reembolsado equivale a la suma íntegra abonada; las eventuales comisiones de pago corren a cargo del Proveedor. + s3b_p3_html: "La solicitud debe enviarse dentro de los 30 días desde la activación, escribiendo a %{email_link} o a través de los canales de soporte indicados en el sitio, indicando el club y los datos de la suscripción." + s3b_p4: El reembolso se efectúa, cuando sea técnicamente posible, en el mismo método de pago utilizado en la compra. Los plazos de abono también dependen de la red de pago; el Proveedor suele iniciar el trámite en un plazo de 14 días desde la confirmación de la solicitud. + s3b_p5: La garantía se aplica una sola vez, a la primera suscripción Match Live TV adquirida por el club. No se renueva automáticamente en periodos posteriores y no puede utilizarse de forma reiterada por el mismo club mediante la creación de nuevas cuentas. + s3b_p6: La garantía está pensada para que el club evalúe Match Live TV en un uso normal durante los primeros 30 días. El Proveedor se reserva el derecho de excluir su aplicación únicamente en caso de usos manifiestamente ajenos a esa finalidad, como una activación temporal destinada exclusivamente a la cobertura intensiva de un evento o torneo aislado, seguida de una solicitud de reembolso. s4_title: 4. Directos, contenidos y protección de menores s4_lead1: Responsabilidad del club deportivo s4_p1_html: "El club que inicia un directo es responsable de los contenidos transmitidos (imágenes, audio, comentarios) y del cumplimiento de las leyes, el reglamento federativo y los consentimientos necesarios, en particular cuando se filma a deportistas menores de edad." diff --git a/backend/config/locales/legal.fr.yml b/backend/config/locales/legal.fr.yml index d2301f1..4e25823 100644 --- a/backend/config/locales/legal.fr.yml +++ b/backend/config/locales/legal.fr.yml @@ -111,6 +111,13 @@ fr: s3_pricing_link_text: Tarifs s3_p2_html: "Les paiements des forfaits payants sont gérés par Stripe. En validant le paiement, vous acceptez également les conditions de Stripe pour le paiement. Le Fournisseur ne conserve pas les données complètes de la carte." s3_p3: Les renouvellements, la résiliation et le droit de rétractation suivent ce qui a été communiqué au moment de l'achat et la réglementation applicable. + s3b_title: 3-bis. Garantie Satisfait ou remboursé + s3b_p1: Les forfaits Premium Light et Premium Full sont couverts par une garantie « Satisfait ou remboursé » d'une durée de 30 jours à compter de la date d'activation du premier abonnement Match Live TV acheté par le club (client). + s3b_p2: Si dans ce délai vous estimez que le service ne convient pas aux besoins du club, vous pouvez demander le remboursement de 100 % du montant effectivement payé pour ce premier abonnement. Le montant remboursé correspond à la somme intégralement versée ; d'éventuelles commissions de paiement restent à la charge du Fournisseur. + s3b_p3_html: "La demande doit être envoyée dans les 30 jours suivant l'activation, en écrivant à %{email_link} ou via les canaux d'assistance indiqués sur le site, en précisant le club et les références de l'abonnement." + s3b_p4: Le remboursement est effectué, lorsque c'est techniquement possible, sur le même moyen de paiement que celui utilisé pour l'achat. Les délais de crédit dépendent aussi du réseau de paiement ; le Fournisseur engage en principe le traitement dans les 14 jours suivant la confirmation de la demande. + s3b_p5: La garantie s'applique une seule fois, au premier abonnement Match Live TV acheté par le club. Elle ne se renouvelle pas automatiquement sur les périodes suivantes et ne peut pas être utilisée de manière répétée par le même club via la création de nouveaux comptes. + s3b_p6: La garantie vise à permettre au club d'évaluer Match Live TV dans un usage normal pendant les 30 premiers jours. Le Fournisseur se réserve le droit d'en exclure l'application uniquement en cas d'usages manifestement étrangers à cette finalité, tels qu'une activation temporaire destinée exclusivement à la couverture intensive d'un événement ou d'un tournoi isolé, suivie d'une demande de remboursement. s4_title: 4. Directs, contenus et protection des mineurs s4_lead1: Responsabilité du club sportif s4_p1_html: "Le club qui lance un direct est responsable des contenus diffusés (images, audio, commentaires) et de la conformité aux lois, au règlement fédéral et aux consentements nécessaires, en particulier lorsque des athlètes mineurs sont filmés." diff --git a/backend/config/locales/legal.it.yml b/backend/config/locales/legal.it.yml index c4eee45..3f3a398 100644 --- a/backend/config/locales/legal.it.yml +++ b/backend/config/locales/legal.it.yml @@ -111,6 +111,13 @@ it: s3_pricing_link_text: Prezzi s3_p2_html: "I pagamenti dei piani a pagamento sono gestiti da Stripe. Accettando il checkout, accetti anche i termini di Stripe per il pagamento. Il Fornitore non memorizza i dati completi della carta." s3_p3: Rinnovi, disdetta e diritto di recesso seguono quanto comunicato al momento dell’acquisto e la normativa applicabile. + s3b_title: 3-bis. Garanzia Soddisfatti o rimborsati + s3b_p1: I piani Premium Light e Premium Full sono coperti da una garanzia «Soddisfatti o rimborsati» della durata di 30 giorni dalla data di attivazione del primo abbonamento Match Live TV acquistato dalla società (cliente). + s3b_p2: Se entro tale periodo ritieni che il servizio non sia adatto alle esigenze della società, puoi richiedere il rimborso del 100% dell’importo effettivamente pagato per quel primo abbonamento. L’importo rimborsato è pari all’intera somma versata; eventuali commissioni di pagamento restano a carico del Fornitore. + s3b_p3_html: "La richiesta va inviata entro i 30 giorni dall’attivazione, scrivendo a %{email_link} oppure tramite i canali di supporto indicati sul sito, indicando la società e i riferimenti dell’abbonamento." + s3b_p4: Il rimborso è disposto, ove tecnicamente possibile, sullo stesso metodo di pagamento utilizzato per l’acquisto. I tempi di accredito dipendono anche dal circuito di pagamento; di norma il Fornitore avvia l’elaborazione entro 14 giorni dalla conferma della richiesta. + s3b_p5: La garanzia si applica una sola volta, al primo abbonamento Match Live TV acquistato dalla società. Non si rinnova automaticamente su periodi successivi e non può essere utilizzata ripetutamente dalla stessa società tramite la creazione di nuovi account. + s3b_p6: La garanzia è destinata a consentire alla società di valutare Match Live TV nel normale utilizzo durante i primi 30 giorni. Il Fornitore si riserva di escluderne l’applicazione esclusivamente in caso di utilizzi manifestamente estranei a tale finalità, quali l’attivazione temporanea finalizzata esclusivamente alla copertura intensiva di un singolo evento o torneo, seguita dalla richiesta di rimborso. s4_title: 4. Dirette, contenuti e protezione dei minori s4_lead1: Responsabilità della società sportiva s4_p1_html: "La società che avvia una diretta è responsabile dei contenuti trasmessi (immagini, audio, commenti) e della conformità alle leggi, al regolamento federale e ai consensi necessari, in particolare quando sono ripresi atleti minorenni." diff --git a/backend/config/locales/pages.de.yml b/backend/config/locales/pages.de.yml index da5d89d..92a2cad 100644 --- a/backend/config/locales/pages.de.yml +++ b/backend/config/locales/pages.de.yml @@ -88,7 +88,7 @@ de: table_matches: Gleichzeitige Spiele table_live_mltv: Live auf Match Live TV table_youtube: YouTube - table_replay: Server-Replay + table_replay: Replay-Archiv table_download: Handy-Download table_price: Preis table_price_free: "€0" @@ -137,7 +137,7 @@ de: q3_answer_html: "Ja. Die Satz-Zählweise ist für Volleyball gemacht; Sie können die Regeln für besondere Turniere anpassen. Entdecken Sie die eigene Seite: %{volleyball_link}." q3_volleyball_link: Match Live TV für Jugendvolleyball q4_question: Was passiert, wenn ich den Livestream verpasse? - q4_answer: "Mit den Plänen Premium Light oder Full wird das Spiel im Archiv gespeichert (30 oder 90 Tage) und Sie können es auf der Website erneut ansehen. Der Free-Plan enthält kein Server-Replay, aber der Livestream bleibt für Streamer und Zuschauer kostenlos." + q4_answer: "Mit den Plänen Premium Light oder Full wird das Spiel im Archiv gespeichert (30 oder 90 Tage) und Sie können es auf der Website erneut ansehen. Der Free-Plan enthält kein Replay-Archiv, aber der Livestream bleibt für Streamer und Zuschauer kostenlos." q5_question: Was kostet es für den Verein? q5_answer_html: "Sie können mit dem Free-Plan starten (begrenztes Team und ein Livestream gleichzeitig). Premium Light und Full bieten mehr parallele Spiele, Archiv und YouTube. %{pricing_link}." q5_pricing_link: Preise vergleichen @@ -147,6 +147,9 @@ de: q7_answer: "Mit Premium Light können Sie ihn auf den Match-Live-TV-Kanal senden; mit Premium Full auch auf den YouTube-Kanal des Vereins. Wer möchte, bleibt beim Match-Live-TV-Link, praktisch für Familien." q8_question: Muss ich Router-Ports öffnen oder TV-Ausrüstung haben? q8_answer: "Nein, nicht für Zuschauer. Für den streamenden Verein reichen ein Smartphone und eine gute Verbindung in der Halle; das technische Team der Plattform kümmert sich um die Infrastruktur. Keine Broadcast-Kameras oder Mischpulte nötig." + q9_question: Wie funktioniert die Garantie „Zufrieden oder Geld zurück“? + q9_answer_html: "Sie können Match Live TV 30 Tage ab Aktivierung des ersten Abos mit Ihrem Verein testen. Wenn die Plattform in diesem Zeitraum nicht zu Ihren Anforderungen passt, können Sie die Erstattung des vollen gezahlten Betrags beantragen. Weitere Details finden Sie in den %{terms_link}." + q9_terms_link: Nutzungsbedingungen cta_signup: Team registrieren cta_live: Live-Spiele ansehen volleyball: diff --git a/backend/config/locales/pages.en.yml b/backend/config/locales/pages.en.yml index 6ad1e59..8da70f0 100644 --- a/backend/config/locales/pages.en.yml +++ b/backend/config/locales/pages.en.yml @@ -88,7 +88,7 @@ en: table_matches: Concurrent matches table_live_mltv: Live on Match Live TV table_youtube: YouTube - table_replay: Server replay + table_replay: Replay archive table_download: Phone download table_price: Price table_price_free: "€0" @@ -137,7 +137,7 @@ en: q3_answer_html: "Yes. The set-based scoring is built for volleyball; you can customize the rules for special tournaments. Check out the dedicated page: %{volleyball_link}." q3_volleyball_link: Match Live TV for youth volleyball q4_question: What happens if I miss the stream? - q4_answer: "With Premium Light or Full plans the match is saved to the archive (30 or 90 days) and you can watch it again from the site. The Free plan doesn't include server replay, but the live stream stays free for both streamers and viewers." + q4_answer: "With Premium Light or Full plans the match is saved to the archive (30 or 90 days) and you can watch it again from the site. The Free plan doesn't include the replay archive, but the live stream stays free for both streamers and viewers." q5_question: How much does it cost for the club? q5_answer_html: "You can start with the Free plan (limited staff and one stream at a time). Premium Light and Full add more concurrent matches, archive and YouTube. %{pricing_link}." q5_pricing_link: Compare pricing @@ -147,6 +147,9 @@ en: q7_answer: "With Premium Light you can send it to the Match Live TV channel; with Premium Full also to the club's YouTube channel. Those who prefer can stick to the Match Live TV link, convenient for families." q8_question: Do I need to open router ports or have TV equipment? q8_answer: "No, not for viewers. For the club that streams, a smartphone and a good gym connection are enough; the platform's technical staff manages the infrastructure. No broadcast cameras or mixers needed." + q9_question: How does the Satisfied or refunded guarantee work? + q9_answer_html: "You can try Match Live TV with your club for 30 days from activation of the first subscription. If within that period you feel the platform is not a good fit, you can request a refund of the full amount paid. For more details see the %{terms_link}." + q9_terms_link: Terms and Conditions cta_signup: Register your team cta_live: Watch live matches volleyball: diff --git a/backend/config/locales/pages.es.yml b/backend/config/locales/pages.es.yml index ec3fe59..48b73ce 100644 --- a/backend/config/locales/pages.es.yml +++ b/backend/config/locales/pages.es.yml @@ -88,7 +88,7 @@ es: table_matches: Partidos simultáneos table_live_mltv: Directo en Match Live TV table_youtube: YouTube - table_replay: Repetición en servidor + table_replay: Archivo de replay table_download: Descarga al móvil table_price: Precio table_price_free: "€0" @@ -137,7 +137,7 @@ es: q3_answer_html: "Sí. El marcador por sets está pensado para el voleibol; puedes personalizar reglas para torneos especiales. Descubre la página dedicada: %{volleyball_link}." q3_volleyball_link: Match Live TV para voleibol juvenil q4_question: "¿Qué pasa si me pierdo el directo?" - q4_answer: "Con los planes Premium Light o Full el partido se guarda en el archivo (30 o 90 días) y puedes volver a verlo desde el sitio. El plan Free no incluye repetición en servidor, pero el directo sigue siendo gratis para quien emite y para quien mira." + q4_answer: "Con los planes Premium Light o Full el partido se guarda en el archivo (30 o 90 días) y puedes volver a verlo desde el sitio. El plan Free no incluye archivo de replay, pero el directo sigue siendo gratis para quien emite y para quien mira." q5_question: "¿Cuánto cuesta para el club?" q5_answer_html: "Puedes empezar con el plan Free (límites de staff y un directo a la vez). Premium Light y Full añaden más partidos en paralelo, archivo y YouTube. %{pricing_link}." q5_pricing_link: Compara precios @@ -147,6 +147,9 @@ es: q7_answer: "Con Premium Light puedes enviarlo al canal de Match Live TV; con Premium Full también al canal de YouTube del club. Quien prefiera puede quedarse con el enlace de Match Live TV, cómodo para las familias." q8_question: "¿Tengo que abrir puertos en el router o tener equipo de TV?" q8_answer: "No, para quien mira no. Para el club que emite basta con el smartphone y una buena conexión en el pabellón; el staff técnico de la plataforma gestiona la infraestructura. Nada de cámaras de retransmisión ni mezcladores." + q9_question: "¿Cómo funciona la garantía Satisfechos o reembolsados?" + q9_answer_html: "Puedes probar Match Live TV con tu club durante 30 días desde la activación de la primera suscripción. Si en ese periodo consideras que la plataforma no se adapta a tus necesidades, puedes solicitar el reembolso del importe íntegro pagado. Para más detalles consulta los %{terms_link}." + q9_terms_link: Términos y Condiciones cta_signup: Registra tu equipo cta_live: Ver directos volleyball: diff --git a/backend/config/locales/pages.fr.yml b/backend/config/locales/pages.fr.yml index 6c4550a..df67960 100644 --- a/backend/config/locales/pages.fr.yml +++ b/backend/config/locales/pages.fr.yml @@ -88,7 +88,7 @@ fr: table_matches: Matchs simultanés table_live_mltv: Direct sur Match Live TV table_youtube: YouTube - table_replay: Replay serveur + table_replay: Archive replay table_download: Téléchargement téléphone table_price: Prix table_price_free: "€0" @@ -137,7 +137,7 @@ fr: q3_answer_html: "Oui. Le score par set est pensé pour le volley ; vous pouvez personnaliser les règles pour des tournois particuliers. Découvrez la page dédiée : %{volleyball_link}." q3_volleyball_link: Match Live TV pour le volley jeunes q4_question: Que se passe-t-il si je rate le direct ? - q4_answer: "Avec les offres Premium Light ou Full, le match est enregistré dans l'archive (30 ou 90 jours) et vous pouvez le revoir depuis le site. L'offre Free n'inclut pas le replay serveur, mais le direct reste gratuit pour ceux qui diffusent et pour ceux qui regardent." + q4_answer: "Avec les offres Premium Light ou Full, le match est enregistré dans l'archive (30 ou 90 jours) et vous pouvez le revoir depuis le site. L'offre Free n'inclut pas l'archive replay, mais le direct reste gratuit pour ceux qui diffusent et pour ceux qui regardent." q5_question: Combien ça coûte pour le club ? q5_answer_html: "Vous pouvez commencer avec l'offre Free (limites sur le staff et un direct à la fois). Premium Light et Full ajoutent plus de matchs en parallèle, l'archive et YouTube. %{pricing_link}." q5_pricing_link: Comparer les tarifs @@ -147,6 +147,9 @@ fr: q7_answer: "Avec Premium Light, vous pouvez le diffuser sur la chaîne Match Live TV ; avec Premium Full, aussi sur la chaîne YouTube du club. Ceux qui préfèrent peuvent rester sur le lien Match Live TV, pratique pour les familles." q8_question: Dois-je ouvrir des ports sur le routeur ou avoir du matériel TV ? q8_answer: "Non, pas pour les spectateurs. Pour le club qui diffuse, un smartphone et une bonne connexion en salle suffisent ; le staff technique de la plateforme gère l'infrastructure. Pas de caméras de diffusion ni de mixeur." + q9_question: Comment fonctionne la garantie Satisfait ou remboursé ? + q9_answer_html: "Vous pouvez essayer Match Live TV avec votre club pendant 30 jours à compter de l'activation du premier abonnement. Si dans ce délai la plateforme ne convient pas à vos besoins, vous pouvez demander le remboursement de la totalité du montant payé. Pour plus de détails, consultez les %{terms_link}." + q9_terms_link: Conditions générales cta_signup: Inscrire l'équipe cta_live: Voir les directs volleyball: diff --git a/backend/config/locales/pages.it.yml b/backend/config/locales/pages.it.yml index ff75b37..10e1939 100644 --- a/backend/config/locales/pages.it.yml +++ b/backend/config/locales/pages.it.yml @@ -88,7 +88,7 @@ it: table_matches: Partite in contemporanea table_live_mltv: Live su Match Live TV table_youtube: YouTube - table_replay: Replay server + table_replay: Archivio replay table_download: Download telefono table_price: Prezzo table_price_free: "€0" @@ -137,7 +137,7 @@ it: q3_answer_html: "Sì. Il punteggio a set è pensato per la pallavolo; puoi personalizzare regole per tornei particolari. Scopri la pagina dedicata: %{volleyball_link}." q3_volleyball_link: Match Live TV per pallavolo giovanile q4_question: Cosa succede se perdo la diretta? - q4_answer: "Con i piani Premium Light o Full la partita viene salvata in archivio (30 o 90 giorni) e puoi rivederla dal sito. Il piano Free non include replay su server, ma la diretta resta gratuita per chi trasmette e per chi guarda." + q4_answer: "Con i piani Premium Light o Full la partita viene salvata in archivio (30 o 90 giorni) e puoi rivederla dal sito. Il piano Free non include l'archivio replay, ma la diretta resta gratuita per chi trasmette e per chi guarda." q5_question: Quanto costa per la società? q5_answer_html: "Puoi iniziare con il piano Free (limiti su staff e una diretta alla volta). Premium Light e Full aggiungono più partite in parallelo, archivio e YouTube. %{pricing_link}." q5_pricing_link: Confronta i prezzi @@ -147,6 +147,9 @@ it: q7_answer: "Con Premium Light puoi mandarla sul canale Match Live TV; con Premium Full anche sul canale YouTube della società. Chi preferisce resta sul link Match Live TV, comodo per le famiglie." q8_question: Devo aprire porte sul router o avere attrezzatura da TV? q8_answer: "No per chi guarda. Per la società che trasmette basta lo smartphone e una buona connessione in palestra; lo staff tecnico della piattaforma gestisce l'infrastruttura. Niente camere broadcast o mixer." + q9_question: Come funziona la garanzia Soddisfatti o rimborsati? + q9_answer_html: "Puoi provare Match Live TV con la tua società per 30 giorni dall'attivazione del primo abbonamento. Se entro questo periodo ritieni che la piattaforma non sia adatta alle tue esigenze, puoi richiedere il rimborso dell'intero importo pagato. Per maggiori dettagli consulta i %{terms_link}." + q9_terms_link: Termini e Condizioni cta_signup: Registra la squadra cta_live: Guarda le dirette volleyball: diff --git a/backend/config/locales/ui.de.yml b/backend/config/locales/ui.de.yml index 87fe6ba..d85a15b 100644 --- a/backend/config/locales/ui.de.yml +++ b/backend/config/locales/ui.de.yml @@ -84,6 +84,16 @@ de: seo_faq_link: FAQ seo_volleyball_link: Match Live TV für Jugendvolleyball seo_signup_link: Team kostenlos registrieren + guarantee: + title: Zufrieden oder Geld zurück + kicker_days: 30 Tage + subtitle: 30 Tage, um Match Live TV ohne Risiko zu testen. + body: Wenn Match Live TV nicht die richtige Lösung für Ihren Verein ist, erstatten wir 100 % des Abos. + compact: 30 Tage zufrieden oder Geld zurück + home_note: Zufrieden oder Geld zurück innerhalb von 30 Tagen + checkout: Ihr Kauf ist durch die 30-Tage-Garantie „Zufrieden oder Geld zurück“ abgedeckt. + learn_more: So funktioniert es + aria_pricing: Garantie Zufrieden oder Geld zurück auth: email: E-Mail password: Passwort diff --git a/backend/config/locales/ui.en.yml b/backend/config/locales/ui.en.yml index afa3059..e9edffd 100644 --- a/backend/config/locales/ui.en.yml +++ b/backend/config/locales/ui.en.yml @@ -84,6 +84,16 @@ en: seo_faq_link: FAQ seo_volleyball_link: Match Live TV for youth volleyball seo_signup_link: register your team for free + guarantee: + title: Satisfied or refunded + kicker_days: 30 days + subtitle: 30 days to try Match Live TV with no risk. + body: If Match Live TV is not the right fit for your club, we refund 100% of the subscription. + compact: 30-day satisfied or refunded + home_note: Satisfied or refunded within 30 days + checkout: Your purchase is covered by the 30-day Satisfied or refunded guarantee. + learn_more: See how it works + aria_pricing: Satisfied or refunded guarantee auth: email: Email password: Password diff --git a/backend/config/locales/ui.es.yml b/backend/config/locales/ui.es.yml index e0bc718..4c03902 100644 --- a/backend/config/locales/ui.es.yml +++ b/backend/config/locales/ui.es.yml @@ -84,6 +84,16 @@ es: seo_faq_link: preguntas frecuentes seo_volleyball_link: Match Live TV para voleibol juvenil seo_signup_link: registra el equipo gratis + guarantee: + title: Satisfechos o reembolsados + kicker_days: 30 días + subtitle: 30 días para probar Match Live TV sin riesgos. + body: Si Match Live TV no es la solución adecuada para tu club, te reembolsamos el 100% de la suscripción. + compact: 30 días satisfechos o reembolsados + home_note: Satisfechos o reembolsados en 30 días + checkout: Tu compra está cubierta por la garantía Satisfechos o reembolsados de 30 días. + learn_more: Cómo funciona + aria_pricing: Garantía satisfechos o reembolsados auth: email: Email password: Contraseña diff --git a/backend/config/locales/ui.fr.yml b/backend/config/locales/ui.fr.yml index c1ed50f..852e441 100644 --- a/backend/config/locales/ui.fr.yml +++ b/backend/config/locales/ui.fr.yml @@ -84,6 +84,16 @@ fr: seo_faq_link: FAQ seo_volleyball_link: Match Live TV pour le volley jeunes seo_signup_link: inscrivez l'équipe gratuitement + guarantee: + title: Satisfait ou remboursé + kicker_days: 30 jours + subtitle: 30 jours pour essayer Match Live TV sans risque. + body: Si Match Live TV n'est pas la bonne solution pour votre club, nous remboursons 100 % de l'abonnement. + compact: 30 jours satisfait ou remboursé + home_note: Satisfait ou remboursé sous 30 jours + checkout: Votre achat est couvert par la garantie Satisfait ou remboursé de 30 jours. + learn_more: Voir comment ça fonctionne + aria_pricing: Garantie satisfait ou remboursé auth: email: E-mail password: Mot de passe diff --git a/backend/config/locales/ui.it.yml b/backend/config/locales/ui.it.yml index f1bd282..d999153 100644 --- a/backend/config/locales/ui.it.yml +++ b/backend/config/locales/ui.it.yml @@ -84,6 +84,16 @@ it: seo_faq_link: domande frequenti seo_volleyball_link: Match Live TV per la pallavolo giovanile seo_signup_link: registra la squadra gratis + guarantee: + title: Soddisfatti o rimborsati + kicker_days: 30 giorni + subtitle: 30 giorni per provare Match Live TV senza rischi. + body: Se Match Live TV non è la soluzione giusta per la tua società, ti rimborsiamo il 100% dell'abbonamento. + compact: 30 giorni soddisfatti o rimborsati + home_note: Soddisfatti o rimborsati entro 30 giorni + checkout: Il tuo acquisto è coperto dalla garanzia Soddisfatti o rimborsati di 30 giorni. + learn_more: Scopri come funziona + aria_pricing: Garanzia soddisfatti o rimborsati auth: email: Email password: Password diff --git a/backend/public/marketing.css b/backend/public/marketing.css index 6e2b217..156da1c 100644 --- a/backend/public/marketing.css +++ b/backend/public/marketing.css @@ -1623,9 +1623,14 @@ body.nav-menu-open { overflow: hidden; } } .plan-card > .btn, .plan-card > .plan-action-hint, -.plan-card > .plan-interval-actions { +.plan-card > .plan-interval-actions, +.plan-card__cta { margin-top: auto; } +.plan-card__cta .plan-interval-actions:first-child, +.plan-card__cta > .btn:first-child { + margin-top: 0; +} .features-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 18px; } .feature-card { display: flex; @@ -2458,6 +2463,162 @@ body.nav-menu-open { overflow: hidden; } font-size: 0.85rem; } .stripe-secure--compact i { font-size: 0.95rem; color: #888; } + +.refund-guarantee--pricing { + display: grid; + grid-template-columns: auto 1fr; + gap: 18px 20px; + align-items: start; + margin-top: 24px; + padding: 22px 24px; + background: + linear-gradient(180deg, rgba(229, 57, 53, 0.07), transparent 42%), + #14141c; + border: 1px solid #2a2a36; + border-radius: 14px; + box-shadow: 0 0 0 1px rgba(229, 57, 53, 0.14); +} +.refund-guarantee__icon { + display: flex; + align-items: center; + justify-content: center; + width: 44px; + height: 44px; + border-radius: 12px; + background: rgba(229, 57, 53, 0.12); + color: #e53935; + font-size: 1.15rem; + line-height: 1; + flex-shrink: 0; +} +.refund-guarantee__copy { min-width: 0; } +.refund-guarantee__title { + margin: 0 0 6px; + color: #f0f0f4; + font-size: 1.05rem; + font-weight: 700; + letter-spacing: -0.01em; + line-height: 1.3; +} +.refund-guarantee__kicker { + display: none; + font-weight: 600; + color: #c8c8d0; +} +.refund-guarantee__subtitle { + margin: 0 0 8px; + color: #ddd; + font-size: 0.92rem; + font-weight: 600; + line-height: 1.4; +} +.refund-guarantee__body { + margin: 0; + color: #aaa; + font-size: 0.9rem; + line-height: 1.55; + max-width: 46rem; +} +.refund-guarantee__more { + margin: 10px 0 0; + font-size: 0.85rem; +} +.refund-guarantee__more a { + color: #ff8a80; + text-decoration: none; + font-weight: 600; +} +.refund-guarantee__more a:hover { + color: #ff6e63; + text-decoration: underline; +} +.refund-guarantee--compact { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + margin: 12px 0 0; + padding: 10px 4px 0; + border-top: 1px solid #2a2a36; + color: #c8c8d0; + font-size: 0.8rem; + font-weight: 600; + line-height: 1.35; + text-align: center; +} +.refund-guarantee--compact i { + color: #e53935; + font-size: 0.88rem; + flex-shrink: 0; +} +.refund-guarantee--cta { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + margin: 14px 0 0; + color: #e8e8ee; + font-size: 0.95rem; + font-weight: 600; + line-height: 1.4; + letter-spacing: 0.01em; +} +.refund-guarantee--cta i { + color: #e53935; + font-size: 0.95rem; + flex-shrink: 0; +} +.refund-guarantee--cta span { + white-space: nowrap; +} +.refund-guarantee--checkout { + display: flex; + align-items: flex-start; + gap: 12px; + margin: 12px 0 16px; + padding: 14px 16px; + background: #14141c; + border: 1px solid #2a2a36; + border-left: 3px solid #e53935; + border-radius: 10px; + color: #aaa; + font-size: 0.9rem; + line-height: 1.5; +} +.refund-guarantee--checkout i { + color: #e53935; + font-size: 1.05rem; + margin-top: 2px; + flex-shrink: 0; +} +.refund-guarantee--checkout p { margin: 0; } +@media (max-width: 640px) { + .refund-guarantee--pricing { + grid-template-columns: 1fr; + gap: 12px; + padding: 16px; + } + .refund-guarantee--pricing .refund-guarantee__icon { + width: 36px; + height: 36px; + font-size: 0.95rem; + border-radius: 10px; + } + .refund-guarantee__kicker { display: inline; } + .refund-guarantee--pricing .refund-guarantee__subtitle { display: none; } + .refund-guarantee__title { font-size: 0.98rem; } + .refund-guarantee__body { font-size: 0.86rem; } + .refund-guarantee--compact { + font-size: 0.76rem; + padding-top: 8px; + margin-top: 10px; + } + .refund-guarantee--cta { + font-size: 0.88rem; + gap: 6px; + margin-top: 12px; + } +} .site-footer { border-top: 1px solid #252530; padding: 32px 0; margin-top: 40px; color: #888; font-size: 0.88rem; } .site-footer .wrap { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 16px; align-items: center; } .site-footer__brand { @@ -2627,6 +2788,7 @@ body.nav-menu-open { overflow: hidden; } border-radius: 12px; margin-bottom: 10px; padding: 0 18px; + scroll-margin-top: 88px; } .faq-item summary { cursor: pointer; @@ -2646,6 +2808,7 @@ body.nav-menu-open { overflow: hidden; } .faq-item p { color: #aaa; margin: 0 0 16px; line-height: 1.55; font-size: 0.95rem; } .legal-doc { max-width: 760px; padding-top: 24px; padding-bottom: 48px; color: #bbb; line-height: 1.65; font-size: 0.95rem; } +.legal-doc section { scroll-margin-top: 88px; } .legal-doc h1 { color: #fff; font-size: 1.6rem; margin-bottom: 8px; } .legal-doc h2 { color: #fff; font-size: 1.1rem; margin: 28px 0 10px; } .legal-doc h3 { color: #ddd; font-size: 1rem; margin: 20px 0 8px; } diff --git a/backend/public/site-analytics.js b/backend/public/site-analytics.js index 32f339a..fe95da5 100644 --- a/backend/public/site-analytics.js +++ b/backend/public/site-analytics.js @@ -283,6 +283,27 @@ }); } + function trackNamedEvent(name) { + if (!name) return; + if (typeof window.gtag === "function") { + window.gtag("event", name, { event_category: "engagement" }); + } + } + + function onNamedEventClick(event) { + var target = event.target; + if (!(target instanceof Element)) return; + var el = target.closest("[data-mltv-event-click]"); + if (!el) return; + trackNamedEvent(el.getAttribute("data-mltv-event-click")); + } + + function onDetailsToggle(event) { + var el = event.target; + if (!(el instanceof HTMLDetailsElement) || !el.open) return; + trackNamedEvent(el.getAttribute("data-mltv-event")); + } + function start() { if (started) return; if (excludedPath(location.pathname)) return; @@ -310,6 +331,9 @@ window.mltvSiteAnalyticsStart = start; + document.addEventListener("click", onNamedEventClick, true); + document.addEventListener("toggle", onDetailsToggle, true); + if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", start); } else { diff --git a/backend/spec/requests/public/pricing_page_spec.rb b/backend/spec/requests/public/pricing_page_spec.rb index 4d872b9..4b1a1c8 100644 --- a/backend/spec/requests/public/pricing_page_spec.rb +++ b/backend/spec/requests/public/pricing_page_spec.rb @@ -26,6 +26,11 @@ RSpec.describe "Public pricing page", type: :request do expect(response.body).to include("Account trasmettitori") expect(response.body).to include("Niente password condivise") expect(response.body).to include("plan-card--featured") + expect(response.body).to include("Soddisfatti o rimborsati") + expect(response.body).to include("30 giorni soddisfatti o rimborsati") + expect(response.body).to include("ti rimborsiamo il 100%") + expect(response.body).to include("Archivio replay") + expect(response.body).not_to include("Replay server") expect(response.body).not_to include("a vita") expect(response.body).not_to include("Più popolare") end diff --git a/backend/spec/requests/public/refund_guarantee_spec.rb b/backend/spec/requests/public/refund_guarantee_spec.rb new file mode 100644 index 0000000..ea9a842 --- /dev/null +++ b/backend/spec/requests/public/refund_guarantee_spec.rb @@ -0,0 +1,40 @@ +require "rails_helper" + +RSpec.describe "Money-back guarantee", type: :request do + before { load Rails.root.join("db/seeds/plans.rb") } + + it "mostra la garanzia in homepage nella sezione piani, non nella hero" do + get root_path + + expect(response).to have_http_status(:ok) + expect(response.body).to include("Soddisfatti o rimborsati entro 30 giorni") + hero, rest = response.body.split("plans-teaser", 2) + expect(hero).not_to include("Soddisfatti o rimborsati entro 30 giorni") + expect(rest).to include("Soddisfatti o rimborsati entro 30 giorni") + end + + it "mostra FAQ e ancora verso i Termini" do + get public_faq_path + + expect(response).to have_http_status(:ok) + expect(response.body).to include("Come funziona la garanzia Soddisfatti o rimborsati?") + expect(response.body).to include("id=\"faq-garanzia\"") + expect(response.body).to include("intero importo pagato") + expect(response.body).to include("garanzia-rimborso") + end + + it "aggiunge la clausola 3-bis nei Termini" do + get public_termini_path + + expect(response).to have_http_status(:ok) + expect(response.body).to include("3-bis. Garanzia Soddisfatti o rimborsati") + expect(response.body).to include("id=\"garanzia-rimborso\"") + expect(response.body).to include("100%") + expect(response.body).to include("31 agosto 2026") + expect(response.body).to include("valutare Match Live TV nel normale utilizzo") + expect(response.body).to include("copertura intensiva di un singolo evento o torneo") + expect(response.body).not_to include("palesemente abusivi") + expect(response.body).not_to include("rimborso al netto") + expect(response.body).not_to include("IVA esclusa") + end +end