msos/docs/newsletter-signup.md

7.4 KiB
Raw Blame History

Standard: Newsletter signup (MailerLite)

Status: established convention — follow it on every page that should collect email subscribers. Audience: anyone (human or AI agent) adding a newsletter signup to this site.

This documents the one and only way we add a "subscribe to our newsletter" form. It is already wired to MailerLite through main.js; you do not write any JavaScript. You only paste HTML.


1. How it works (read this once)

  • All subscribe forms are handled centrally by setupNewsletter() in main.js (section 7).
  • On page load it finds every form.subscribe-form and form.subscribe-form-bottom, and:
    • forces the input to type="email", name="fields[email]", required,
    • inserts a live status message element after the form,
    • on submit: validates the email, then POSTs to MailerLite's JSONP endpoint,
    • shows a localized success / error / "sending" message (EN / SI / MK).
  • MailerLite uses double opt-in: the subscriber gets a confirmation email. The success message intentionally says "check your inbox to confirm".

MailerLite config lives in one place — main.js, setupNewsletter():

const ML_ACCOUNT = '1253161';
const ML_FORM    = '194374752800868123';

To point the whole site at a different MailerLite audience/form, change those two values only. (They come from MailerLite → Forms → Embedded forms → your form → the subscribe URL https://assets.mailerlite.com/jsonp/<ACCOUNT>/forms/<FORM>/subscribe.)


2. Two non-negotiable requirements

  1. The page must load main.js. Without it the form is dead. Check for:

    <script src="{{PREFIX}}main.js"></script>
    

    just before </body>. If a page has its own script (e.g. news-filter.js), load main.js as well, before it. (This was the exact bug on the News hub page — it shipped without main.js, so its form — and its header dropdowns — didn't work.)

  2. Use the exact class names. subscribe-form-bottom (full band, the default) or subscribe-form (compact hero). No other class is auto-wired.


3. The snippet (default — full "band" CTA)

This is the standard block shown above the footer on content pages (News, articles, projects, get-to-know…). Paste it just before </main>.

<section class="newsletter-cta">
    <div class="container">
        <div class="cta-content">
            <h2>{{HEADING}}</h2>
            <p>{{SUBTITLE}}</p>
            <form class="subscribe-form-bottom">
                 <div class="input-wrapper">
                    <input type="email" placeholder="{{PLACEHOLDER}}">
                 </div>
                <button type="submit" class="btn btn-primary-orange">{{BUTTON}}</button>
            </form>
            <p class="privacy-note">{{PRIVACY_TEXT}} <a href="{{PREFIX}}{{LANG}}/privacy-policy/">{{PRIVACY_LINK}}</a>{{PRIVACY_SUFFIX}}</p>
        </div>
    </div>
</section>

Styling is already defined in css/pages/_article.css (.newsletter-cta, .subscribe-form-bottom, .privacy-note) and is globally available via main.css. Nothing to add.

Compact variant (hero)

When you want it inline under a page hero (as on the get-to-know pages), use the smaller form — same wiring, no band wrapper:

<form class="subscribe-form">
    <input type="email" placeholder="{{PLACEHOLDER}}">
    <button type="submit" class="btn btn-primary-orange">{{BUTTON}}</button>
</form>
<p class="privacy-note">{{PRIVACY_TEXT}} <a href="{{PREFIX}}{{LANG}}/privacy-policy/">{{PRIVACY_LINK}}</a>{{PRIVACY_SUFFIX}}</p>

4. {{PREFIX}} — the relative path to the site root

Count the folders between the page and the repo root; that's how many ../ you need.

Page location (example) {{PREFIX}}
en/index.html ../
en/news/index.html ../../
en/news/proof-of-means-updated-2026/index.html ../../../

So the privacy link on a depth3 article is ../../../en/privacy-policy/, and the script tag is ../../../main.js. Get this wrong and the link/JS 404s.


5. Copy — fill the placeholders per language

Always ship all three languages (en/, si/, mk/) — the site is fully mirrored.

Honest copy only. Do not reuse the legacy "Join 2,000+ subscribers" heading that still appears on some older pages — we don't have that many subscribers. Tailor the heading to the page. The values below are the current News-section standard:

Field EN MK SI
{{HEADING}} Never miss an MSOS update Не пропуштајте ниту една новост од МСОС Ne zamudite nobene novice MSOS
{{SUBTITLE}} News, announcements and open calls — straight to your inbox. Вести, соопштенија и отворени повици — директно во вашето сандаче. Novice, obvestila in razpisi — naravnost v vaš e-poštni predal.
{{PLACEHOLDER}} Enter your email Внесете ја вашата е-пошта Vnesite svoj e-mail
{{BUTTON}} Subscribe Претплати се Naroči se
{{PRIVACY_TEXT}} We care about your data in our Ние се грижиме за вашите податоци во нашата Skrbimo za vaše podatke v naši
{{PRIVACY_LINK}} privacy policy политика за приватност politiki zasebnosti
{{PRIVACY_SUFFIX}} (empty) (empty) .

Change {{HEADING}} / {{SUBTITLE}} to fit the page's purpose; keep the rest as-is for consistency.


6. Checklist before you call it done

  • Block pasted before </main> (band) or under the hero (compact).
  • {{PREFIX}} correct for the page depth (privacy link and the main.js script tag).
  • Page loads main.js (added before any page-specific script).
  • All three languages updated (en/, si/, mk/).
  • Copy is honest (no fake subscriber counts).
  • Tested locally: on load the input gets name="fields[email]" and a .subscribe-status element appears after the form; an invalid email shows the "valid email" error. Do not submit a real address while testing — it lands in the live MailerLite audience.