137 lines
7.4 KiB
Markdown
137 lines
7.4 KiB
Markdown
# 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()`:
|
||
|
||
```js
|
||
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:
|
||
```html
|
||
<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>`.
|
||
|
||
```html
|
||
<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:
|
||
|
||
```html
|
||
<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 depth‑3 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.
|