Free Mailchimp Alternative
AI runs online
not yet reviewed by publik. It is live now; the founder has not reviewed this version yet.
OpenCampaign
open source · on publik
Prices are for one typical use: one request of about 1,500 words sent and 375 words back. A higher quality score is better.
Not checked yet: publik has not read whether OpenCampaign can run its AI on your computer.
| Model | Quality | Per 1,000 uses |
|---|---|---|
| On your computer (Ollama, 4-bit download size) | ||
| Granite 4.2 3B2.2 GB | 9 | $0 |
| Phi-4 Mini2.5 GB | 6 | $0 |
| Llama 3.1 8B4.9 GB | 7 | $0 |
| gpt-oss 20B14 GB | 9 | $0 |
| Gemma 4 31B20 GB | 19* | $0 |
| Qwen3.5 35B-A3B24 GB | 19* | $0 |
| publik API | ||
| publik-fastGLM-5.3 Flash | 42 | $1.00 |
| publik-balancedMiMo-V2.6-Pro · OpenCampaign | 46 | $10.00 |
| publik-smartGPT-6 Sol | 48 | $18.00 |
Quality: Artificial Analysis Intelligence Index v4.3.2, read 2026-09-22 (publik API models 2026-09-25); * = estimated by Artificial Analysis. Sizes: the Ollama library, read 2026-09-22.
Every step written out. No terminal experience needed. Pick your setup.
Self-hosted email marketing: accounts, campaigns, audiences, automations, signup forms, open/click tracking and AI-assisted campaign review — in one Next.js app backed by SQLite.
{{first_name}}, {{company}}, …), test sends, and a guided send flow with simulation mode.No demo data ships with the app — workspaces start empty, so dashboards and reports only ever show your real numbers.
| Variable | Purpose |
|---|---|
DATABASE_URL | SQLite file path, e.g. file:./db/custom.db |
APP_URL | Public base URL used in tracking links, pixels and unsubscribe URLs |
Everything else (SMTP credentials, AI keys) is configured in the app under Settings and stored in the database — no extra env vars needed.
Open any campaign → AI review → Analyze campaign. Four interchangeable engines, all returning the same score / strengths / issues / suggestions / subject-ideas report. Keys are stored per account and can be tested from Settings → AI analysis:
| Provider | Notes |
|---|---|
| Local | Built-in heuristics: subject quality, spam trigger words, caps/punctuation, image-to-text balance, link count, CTA verbs, personalization, unsubscribe compliance. No key, nothing leaves the server. |
| OpenRouter | Uses your key and picks a free model automatically — fetches the live model list, filters for $0/$0 pricing, prefers strong known free models, retries down the list. Caches for an hour. |
| OpenAI | Chat Completions with JSON-mode output (gpt-4o-mini). |
| PublikHQ | Posts to a PublikHQ-compatible AI endpoint. |
PublikHQ endpoint contract
POST {publikhqUrl}/api/v1/ai/analyze
Authorization: Bearer {apiKey}
{ "campaign": { "name", "subject", "previewText", "content", "fromName", "fromEmail" } }
Responses are parsed flexibly: a JSON object with score / summary / strengths / issues / suggestions / subjectIdeas, the same wrapped in { "data": … }, a { "analysis" | "content" | "text": "…" } string (JSON or prose), or raw prose — which is then merged with local scoring. When OpenCampaign itself is deployed on publikhq.com, set the endpoint to your own domain for fully self-hosted AI.
The dashboard pings POST /api/automations/process every 60 s. For server-side processing independent of the UI, add a cron:
* * * * * curl -fsS -X POST https://your-domain.com/api/automations/process > /dev/null
A record for publikhq.com (and www) at your server's IP.git clone <your-repo-url> opencampaign && cd opencampaign
APP_URL=https://publikhq.com docker compose up -d --build
Schema migration and server start happen automatically; SQLite persists in the opencampaign-data volume.
# /etc/caddy/Caddyfile
publikhq.com, www.publikhq.com {
reverse_proxy localhost:3000
}
sudo systemctl reload caddy
Caddy issues and renews certificates automatically. (Nginx + certbot works the same way: proxy_pass http://127.0.0.1:3000; with standard upgrade headers.)
git clone <your-repo-url> opencampaign && cd opencampaign
npm install
cp .env.example .env # DATABASE_URL=file:/var/lib/opencampaign/app.db APP_URL=https://publikhq.com
npm run db:push
npm run build
npx pm2 start "npm run start:node" --name opencampaign
pm2 save && pm2 startup
Then reverse-proxy port 3000 as above.
Set these on the platform dashboard:
| Setting | Value |
|---|---|
| Build command | npm install && npm run build |
| Start command | npm run start:node |
| Env vars | DATABASE_URL (persistent disk path!), APP_URL=https://publikhq.com, NODE_ENV=production |
SQLite needs a persistent disk mounted at the path in DATABASE_URL. On ephemeral filesystems use a hosted Postgres/MySQL by swapping the Prisma datasource in prisma/schema.prisma.
APP_URL set to https://publikhq.com (tracking links in emails must be absolute and public)./settings: sender defaults, SMTP credentials, AI provider + keys.src/
app/
page.tsx # auth gate + single-page app shell (sidebar + views)
api/ # REST API + auth + tracking endpoints
auth/{signup,signin,signout,me,password}
campaigns/[id]/{send,test,analyze}
contacts/{import,export}
automations/process # cron-friendly job processor
track/{open,click,unsubscribe}/[token]
signup # public form endpoint (routes by account id)
components/oc/ # feature views (auth, dashboard, campaigns, audience, …)
lib/
ai/ # local engine + openrouter + openai + publikhq
auth.ts # scrypt hashing, sessions, per-account settings
mail.ts # personalization, tracking rewrite, SMTP
automations.ts # enqueue + process due jobs
csv.ts, oc-client.ts, db.ts
prisma/
schema.prisma # data model (User, Session, Campaign, Contact, …)
No seed script — accounts start empty on purpose.
MIT — see LICENSE.