drop-marketing-infra-spec
Drop Marketing Infrastructure — Implementation Spec
Project: Drop (Fintech Payment App) Task: MC #1197 Date: 2026-02-17 Author: John (AI Director) Status: Draft — Awaiting Approval
1. Executive Summary
Drop currently has a basic landing page (getdrop.no) with waitlist functionality but lacks comprehensive marketing infrastructure to support user acquisition, retention, and viral growth. This spec defines the complete marketing technology stack covering:
- Landing page optimization and conversion tracking
- SEO strategy for Norwegian fintech market
- App Store/Play Store listing preparation
- Referral system with fraud prevention
- Campaign tracking (UTM parameters and attribution)
- Email marketing integration
- A/B testing framework
- Analytics and reporting
Core Principles:
- Norwegian-first: All copy, SEO, and campaigns prioritize Norwegian market
- GDPR + markedsføringsloven compliant: Strict consent management
- Pass-through branding: Drop never holds money — emphasize transparency
- Viral growth: Referral program as primary acquisition channel
- Data-driven: Every decision backed by metrics
2. Current State Assessment
2.1 What Exists
Landing Page (getdrop.no):
- Single-page marketing site with hero, features, how-it-works, CTA
- Waitlist form (
POST /api/waitlist) with honeypot anti-spam - Mobile-responsive design (DM Sans + Fraunces fonts)
- Basic SEO meta tags (title, description, og:tags)
- Trust signals: "Regulert i Norge", "0.5% gebyr", "30+ land"
- Deployed to Vercel (pages/ directory for static content)
<title>Drop — Send penger. Enklere. Billigere.</title>
<meta name="description" content="Drop er den nye standarden for internasjonale overforinger i Skandinavia. 0,5% gebyr. QR-betaling i butikk. Regulert i Norge.">
<meta property="og:title" content="Drop — Enklere betalinger. Lavere gebyrer.">
<meta property="og:description" content="Send penger til 30+ land med 0,5% gebyr. QR-betaling i butikk. Regulert i Norge.">
<meta property="og:image" content="https://getdrop.no/drop-logo.png">
Branding:
- Logo: Green rounded square with white $ icon + gold dot
- Colors:
--drop-green: #0B6E35,--drop-gold: #D4A017 - Tagline: "Enklere betalinger. Lavere gebyrer."
- Value props: 0.5% remittance fee, 1% merchant QR fee, 30+ countries
Domain:
- Primary: getdrop.no (registered via one.com)
- drop.no owned by TV2 (not available)
2.2 What's Missing
Critical Gaps:
- No conversion tracking (Google Analytics, Plausible, or similar)
- No UTM parameter handling for campaign attribution
- No App Store/Play Store listings (not launched)
- No referral system (database schema or logic)
- No email marketing integration (Resend configured but no campaigns)
- No A/B testing framework
- No SEO sitemap or robots.txt
- No structured data (JSON-LD) for rich snippets
- No blog/content marketing infrastructure
- No social media presence (@dropnorge handles not claimed)
Legal/Compliance Gaps:
- Marketing consent collection not integrated with email system
- No cookie consent banner (required for analytics tracking)
- No marketing-specific terms in vilkår.html
3. Landing Page Optimization
3.1 Conversion Optimization
Goal: Convert 25% of visitors to waitlist signups (industry benchmark: 15-20%)
Improvements:
A. Hero Section
Current state: Generic CTA "Last ned gratis" (app not available yet)
Optimization:
<!-- Replace generic CTA with value-focused copy -->
<div class="hero-actions">
<a class="btn-gradient" href="#cta">Bli med på ventelisten</a>
<span class="hero-cta-subtext">De første 1000 får 5 gratis overføringer</span>
</div>
Value Prop Enhancement:
- Add "Ingen binding. Ingen skjulte kostnader." under CTA
- Add trust badge: "Regulert av Finanstilsynet" (when applicable)
- Replace phone mockup with actual app screenshot from Figma Make export
B. Social Proof
Current state: Generic testimonial placeholders
Add Real Metrics (when available):
<div class="trust-bar">
<div class="trust-item">
<div class="trust-number">2,340</div>
<div class="trust-label">På ventelisten</div>
</div>
<div class="trust-item">
<div class="trust-number">kr 12M</div>
<div class="trust-label">Spart i gebyrer (demo)</div>
</div>
<div class="trust-item">
<div class="trust-number">4.8★</div>
<div class="trust-label">Snittrating (beta)</div>
</div>
</div>
Source: Pull waitlist count from database, update dynamically
C. Features Section
Current state: 3 feature cards (Send, QR, Wallet)
Optimization:
- Add FAQ accordion below features: "Er Drop en bank?" → "Nei, vi er en betalingstjeneste..."
- Add comparison table: Drop vs. Western Union vs. Wise vs. Banks
Comparison Table:
<table class="comparison-table">
<thead>
<tr><th>Tjeneste</th><th>Gebyr</th><th>Hastighet</th><th>Lojalitet</th></tr>
</thead>
<tbody>
<tr><td><strong>Drop</strong></td><td>0.5%</td><td>Minutter</td><td>Bonuspoeng</td></tr>
<tr><td>Western Union</td><td>5-10%</td><td>1-3 dager</td><td>—</td></tr>
<tr><td>Wise</td><td>0.7-1.2%</td><td>1-2 dager</td><td>—</td></tr>
<tr><td>Tradisjonell bank</td><td>50-200 kr + FX</td><td>3-5 dager</td><td>—</td></tr>
</tbody>
</table>
D. CTA Section
Current state: Email input + submit button
Optimization:
- Add GDPR-compliant marketing consent checkbox
- Add "Hva skjer etter?" explainer below form:
1. Du får bekreftelses-epost 2. Vi varsler deg når appen lanseres (Mars 2026) 3. Du får tidlig tilgang før alle andre - Add exit-intent popup (trigger on mouse leave): "Vent! Ta med 100 kr gratis når du registrerer deg nå."
3.2 Mobile Optimization
Issues:
- Phone mockup too large on mobile (600px → overflow)
- Nav menu doesn't collapse properly
Fixes:
@media (max-width: 480px) {
.phone { width: 240px; height: 480px; } /* Already implemented */
.hero { padding-top: 100px; } /* Reduce top padding */
.hero h1 { font-size: 28px; line-height: 1.2; }
.hero p { font-size: 15px; }
}
Mobile CTA Sticky Bar: Add persistent bottom bar on mobile with CTA:
<div class="mobile-cta-bar">
<a href="#cta" class="btn-gradient">Registrer deg gratis</a>
</div>
3.3 Page Speed
Current Performance (estimate):
- FCP (First Contentful Paint): ~1.5s
- LCP (Largest Contentful Paint): ~2.5s
- CLS (Cumulative Layout Shift): 0.05
Optimizations:
- Preload hero fonts:
<link rel="preload" href="..." as="font"> - Lazy load phone mockup below fold
- Add
loading="lazy"to all images except hero - Minify CSS (inline critical CSS, defer non-critical)
- Add service worker for offline caching (PWA)
Target Metrics:
- FCP: < 1.2s
- LCP: < 2.0s
- CLS: < 0.1
- Lighthouse Score: 95+
4. SEO Strategy
4.1 Target Keywords (Norwegian)
Primary Keywords (High Volume, High Intent):
| Keyword | Monthly Searches (est.) | Difficulty | Priority |
|---|---|---|---|
| send penger utlandet | 1,200 | Medium | HIGH |
| billig pengeoverføring | 800 | Low | HIGH |
| internasjonale overføringer | 600 | Medium | HIGH |
| qr betaling norge | 400 | Low | MEDIUM |
| vipps alternativ | 300 | High | MEDIUM |
| western union alternativ | 250 | Low | HIGH |
| wise alternativ | 200 | Low | MEDIUM |
| mobilbetaling | 1,500 | High | LOW |
Long-tail Keywords:
- "hvor mye koster det å sende penger til utlandet"
- "billigste måte å sende penger til utlandet"
- "qr kode betaling butikk"
- "send penger uten gebyr"
English Keywords (Secondary — expat market):
- "send money from norway"
- "international money transfer norway"
- "cheap remittance norway"
4.2 On-Page SEO Implementation
A. Meta Tags Enhancement
Homepage:
<title>Send Penger Utlandet — 0.5% Gebyr | Drop Norge</title>
<meta name="description" content="Send penger til 30+ land med bare 0.5% gebyr. Raskere enn banker, billigere enn Western Union. Regulert i Norge. Registrer deg gratis.">
<meta name="keywords" content="send penger utlandet, billig pengeoverføring, internasjonale overføringer, qr betaling, vipps alternativ">
<link rel="canonical" href="https://getdrop.no/">
Subpages (need to be created):
/send-penger— Dedicated remittance page/qr-betaling— QR payment explainer/priser— Pricing comparison/hvordan-det-virker— How it works (detailed)/sikkerhet— Security explainer
B. Structured Data (JSON-LD)
Organization Schema:
{
"@context": "https://schema.org",
"@type": "FinancialService",
"name": "Drop",
"alternateName": "Drop Norge",
"url": "https://getdrop.no",
"logo": "https://getdrop.no/drop-logo.png",
"description": "Internasjonale pengeoverføringer og QR-betaling i Norge",
"address": {
"@type": "PostalAddress",
"addressCountry": "NO"
},
"sameAs": [
"https://facebook.com/dropnorge",
"https://instagram.com/dropnorge",
"https://linkedin.com/company/drop-norge"
]
}
FAQ Schema (for FAQ section):
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "Er Drop en bank?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Nei, Drop er ikke en bank. Vi er en betalingstjeneste som bruker din eksisterende bankkonto via BankID. Pengene dine forblir i din bank."
}
},
{
"@type": "Question",
"name": "Hvor mye koster det å sende penger?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Drop tar 0.5% gebyr på internasjonale overføringer. Ingen skjulte kostnader. Du ser alltid totalprisen før du sender."
}
}
]
}
C. Sitemap.xml
Generate dynamic sitemap:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://getdrop.no/</loc>
<lastmod>2026-02-17</lastmod>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://getdrop.no/pages/send-penger.html</loc>
<changefreq>monthly</changefreq>
<priority>0.9</priority>
</url>
<url>
<loc>https://getdrop.no/pages/qr-betaling.html</loc>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://getdrop.no/pages/priser.html</loc>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
</url>
<!-- Add all subpages -->
</urlset>
Submit to:
- Google Search Console
- Bing Webmaster Tools
D. Robots.txt
User-agent: *
Allow: /
Disallow: /api/
Sitemap: https://getdrop.no/sitemap.xml
4.3 Off-Page SEO
A. Backlink Strategy
Target Sources:
- Norwegian fintech blogs: kryptografen.no, shifter.no, digi.no
- Business directories: proff.no, 1881.no (ALAI Holding AS listing → link to Drop)
- Press releases: mynewsdesk.com, newswire.no
- Partner pages: SpareBank 1 partner page (if approved)
- LinkedIn articles: Alem's personal posts about Drop
Content for Outreach:
- "Slik sparer nordmenn penger på internasjonale overføringer"
- "Drop vs. Western Union: Detaljert sammenligning"
- "Hvorfor vi bygde et nytt betalingsalternativ for Skandinavia"
B. Local SEO
Google My Business (when applicable):
- List Drop under ALAI Holding AS
- Category: "Financial Service"
- Add getdrop.no as website
- Upload Drop logo
Local Citations:
- Register on gulesider.no (if relevant)
- Add to fintech.no directory
4.4 Technical SEO
Checklist:
- HTTPS enabled (Vercel default)
- Canonical tags on all pages
- Hreflang tags for NO/EN (if English landing page added)
- XML sitemap submitted
- robots.txt configured
- 404 page with CTA to homepage
- Redirect strategy (301 for old Zica URLs if any)
- Mobile-friendly test passed
- Core Web Vitals optimized
Hreflang Example (if English page added):
<link rel="alternate" hreflang="no" href="https://getdrop.no/" />
<link rel="alternate" hreflang="en" href="https://getdrop.no/en/" />
<link rel="alternate" hreflang="x-default" href="https://getdrop.no/" />
5. App Store / Play Store Listing Preparation
5.1 App Store Optimization (ASO) Strategy
Goal: Rank in top 5 for "send penger" and "pengeoverføring" in Norwegian App Store
Primary Keywords (App Store):
- send penger (High volume)
- pengeoverføring (Medium volume)
- qr betaling (Medium volume)
- internasjonale overføringer (Low volume)
Secondary Keywords:
- billig, lavere gebyrer, vipps alternativ, remittance, money transfer
5.2 App Store Listing (iOS)
A. App Name (30 chars)
Drop: Send Penger & QR Betal
Rationale: Includes primary keyword "Send Penger" + brand
B. Subtitle (30 chars)
0.5% gebyr. Regulert i Norge
Rationale: USP (0.5% fee) + trust signal (regulated)
C. Promotional Text (170 chars)
De første 1000 brukerne får 5 gratis overføringer. 🎉
Send penger til 30+ land med bare 0.5% gebyr. Betal i butikk med QR. Enklere enn Vipps. Billigere enn Western Union.
Rationale: Urgency + value props + social proof comparison
D. Description (4000 chars)
# Send Penger. Enklere. Billigere.
Drop er den nye standarden for internasjonale pengeoverføringer i Skandinavia. Vi gjør det enkelt, trygt og billig å sende penger til familie og venner i utlandet.
## Hvorfor Drop?
✅ **0.5% gebyr** — Ikke 5%, ikke 10%. Bare 0.5% på alle overføringer.
✅ **30+ land** — Send til Europa, Asia, Afrika, Amerika.
✅ **Minutter, ikke dager** — Pengene er fremme på minutter, ikke 3-5 virkedager.
✅ **Regulert i Norge** — Trygt og lovlig. Pengene dine er sikre.
✅ **Ingen skjulte kostnader** — Hva du ser er hva du betaler.
## Slik fungerer det
1. **Registrer deg** med BankID (tar 2 minutter)
2. **Velg mottaker** og land
3. **Skriv inn beløp** — se gebyret med en gang
4. **Send** direkte fra din bankkonto
5. **Ferdig** — mottaker får pengene på minutter
## QR-betaling i butikk
Betal i butikk med QR-kode. Ingen kort. Ingen kontanter. Bare skann og betal.
- Støtter alle butikker med Drop QR
- 1% merchant-gebyr (billigere enn kortterminaler)
- Kvittering direkte i appen
## Sikkerhet
- BankID-pålogging (samme sikkerhet som nettbanken din)
- Pengene forblir i din bank (Drop holder aldri på pengene dine)
- Kryptert kommunikasjon (samme standard som banker)
- To-faktor autentisering på alle transaksjoner
## Drop vs. konkurrentene
| Tjeneste | Gebyr | Hastighet |
|----------|-------|-----------|
| Drop | 0.5% | Minutter |
| Western Union | 5-10% | 1-3 dager |
| Wise | 0.7-1.2% | 1-2 dager |
| Tradisjonell bank | 50-200 kr + FX | 3-5 dager |
## Pass-through modell
Drop er IKKE en bank. Vi holder aldri på pengene dine. Alt går direkte fra din bankkonto til mottaker via Open Banking (PSD2). Dette gjør oss tryggere og billigere enn tradisjonelle tjenester.
## Hvem er Drop for?
- Nordmenn som sender penger hjem til familie i utlandet
- Expats som betaler regninger i hjemlandet
- Studenter som får penger fra foreldre i utlandet
- Alle som er lei av høye bankgebyrer
## Presse
"Drop kan bli det nordmenn trenger for billigere pengeoverføringer."
— [Placeholder for actual press quote]
## Kontakt oss
[email protected]
https://getdrop.no
---
Drop er et produkt av ALAI Holding AS (org.nr 932 516 136).
Lanseres i Norge 2026.
E. Keywords (100 chars)
send penger,pengeoverføring,qr betaling,internasjonale,billig,vipps,remittance,money transfer,gebyr
Rationale: Mix of Norwegian (primary) and English (expat market)
F. Screenshots (6.7" iPhone)
Order of Screenshots (psychological funnel):
-
Hero/Dashboard — Shows total balance + "Send" and "QR Betal" buttons
- Caption: "Din banksaldo. Alle transaksjoner. Én app."
-
Send Money Flow — Shows "Velg land" → "Skriv beløp" → "Se gebyr" → "Send"
- Caption: "Send til 30+ land med 0.5% gebyr"
-
Fee Comparison — Visual chart: Drop (0.5%) vs Western Union (7%) vs Wise (1%)
- Caption: "Spar opptil 90% på gebyrer"
-
QR Payment — Shows QR scanner screen + "Skann og betal"
- Caption: "Betal i butikk med QR-kode"
-
Transaction History — Shows recent transactions with dates, amounts, statuses
- Caption: "Full kontroll over alle transaksjoner"
-
Security Screen — Shows BankID logo + lock icon + "Pengene forblir i din bank"
- Caption: "Trygt med BankID og PSD2"
Design Notes:
- Use actual Figma Make export screenshots (from mockups/figma-make-export/)
- Add captions in white text with green background
- Ensure all text is legible (16pt minimum)
- No placeholder content ("Lorem ipsum") — real data only
G. App Preview Video (30 sec)
Storyboard:
- 0-5s: Problem — "Sender du penger hjem?" → show high Western Union fees
- 5-10s: Solution — "Drop gir deg 0.5% gebyr" → show app interface
- 10-15s: Demo — Show send flow (select country → amount → confirm)
- 15-20s: QR feature — Show QR scan + payment confirmation
- 20-25s: Social proof — "2,340 nordmenn på ventelisten"
- 25-30s: CTA — "Last ned gratis i dag" → App Store badge
Voiceover Script (Norwegian):
Sender du penger hjem? Western Union tar opptil 10% gebyr.
Med Drop tar vi bare 0.5%. Pengene er fremme på minutter.
Velg land. Skriv beløp. Send. Ferdig.
Betal i butikk med QR. Ingen kort. Ingen kontanter.
Over 2,000 nordmenn bruker allerede Drop.
Last ned gratis i dag.
5.3 Google Play Store Listing
Differences from App Store:
- Title: 30 chars (same as iOS)
- Short Description: 80 chars
Send penger til 30+ land med 0.5% gebyr. QR-betaling i butikk. Regulert i Norge. - Full Description: 4000 chars (same as iOS)
- Graphic Assets:
- Feature Graphic: 1024x500 (banner)
- Icon: 512x512 (already have drop-logo.png)
- Screenshots: 1080x1920 (Android ratio)
Category:
- Primary: Finance
- Secondary: Payments
Content Rating:
- Everyone (PSD2 compliance → 18+ enforced in-app, not store rating)
5.4 Localization Strategy
Phase 1 (Launch): Norwegian only Phase 2 (3 months post-launch): Add English for expats Phase 3 (6 months): Swedish, Danish (Nordic expansion)
Translation Requirements:
- App Store/Play Store listings
- In-app UI strings (already in Norwegian via Figma Make)
- Support docs (FAQ, Help Center)
- Email templates (already covered in email spec)
6. Referral System
6.1 Referral Mechanics
Goal: 65% of new users from referrals (Revolut benchmark)
Incentive Structure (Dual-Sided):
| Action | Referrer Reward | Referee Reward |
|---|---|---|
| Sign up + verify BankID | 0 kr | 0 kr |
| First transfer (min 500 kr) | 50 kr credit | 50 kr credit |
| Second transfer (within 30 days) | +25 kr bonus | — |
Credit Usage:
- Credits apply to next transfer fee (reduces 0.5% fee)
- 50 kr credit = free transfer up to 10,000 kr (0.5% of 10k = 50 kr)
- Credits expire after 90 days (encourages usage)
Cap: Max 500 kr in credits per user per month (prevents farming)
Example Flow:
- Referrer (Maria) shares link:
getdrop.no?ref=maria123 - Referee (Sara) clicks → signs up → sees banner: "Maria inviterte deg. Dere får begge 50 kr når du sender din første overføring."
- Sara verifies BankID → completes first transfer (1,000 kr) → gets 50 kr credit
- Maria gets notification: "Sara brukte din lenke. Du fikk 50 kr!" → Maria's next transfer is discounted
6.2 Database Schema
A. referral_codes Table
CREATE TABLE IF NOT EXISTS referral_codes (
id TEXT PRIMARY KEY, -- ref_abc123
user_id TEXT NOT NULL UNIQUE, -- Owner of code
code TEXT UNIQUE NOT NULL, -- Short code (6 chars, alphanumeric)
referral_link TEXT NOT NULL, -- https://getdrop.no?ref={code}
clicks INTEGER DEFAULT 0, -- Link clicks
signups INTEGER DEFAULT 0, -- Successful signups
conversions INTEGER DEFAULT 0, -- First transfer completions
total_earned_credits REAL DEFAULT 0,-- Total credits earned (kr)
created_at TEXT DEFAULT (datetime('now')),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE INDEX idx_referral_codes_user ON referral_codes(user_id);
CREATE INDEX idx_referral_codes_code ON referral_codes(code);
Code Generation Logic:
// Generate 6-char alphanumeric code (no ambiguous chars: 0, O, I, l)
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
let code = '';
for (let i = 0; i < 6; i++) {
code += chars[Math.floor(Math.random() * chars.length)];
}
// Example: "MK3P7Z"
B. referral_tracking Table
CREATE TABLE IF NOT EXISTS referral_tracking (
id TEXT PRIMARY KEY, -- reft_abc123
referrer_id TEXT NOT NULL, -- User who referred
referee_id TEXT NOT NULL, -- New user
referral_code TEXT NOT NULL, -- Code used
signup_at TEXT NOT NULL, -- When referee signed up
first_transfer_at TEXT, -- When referee completed first transfer
referrer_reward REAL DEFAULT 0, -- Credits given to referrer (kr)
referee_reward REAL DEFAULT 0, -- Credits given to referee (kr)
status TEXT NOT NULL CHECK(status IN ('pending','completed','cancelled')),
-- pending = signed up, not transferred yet
-- completed = first transfer done, rewards issued
-- cancelled = referee deleted account before transfer
created_at TEXT DEFAULT (datetime('now')),
FOREIGN KEY (referrer_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (referee_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE INDEX idx_referral_tracking_referrer ON referral_tracking(referrer_id);
CREATE INDEX idx_referral_tracking_referee ON referral_tracking(referee_id);
CREATE INDEX idx_referral_tracking_status ON referral_tracking(status);
C. referral_credits Table
CREATE TABLE IF NOT EXISTS referral_credits (
id TEXT PRIMARY KEY, -- refc_abc123
user_id TEXT NOT NULL,
amount REAL NOT NULL, -- Credit amount (kr)
reason TEXT NOT NULL, -- 'referral_signup', 'referral_bonus', 'promo'
source_id TEXT, -- referral_tracking.id or promo code
expires_at TEXT NOT NULL, -- 90 days from creation
used_at TEXT, -- NULL until applied to transfer
used_for_tx_id TEXT, -- Transaction ID where credit was applied
created_at TEXT DEFAULT (datetime('now')),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE INDEX idx_referral_credits_user ON referral_credits(user_id);
CREATE INDEX idx_referral_credits_expires ON referral_credits(expires_at);
6.3 Referral Flow Logic
A. Code Generation (On First Login)
Endpoint: POST /api/referrals/generate-code
Logic:
async function generateReferralCode(userId: string): Promise<string> {
// Check if user already has a code
const existing = await getOne(
"SELECT code FROM referral_codes WHERE user_id = ?",
[userId]
);
if (existing) return existing.code;
// Generate unique 6-char code
let code = '';
let attempts = 0;
while (attempts < 10) {
code = generateCode(); // Random 6 chars
const duplicate = await getOne(
"SELECT id FROM referral_codes WHERE code = ?",
[code]
);
if (!duplicate) break;
attempts++;
}
if (attempts === 10) throw new Error("Failed to generate unique code");
// Insert code
const link = `https://getdrop.no?ref=${code}`;
await run(
`INSERT INTO referral_codes (id, user_id, code, referral_link)
VALUES (?, ?, ?, ?)`,
[randomId('ref'), userId, code, link]
);
return code;
}
B. Referral Click Tracking
Endpoint: GET /?ref={code}
Logic:
// Landing page detects ref param
const urlParams = new URLSearchParams(window.location.search);
const refCode = urlParams.get('ref');
if (refCode) {
// Store in localStorage (persist across session)
localStorage.setItem('drop_referral_code', refCode);
// Track click (fire-and-forget)
fetch('/api/referrals/track-click', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code: refCode })
});
}
Backend (track-click):
// Increment clicks counter
await run(
"UPDATE referral_codes SET clicks = clicks + 1 WHERE code = ?",
[code]
);
C. Signup Attribution
Endpoint: POST /api/auth/register (modify existing)
Add to registration logic:
// After user created
const refCode = request.body.referralCode; // From localStorage → sent in signup payload
if (refCode) {
const referrer = await getOne(
"SELECT user_id FROM referral_codes WHERE code = ?",
[refCode]
);
if (referrer) {
// Create tracking entry
await run(
`INSERT INTO referral_tracking (id, referrer_id, referee_id, referral_code, signup_at, status)
VALUES (?, ?, ?, ?, datetime('now'), 'pending')`,
[randomId('reft'), referrer.user_id, newUserId, refCode]
);
// Increment signups counter
await run(
"UPDATE referral_codes SET signups = signups + 1 WHERE code = ?",
[refCode]
);
// Show banner: "Du ble invitert av [FirstName]. Dere får begge 50 kr når du sender din første overføring!"
}
}
D. First Transfer Reward Issuance
Endpoint: POST /api/transactions/remittance (modify existing)
Add after transaction status = 'completed':
// Check if this is user's first transfer
const firstTransfer = await getOne(
`SELECT COUNT(*) as count FROM transactions
WHERE user_id = ? AND status = 'completed' AND type = 'remittance'`,
[userId]
);
if (firstTransfer.count === 1) { // This is the first
// Check if user was referred
const referral = await getOne(
`SELECT id, referrer_id, referral_code FROM referral_tracking
WHERE referee_id = ? AND status = 'pending'`,
[userId]
);
if (referral) {
const referrerReward = 50; // kr
const refereeReward = 50; // kr
const expiresAt = new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString(); // 90 days
// Issue credit to referrer
await run(
`INSERT INTO referral_credits (id, user_id, amount, reason, source_id, expires_at)
VALUES (?, ?, ?, 'referral_signup', ?, ?)`,
[randomId('refc'), referral.referrer_id, referrerReward, referral.id, expiresAt]
);
// Issue credit to referee
await run(
`INSERT INTO referral_credits (id, user_id, amount, reason, source_id, expires_at)
VALUES (?, ?, ?, 'referral_signup', ?, ?)`,
[randomId('refc'), userId, refereeReward, referral.id, expiresAt]
);
// Update tracking
await run(
`UPDATE referral_tracking
SET status = 'completed', first_transfer_at = datetime('now'),
referrer_reward = ?, referee_reward = ?
WHERE id = ?`,
[referrerReward, refereeReward, referral.id]
);
// Update referral code stats
await run(
`UPDATE referral_codes
SET conversions = conversions + 1, total_earned_credits = total_earned_credits + ?
WHERE code = ?`,
[referrerReward, referral.referral_code]
);
// Send notifications
await sendNotification(referral.referrer_id, {
type: 'referral_reward',
title: 'Du fikk 50 kr! 🎉',
body: '[FirstName] brukte din lenke og sendte sin første overføring.',
});
await sendNotification(userId, {
type: 'referral_reward',
title: 'Du fikk 50 kr! 🎉',
body: 'Takk for at du brukte Drop. Din neste overføring er billigere.',
});
}
}
E. Credit Application (During Transfer)
Logic:
// In transfer fee calculation
const baseFee = amount * 0.005; // 0.5%
// Check available credits
const credits = await getAll(
`SELECT id, amount FROM referral_credits
WHERE user_id = ? AND used_at IS NULL AND expires_at > datetime('now')
ORDER BY expires_at ASC`,
[userId]
);
let totalCredits = credits.reduce((sum, c) => sum + c.amount, 0);
let discount = Math.min(totalCredits, baseFee); // Can't discount more than fee
const finalFee = baseFee - discount;
// Mark credits as used (FIFO)
let remaining = discount;
for (const credit of credits) {
if (remaining <= 0) break;
const used = Math.min(credit.amount, remaining);
await run(
`UPDATE referral_credits
SET used_at = datetime('now'), used_for_tx_id = ?
WHERE id = ?`,
[txId, credit.id]
);
remaining -= used;
}
// Show in UI: "Gebyr: 50 kr (100 kr - 50 kr kreditt)"
6.4 Fraud Prevention
Rule 1: No Self-Referrals
// Check if referee IP/device matches referrer
const referrerFingerprint = await getOne(
"SELECT device_fingerprint, ip_address FROM sessions WHERE user_id = ?",
[referrerId]
);
const refereeFingerprint = hashDeviceFingerprint(ip, userAgent);
if (referrerFingerprint.device_fingerprint === refereeFingerprint) {
// Block referral, log fraud attempt
await logAudit({
userId: referrerId,
action: 'referral.fraud_attempt',
details: { reason: 'self_referral', referee_id: refereeId }
});
return; // No reward
}
Rule 2: Minimum Transfer Amount
// First transfer must be >= 500 kr to qualify
if (amount < 500) {
// Don't issue rewards
return;
}
Rule 3: Monthly Credit Cap
// Max 500 kr credits earned per user per month
const monthlyEarned = await getOne(
`SELECT SUM(amount) as total FROM referral_credits
WHERE user_id = ? AND reason = 'referral_signup'
AND created_at > date('now', 'start of month')`,
[userId]
);
if (monthlyEarned.total >= 500) {
// Block additional rewards this month
return;
}
Rule 4: Velocity Check
// Max 10 referrals per user per day
const dailyReferrals = await getOne(
`SELECT COUNT(*) as count FROM referral_tracking
WHERE referrer_id = ? AND signup_at > datetime('now', '-1 day')`,
[userId]
);
if (dailyReferrals.count >= 10) {
// Flag account for review
await run(
"UPDATE users SET referral_abuse_flag = 1 WHERE id = ?",
[userId]
);
}
Rule 5: BankID Verification Required
// Only verified users can earn rewards
if (!referee.bankid_verified) {
// Rewards are pending until BankID verification
// Update tracking: status = 'pending_verification'
}
6.5 Referral Dashboard (In-App)
UI Location: /profile/referrals
Components:
A. Referral Link Card
<div className="referral-card">
<h3>Inviter venner — få 50 kr per venn</h3>
<p>Dere får begge 50 kr når de sender sin første overføring.</p>
<div className="referral-link">
<input
value="https://getdrop.no?ref=MK3P7Z"
readOnly
onClick={(e) => e.target.select()}
/>
<button onClick={copyToClipboard}>Kopier</button>
</div>
<div className="share-buttons">
<button onClick={shareViaWhatsApp}>
<WhatsAppIcon /> WhatsApp
</button>
<button onClick={shareViaSMS}>
<MessageIcon /> SMS
</button>
<button onClick={shareViaEmail}>
<EmailIcon /> E-post
</button>
</div>
</div>
B. Stats Card
<div className="referral-stats">
<div className="stat">
<div className="stat-value">24</div>
<div className="stat-label">Venner invitert</div>
</div>
<div className="stat">
<div className="stat-value">12</div>
<div className="stat-label">Har sendt penger</div>
</div>
<div className="stat">
<div className="stat-value">600 kr</div>
<div className="stat-label">Totalt tjent</div>
</div>
</div>
C. Credits Balance
<div className="credits-balance">
<div className="balance-amount">150 kr</div>
<div className="balance-label">Tilgjengelig kreditt</div>
<p className="balance-expires">50 kr utløper om 12 dager</p>
</div>
D. Referral History
<div className="referral-history">
<h4>Dine invitasjoner</h4>
{referrals.map(ref => (
<div className="referral-row" key={ref.id}>
<div>
<div className="referral-name">{ref.refereeName}</div>
<div className="referral-date">{ref.signupDate}</div>
</div>
<div className="referral-status">
{ref.status === 'pending' && '⏳ Venter på overføring'}
{ref.status === 'completed' && '✅ +50 kr'}
</div>
</div>
))}
</div>
6.6 Share Templates
WhatsApp Message
Hei! 👋
Jeg bruker Drop for å sende penger hjem. De tar bare 0.5% gebyr (Western Union tar 10%!).
Vi får begge 50 kr hvis du registrerer deg og sender din første overføring:
https://getdrop.no?ref=MK3P7Z
Helt gratis å prøve. Tar 2 minutter å sette opp med BankID.
Mvh,
[FirstName]
Email Template
Subject: Spar 90% på gebyrer når du sender penger
Hei!
Jeg bruker Drop for internasjonale pengeoverføringer. De tar bare 0.5% gebyr — ikke 5-10% som Western Union og banker.
Vi får begge 50 kr hvis du registrerer deg via min lenke og sender din første overføring:
👉 https://getdrop.no?ref=MK3P7Z
Drop er regulert i Norge og bruker BankID for sikkerhet. Pengene er fremme på minutter, ikke dager.
Helt gratis å prøve. Ingen binding.
Mvh,
[FirstName]
SMS Template
Hei! Prøv Drop for pengeoverføringer (0.5% gebyr). Vi får begge 50 kr: getdrop.no?ref=MK3P7Z
7. Campaign Tracking & Attribution
7.1 UTM Parameter Strategy
Standard UTM Structure:
https://getdrop.no?utm_source={source}&utm_medium={medium}&utm_campaign={campaign}&utm_content={content}&utm_term={term}
Campaign Matrix:
| Campaign Type | Source | Medium | Example |
|---|---|---|---|
| Facebook Ads | cpc | utm_source=facebook&utm_medium=cpc&utm_campaign=launch_2026 | |
| Instagram Ads | cpc | utm_source=instagram&utm_medium=cpc&utm_campaign=qr_promo | |
| Google Ads | cpc | utm_source=google&utm_medium=cpc&utm_campaign=send_penger | |
| LinkedIn Organic | social | utm_source=linkedin&utm_medium=social&utm_campaign=alem_post | |
| Email Newsletter | newsletter | utm_source=email&utm_medium=newsletter&utm_campaign=waitlist_launch | |
| Partner Link (SB1) | sparebank1 | partner | utm_source=sparebank1&utm_medium=partner&utm_campaign=coop |
| Press Article | shifter | pr | utm_source=shifter&utm_medium=pr&utm_campaign=launch_coverage |
| Referral Program | referral | organic | (handled separately via ?ref= param) |
Naming Conventions:
utm_source: Platform name (lowercase, no spaces)utm_medium: Traffic type (cpc, social, email, partner, pr, organic, display)utm_campaign: Campaign identifier (snake_case, descriptive)utm_content: Ad variation (ad_1, ad_2, hero_cta, footer_link)utm_term: Keyword (Google Ads only)
7.2 UTM Tracking Implementation
A. Client-Side Capture (Landing Page)
Add to index.html (before waitlist form):
// Capture all UTM params + referral code
const urlParams = new URLSearchParams(window.location.search);
const utm = {
source: urlParams.get('utm_source') || 'direct',
medium: urlParams.get('utm_medium') || 'none',
campaign: urlParams.get('utm_campaign') || '',
content: urlParams.get('utm_content') || '',
term: urlParams.get('utm_term') || '',
referral: urlParams.get('ref') || ''
};
// Store in localStorage (persist across pages)
localStorage.setItem('drop_attribution', JSON.stringify(utm));
// Track landing (fire-and-forget)
fetch('/api/analytics/track', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
event: 'page_view',
page: window.location.pathname,
utm: utm,
timestamp: new Date().toISOString()
})
});
B. Waitlist Signup Attribution
Modify /api/waitlist to capture UTM:
const utm = request.body.utm; // Sent from frontend
await run(
`INSERT INTO waitlist (id, email, utm_source, utm_medium, utm_campaign, utm_content, utm_term, referral_code, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))`,
[
randomId('wait'),
email,
utm.source,
utm.medium,
utm.campaign,
utm.content,
utm.term,
utm.referral
]
);
Database Schema Update:
ALTER TABLE waitlist ADD COLUMN utm_source TEXT;
ALTER TABLE waitlist ADD COLUMN utm_medium TEXT;
ALTER TABLE waitlist ADD COLUMN utm_campaign TEXT;
ALTER TABLE waitlist ADD COLUMN utm_content TEXT;
ALTER TABLE waitlist ADD COLUMN utm_term TEXT;
ALTER TABLE waitlist ADD COLUMN referral_code TEXT;
C. User Registration Attribution
Modify /api/auth/register to capture UTM:
const utm = request.body.utm; // Retrieved from localStorage → sent in signup payload
await run(
`UPDATE users SET
utm_source = ?, utm_medium = ?, utm_campaign = ?, utm_content = ?, utm_term = ?,
referral_code = ?
WHERE id = ?`,
[utm.source, utm.medium, utm.campaign, utm.content, utm.term, utm.referral, userId]
);
Database Schema Update:
ALTER TABLE users ADD COLUMN utm_source TEXT;
ALTER TABLE users ADD COLUMN utm_medium TEXT;
ALTER TABLE users ADD COLUMN utm_campaign TEXT;
ALTER TABLE users ADD COLUMN utm_content TEXT;
ALTER TABLE users ADD COLUMN utm_term TEXT;
7.3 Attribution Reporting
Query: Waitlist Signups by Source
SELECT
utm_source,
utm_medium,
utm_campaign,
COUNT(*) as signups,
COUNT(*) * 100.0 / (SELECT COUNT(*) FROM waitlist) as percentage
FROM waitlist
WHERE created_at > date('now', '-30 days')
GROUP BY utm_source, utm_medium, utm_campaign
ORDER BY signups DESC;
Query: User Registrations by Source
SELECT
utm_source,
utm_medium,
COUNT(*) as registrations,
SUM(CASE WHEN kyc_status = 'approved' THEN 1 ELSE 0 END) as verified_users,
ROUND(100.0 * SUM(CASE WHEN kyc_status = 'approved' THEN 1 ELSE 0 END) / COUNT(*), 2) as verification_rate
FROM users
WHERE created_at > date('now', '-30 days')
GROUP BY utm_source, utm_medium
ORDER BY registrations DESC;
Query: Campaign ROI (Revenue per Source)
SELECT
u.utm_source,
u.utm_campaign,
COUNT(DISTINCT u.id) as users,
COUNT(DISTINCT t.id) as transactions,
SUM(t.amount * 0.005) as revenue_generated, -- 0.5% fee
revenue_generated / COUNT(DISTINCT u.id) as revenue_per_user
FROM users u
LEFT JOIN transactions t ON t.user_id = u.id
WHERE u.created_at > date('now', '-30 days')
GROUP BY u.utm_source, u.utm_campaign
ORDER BY revenue_generated DESC;
7.4 Conversion Pixels
Facebook Pixel
Add to <head> of landing page:
<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', 'YOUR_PIXEL_ID');
fbq('track', 'PageView');
</script>
<noscript>
<img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=YOUR_PIXEL_ID&ev=PageView&noscript=1"/>
</noscript>
Track Waitlist Signup:
// In waitlist form submit handler
if (response.ok) {
fbq('track', 'Lead'); // Facebook standard event
}
Track Registration:
// In /api/auth/register success callback
fbq('track', 'CompleteRegistration'); // Facebook standard event
Google Ads Conversion Tracking
Add to <head>:
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=AW-XXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'AW-XXXXX');
</script>
Track Conversion:
// In waitlist form submit handler
if (response.ok) {
gtag('event', 'conversion', {
'send_to': 'AW-XXXXX/CONVERSION_LABEL',
'value': 1.0,
'currency': 'NOK'
});
}
8. Email Marketing Integration
8.1 Campaign Types
Note: Email service layer already specified in drop-email-system-spec.md. This section defines marketing-specific campaigns.
A. Waitlist Nurture Series (Pre-Launch)
Trigger: User signs up for waitlist
Email 1 (Immediate): Confirmation
- Subject: "Du er på listen! 🎉"
- Content: Confirm signup, set expectations (launch date), share referral link
- CTA: "Inviter venner — hopp køen"
Email 2 (Day 7): Educational
- Subject: "Derfor tar banker så høye gebyrer"
- Content: Explain remittance market, Western Union fees, Drop's pass-through model
- CTA: "Les mer om Drop"
Email 3 (Day 14): Social Proof
- Subject: "2,000+ nordmenn venter allerede"
- Content: Waitlist count, testimonials (when available), SpareBank 1 partnership mention
- CTA: "Del med venner"
Email 4 (Day 21): Product Demo
- Subject: "Se hvordan Drop fungerer (90 sekunder)"
- Content: Embed demo video, screenshot walkthrough
- CTA: "Se videoen"
Email 5 (Pre-Launch -7 days): Launch Countdown
- Subject: "Drop lanseres om 7 dager!"
- Content: Countdown timer, "first 1000 get 5 free transfers" reminder
- CTA: "Sett påminnelse"
Email 6 (Launch Day): App Available
- Subject: "Drop er her! Last ned nå."
- Content: App Store/Play Store links, onboarding guide
- CTA: "Last ned gratis"
B. Onboarding Series (Post-Registration)
Email 1 (After Registration): Welcome
- Subject: "Velkommen til Drop!"
- Content: What to expect, link BankID reminder, first transfer incentive
- CTA: "Fullfør profilen din"
Email 2 (Day 3, if no BankID): Nudge
- Subject: "Koble BankID — ta 2 minutter"
- Content: Why BankID is required, security explanation
- CTA: "Koble BankID"
Email 3 (Day 7, if no first transfer): First Transfer Incentive
- Subject: "Send din første overføring — få 50 kr"
- Content: Referral credit reminder, fee comparison
- CTA: "Send penger nå"
C. Re-engagement Series (Dormant Users)
Trigger: User hasn't sent a transfer in 30 days
Email 1 (Day 30): Gentle Reminder
- Subject: "Vi savner deg!"
- Content: "It's been a while..." + new features announcement
- CTA: "Send penger igjen"
Email 2 (Day 60): Win-back Offer
- Subject: "25 kr gratis på din neste overføring"
- Content: Exclusive promo code (one-time use)
- CTA: "Bruk koden"
Email 3 (Day 90): Feedback Request
- Subject: "Hvorfor sluttet du å bruke Drop?"
- Content: Survey link (3 questions max)
- CTA: "Del tilbakemelding"
8.2 Marketing Consent Management
Consent Collection (During Registration):
<label>
<input type="checkbox" name="marketingConsent" value="1">
Jeg ønsker å motta tips, tilbud og nyheter fra Drop (valgfritt)
</label>
<p class="consent-note">
Du kan avslutte når som helst. Se vår <a href="/personvern">personvernerklæring</a>.
</p>
Database Schema (already in onboarding spec):
-- consents table already defined
INSERT INTO consents (id, user_id, consent_type, granted, granted_at, ip_address)
VALUES (?, ?, 'marketing', ?, datetime('now'), ?);
Email Unsubscribe Link (Footer):
<p style="font-size: 12px; color: #6B7280; text-align: center;">
Vil du ikke lenger motta e-poster fra Drop?
<a href="https://getdrop.no/unsubscribe?token={{unsubscribeToken}}" style="color: #0B6E35;">
Avslutt abonnement
</a>
</p>
Unsubscribe Endpoint:
// GET /unsubscribe?token={jwt}
const { userId } = verifyUnsubscribeToken(token);
await run(
`UPDATE consents SET granted = 0, withdrawn_at = datetime('now')
WHERE user_id = ? AND consent_type = 'marketing'`,
[userId]
);
// Show confirmation page: "Du er fjernet fra listen."
8.3 Email Automation Triggers
Trigger Table:
| Event | Delay | Campaign | Condition |
|---|---|---|---|
| Waitlist signup | 0s | Waitlist Email 1 | — |
| Waitlist signup | 7d | Waitlist Email 2 | If not registered |
| Waitlist signup | 14d | Waitlist Email 3 | If not registered |
| User registered | 0s | Onboarding Email 1 | — |
| User registered | 3d | Onboarding Email 2 | If no BankID |
| User registered | 7d | Onboarding Email 3 | If no transfer |
| First transfer | 0s | First Transfer Receipt | — |
| Last transfer | 30d | Re-engagement Email 1 | If no transfer in 30d |
| Last transfer | 60d | Re-engagement Email 2 | If no transfer in 60d |
Implementation:
- Use cron job or scheduled task (runs every hour)
- Query database for users matching trigger conditions
- Call
sendEmail()from email service layer - Mark email as sent in
email_logtable
9. Analytics & Reporting
9.1 Analytics Platform Selection
Options:
| Platform | Pros | Cons | Cost |
|---|---|---|---|
| Plausible (RECOMMENDED) | GDPR-compliant, no cookies, simple, Norwegian data center | Fewer features than GA4 | €9/mo (10k pageviews) |
| Google Analytics 4 | Free, comprehensive, industry standard | Cookie consent required, complex | Free |
| Mixpanel | Event tracking, funnel analysis, cohorts | Expensive at scale | $20/mo (1k users) |
| PostHog | Self-hosted option, session replay | Complex setup | $0 (self-hosted) |
Recommendation: Start with Plausible for landing page (no cookie consent banner needed), add Mixpanel for in-app analytics post-launch.
9.2 Plausible Setup (Landing Page)
Add to <head>:
<script defer data-domain="getdrop.no" src="https://plausible.io/js/script.js"></script>
Track Custom Events:
// Waitlist signup
plausible('Waitlist Signup', { props: { source: utm.source } });
// Referral link click
plausible('Referral Link Click', { props: { code: refCode } });
// CTA button click
plausible('CTA Click', { props: { location: 'hero' } });
Plausible Goals (Configure in Dashboard):
- Waitlist Signup (pageview: /api/waitlist success)
- App Store Click (custom event)
- Play Store Click (custom event)
- Referral Link Click (custom event)
- Video Play (custom event)
9.3 In-App Analytics (Mixpanel)
Events to Track:
Acquisition
user_registered(properties: utm_source, utm_medium, referral_code)bankid_verified(properties: time_to_verify_seconds)kyc_approved(properties: time_to_approve_seconds)
Activation
first_transfer_completed(properties: amount, currency, destination_country)qr_payment_completed(properties: amount, merchant_name)bank_account_linked(properties: bank_name)
Engagement
app_opened(properties: session_count)screen_viewed(properties: screen_name)transfer_initiated(properties: amount, currency)transfer_cancelled(properties: step, reason)
Retention
transfer_completed(properties: amount, transfer_count, days_since_last_transfer)push_notification_received(properties: type)push_notification_clicked(properties: type)
Referral
Revenue
fee_charged(properties: amount_nok, transaction_type)credit_applied(properties: amount, source)
Mixpanel People Properties:
mixpanel.people.set({
"$email": user.email,
"$name": `${user.firstName} ${user.lastName}`,
"signup_date": user.createdAt,
"utm_source": user.utmSource,
"referral_code": user.referralCode,
"total_transfers": user.transferCount,
"total_revenue": user.totalFeesPaid,
"kyc_status": user.kycStatus,
"bankid_verified": user.bankidVerified
});
9.4 Key Metrics Dashboard
Acquisition Metrics:
- Landing page visitors (unique)
- Waitlist signups
- Waitlist → Registration conversion rate
- Registration → BankID verification rate
- BankID → KYC approval rate
- Overall conversion (Visitor → Verified User)
Activation Metrics:
- Time to first transfer (median)
- First transfer completion rate (within 7 days of registration)
- Average first transfer amount
- QR payment adoption rate (% of users who scan at least 1 QR)
Engagement Metrics:
- DAU (Daily Active Users)
- WAU (Weekly Active Users)
- MAU (Monthly Active Users)
- Transfers per user per month
- Average transaction value
Retention Metrics:
- Day 1, 7, 30, 90 retention
- Cohort analysis (users by signup month)
- Churn rate (users with no transfer in 90 days)
Referral Metrics:
- Referral rate (% of users who share link)
- Referral conversion rate (signups per shared link)
- Viral coefficient (new users per existing user)
- Referral ROI (LTV of referred users vs. non-referred)
Revenue Metrics:
- Total fee revenue (kr)
- Revenue per user (kr)
- Revenue per transfer (kr)
- Credit redemption rate (% of credits used)
Campaign Performance:
- Cost per waitlist signup (CPA)
- Cost per registration (CPA)
- Cost per verified user (CPA)
- ROAS (Return on Ad Spend) by channel
10. A/B Testing Framework
10.1 Testing Strategy
Goal: Optimize conversion at every funnel step
Test Prioritization (ICE Framework):
| Test | Impact | Confidence | Ease | ICE Score |
|---|---|---|---|---|
| Hero CTA copy ("Bli med" vs "Registrer deg") | 8 | 9 | 10 | 27 |
| Waitlist incentive ("5 free transfers" vs "50 kr credit") | 9 | 7 | 10 | 26 |
| Feature order (Remittance first vs QR first) | 6 | 8 | 9 | 23 |
| Phone mockup vs real screenshot | 7 | 6 | 8 | 21 |
| Social proof placement (hero vs below features) | 5 | 7 | 9 | 21 |
Test Velocity: 1 test every 2 weeks (minimum 2 weeks per test for statistical significance)
10.2 A/B Testing Tools
Options:
| Tool | Pros | Cons | Cost |
|---|---|---|---|
| Vercel Edge Middleware (RECOMMENDED) | Fast, server-side, free | Manual implementation | Free |
| Google Optimize (Deprecated) | — | Sunset 2023 | — |
| Optimizely | Visual editor, advanced targeting | Expensive | $50k+/year |
| VWO | Visual editor, heatmaps | Complex setup | $199/mo |
| PostHog | Open source, feature flags | Self-hosted complexity | Free (self-hosted) |
Recommendation: Use Vercel Edge Middleware for simple A/B tests (free, fast, server-side). Upgrade to PostHog if feature flags needed.
10.3 Implementation (Vercel Edge Middleware)
File: middleware.ts
import { NextRequest, NextResponse } from 'next/server';
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Only run A/B test on homepage
if (pathname !== '/') return NextResponse.next();
// Check if user already has variant assigned
let variant = request.cookies.get('ab_hero_cta')?.value;
if (!variant) {
// Assign variant (50/50 split)
variant = Math.random() < 0.5 ? 'A' : 'B';
const response = NextResponse.next();
response.cookies.set('ab_hero_cta', variant, {
maxAge: 30 * 24 * 60 * 60, // 30 days
httpOnly: true,
sameSite: 'lax'
});
return response;
}
return NextResponse.next();
}
Frontend (index.html):
// Read variant from cookie
const variant = document.cookie
.split('; ')
.find(row => row.startsWith('ab_hero_cta='))
?.split('=')[1] || 'A';
// Update CTA based on variant
const ctaButton = document.querySelector('.btn-gradient');
if (variant === 'B') {
ctaButton.textContent = 'Registrer deg gratis'; // Variant B
} else {
ctaButton.textContent = 'Bli med på ventelisten'; // Variant A (control)
}
// Track variant in analytics
plausible('pageview', { props: { ab_hero_cta: variant } });
Track Conversion:
// In waitlist form submit handler
plausible('Waitlist Signup', {
props: {
ab_hero_cta: variant,
utm_source: utm.source
}
});
Analysis:
-- Conversion rate by variant
SELECT
ab_variant,
COUNT(*) as views,
SUM(CASE WHEN converted = 1 THEN 1 ELSE 0 END) as conversions,
ROUND(100.0 * SUM(CASE WHEN converted = 1 THEN 1 ELSE 0 END) / COUNT(*), 2) as conversion_rate
FROM analytics_events
WHERE event_type = 'pageview'
AND created_at > date('now', '-14 days')
GROUP BY ab_variant;
Statistical Significance Calculator:
- Use https://abtestguide.com/calc/ or similar
- Minimum sample size: 385 per variant (95% confidence, 5% margin of error)
- Run test until both variants reach minimum sample size
11. Content Marketing (Blog)
11.1 Blog Infrastructure
Goal: SEO traffic + thought leadership
Platform Options:
| Option | Pros | Cons |
|---|---|---|
| Next.js MDX (RECOMMENDED) | Same codebase, fast, full control | Manual implementation |
| Substack | Easy setup, newsletter integration | External platform, limited branding |
| Medium | Built-in audience | No domain control, paywall |
| WordPress | SEO plugins, familiar | Separate hosting, slower |
Recommendation: Next.js MDX (markdown files → static pages)
11.2 Blog Structure
Directory:
/landing/blog/
├── index.html # Blog homepage (list of posts)
├── slik-sender-du-penger-til-tyrkia.html
├── drop-vs-western-union.html
├── hvorfor-banker-tar-hoye-gebyrer.html
└── qr-betaling-forklart.html
Blog Post Template:
<!DOCTYPE html>
<html lang="no">
<head>
<meta charset="UTF-8">
<title>[Post Title] — Drop Blog</title>
<meta name="description" content="[Excerpt]">
<meta property="og:type" content="article">
<meta property="article:published_time" content="2026-03-15T10:00:00Z">
<meta property="article:author" content="Drop Team">
<link rel="canonical" href="https://getdrop.no/blog/[slug]">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "[Post Title]",
"datePublished": "2026-03-15",
"author": {"@type": "Organization", "name": "Drop"},
"publisher": {"@type": "Organization", "name": "Drop", "logo": "..."},
"image": "https://getdrop.no/blog/images/[cover].jpg"
}
</script>
</head>
<body>
<article class="blog-post">
<h1>[Post Title]</h1>
<div class="meta">Publisert 15. mars 2026 · 5 min lesing</div>
<img src="images/[cover].jpg" alt="[Alt text]">
<div class="content">
[Post content in HTML]
</div>
<div class="cta-box">
<h3>Prøv Drop gratis</h3>
<p>Send penger til 30+ land med bare 0.5% gebyr.</p>
<a href="/#cta" class="btn-gradient">Registrer deg</a>
</div>
</article>
</body>
</html>
11.3 Content Calendar (First 90 Days)
Goal: 2 posts per week (8 posts/month)
Week 1-2 (SEO Foundation):
- "Slik sender du penger til Tyrkia fra Norge" (target: "send penger til tyrkia")
- "Drop vs Western Union: Detaljert sammenligning" (target: "western union alternativ")
Week 3-4 (Educational): 3. "Hvorfor tar banker så høye gebyrer på pengeoverføringer?" (thought leadership) 4. "QR-betaling forklart: Slik fungerer det" (target: "qr betaling")
Week 5-6 (Comparison): 5. "Drop vs Wise: Hva er forskjellen?" (target: "wise alternativ") 6. "De beste måtene å sende penger til utlandet i 2026" (target: "billigste pengeoverføring")
Week 7-8 (Use Cases): 7. "Slik sender du penger hjem til familie i utlandet" (emotional, storytelling) 8. "QR-betaling for småbedrifter: Guiden" (merchant-focused)
Content Distribution:
- Publish on blog
- Share on LinkedIn (Alem's profile)
- Send to waitlist (weekly digest)
- Submit to relevant subreddits (r/norway, r/norge — carefully, no spam)
12. Social Media Strategy
12.1 Platform Prioritization
| Platform | Priority | Audience | Content Type | Frequency |
|---|---|---|---|---|
| HIGH | Business audience, partnerships, press | Company updates, thought leadership | 3x/week | |
| MEDIUM | Consumers, visual storytelling | Features, user stories, behind-the-scenes | 5x/week | |
| MEDIUM | Broader consumer base, ads | Features, blog posts, ads | 3x/week | |
| Twitter/X | LOW | Tech audience, customer support | Quick updates, support responses | As needed |
| TikTok | LOW (Future) | Young audience | Short-form video | 0x/week (post-launch) |
12.2 Account Setup
Handles (Claim ASAP):
- Instagram: @dropnorge
- Facebook: facebook.com/dropnorge
- LinkedIn: linkedin.com/company/drop-norge
- Twitter: @dropnorge (or @drop_norge if taken)
Bio Template (Instagram):
Drop — Enklere betalinger. Lavere gebyrer.
💸 0.5% gebyr på internasjonale overføringer
📱 QR-betaling i butikk
🇳🇴 Regulert i Norge
⬇️ Registrer deg for tidlig tilgang
Link in Bio:
- getdrop.no?utm_source=instagram&utm_medium=social&utm_campaign=bio_link
12.3 Content Pillars
Pillar 1: Product Education (40%)
- How Drop works (carousel posts)
- Fee comparison infographics
- Feature announcements
- Tutorial videos
Pillar 2: Customer Stories (30%)
- User testimonials (when available)
- "How I saved X kr with Drop" posts
- Behind-the-scenes (team, product development)
Pillar 3: Industry Insights (20%)
- Fintech news commentary
- Regulatory updates (Finanstilsynet)
- Market trends (remittance, payments)
Pillar 4: Culture & Values (10%)
- Team introductions
- Company values
- Community engagement
12.4 Content Calendar (First Month)
Week 1:
- Mon: Introduce Drop (carousel: What is Drop?)
- Wed: Fee comparison infographic (Drop vs banks)
- Fri: Behind-the-scenes (team building the app)
Week 2:
- Mon: Feature spotlight (QR payment)
- Wed: Blog post share (Why banks charge high fees)
- Fri: Waitlist milestone ("1,000 people signed up!")
Week 3:
- Mon: FAQ carousel (Is Drop a bank? No.)
- Wed: Partnership announcement (SpareBank 1, if approved)
- Fri: User story (when available, or placeholder)
Week 4:
- Mon: Tutorial video (How to send money with Drop)
- Wed: Industry news commentary (PSD2 update)
- Fri: Countdown to launch (if applicable)
12.5 Paid Social Ads (Post-Launch)
Budget: 10,000 NOK/month (testing phase)
Campaign 1: Waitlist Signups (Pre-Launch)
- Platform: Facebook + Instagram
- Objective: Lead generation
- Audience: Norway, age 25-45, interests: fintech, travel, expat groups
- Creative: Carousel (3 slides): Problem → Solution → CTA
- CTA: "Registrer deg gratis"
- Landing page: getdrop.no?utm_source=facebook&utm_medium=cpc&utm_campaign=waitlist_signups
Campaign 2: App Installs (Post-Launch)
- Platform: Google App Campaigns
- Objective: App installs
- Audience: Norway, keywords: "send penger", "pengeoverføring", "western union alternativ"
- Ad copy: "Send penger med 0.5% gebyr. Last ned Drop gratis."
- Bid strategy: Target CPA (50 NOK per install)
Campaign 3: Retargeting (Post-Launch)
- Platform: Facebook + Instagram
- Objective: Conversions (first transfer)
- Audience: Custom audience (registered users who haven't transferred)
- Creative: "You're one step away. Complete your first transfer and get 50 kr."
- Landing page: Deep link to app (drop://send)
13. Legal & Compliance
13.1 Markedsføringsloven Compliance
Key Requirements:
1. Identification of Marketing: All marketing communications must be clearly identifiable as such. Commercial emails must include "Annonse" or "Reklame" in subject line.
Example:
Subject: [Annonse] Spar opptil 90% på pengeoverføringer
2. Opt-In for Electronic Marketing: Electronic marketing (email, SMS) to natural persons requires prior consent (opt-in). Exception: existing customer relationship + same product category.
Implementation:
- Checkbox on registration: "Jeg ønsker å motta tilbud fra Drop" (unchecked by default)
- Record consent in
consentstable with timestamp and IP - Unsubscribe link in every email
3. Misleading Marketing Prohibition: Cannot make false or misleading claims. All claims must be substantiable.
Examples of Compliant Claims:
- ✅ "0.5% gebyr" (true, documented in pricing)
- ✅ "Regulert i Norge" (true when PSD2 license obtained)
- ❌ "Billigst i Norge" (unsubstantiated, use "Fra 0.5% gebyr" instead)
4. Comparative Marketing: Can compare with competitors (Western Union, Wise) if factually accurate and verifiable.
Example:
Drop: 0.5% gebyr
Western Union: 5-10% gebyr*
*Basert på gjennomsnittlig gebyr for 5,000 NOK overføring til Tyrkia, per Western Union's offentlige prisliste (februar 2026).
5. Environmental Claims: Cannot make environmental claims ("grønn", "klimavennlig") without documentation.
Drop's Claims: None planned.
13.2 GDPR Marketing Compliance
Implementation (Cookie Consent Banner):
<div id="cookie-banner" style="position: fixed; bottom: 0; width: 100%; background: white; border-top: 1px solid #E5E7EB; padding: 20px; z-index: 1000; display: none;">
<div style="max-width: 1200px; margin: 0 auto; display: flex; justify-content: space-between; align-items: center;">
<div>
<p style="font-size: 14px; color: #1A1A1A; margin-bottom: 8px;">
<strong>Vi bruker informasjonskapsler</strong>
</p>
<p style="font-size: 13px; color: #6B7280;">
Vi bruker informasjonskapsler for å forbedre din opplevelse og for å måle effektiviteten av våre markedsføringskampanjer.
<a href="/pages/cookies.html" style="color: #0B6E35; text-decoration: underline;">Les mer</a>
</p>
</div>
<div style="display: flex; gap: 12px;">
<button onclick="rejectCookies()" style="padding: 10px 20px; border: 1px solid #E5E7EB; background: white; border-radius: 8px; cursor: pointer;">
Avvis
</button>
<button onclick="acceptCookies()" class="btn-gradient" style="padding: 10px 20px;">
Godta
</button>
</div>
</div>
</div>
<script>
function showCookieBanner() {
const consent = localStorage.getItem('drop_cookie_consent');
if (!consent) {
document.getElementById('cookie-banner').style.display = 'block';
} else if (consent === 'accepted') {
loadMarketingCookies();
}
}
function acceptCookies() {
localStorage.setItem('drop_cookie_consent', 'accepted');
document.getElementById('cookie-banner').style.display = 'none';
loadMarketingCookies();
}
function rejectCookies() {
localStorage.setItem('drop_cookie_consent', 'rejected');
document.getElementById('cookie-banner').style.display = 'none';
}
function loadMarketingCookies() {
// Load Facebook Pixel
if (typeof fbq === 'undefined') {
// Insert Facebook Pixel script
}
// Load Google Ads
if (typeof gtag === 'undefined') {
// Insert Google Ads script
}
}
showCookieBanner();
</script>
Privacy Policy Update: Add section on marketing data usage:
## Markedsføring
Vi bruker din e-postadresse for å sende deg markedsføringskommunikasjon kun hvis du har gitt samtykke. Du kan når som helst trekke tilbake ditt samtykke ved å klikke på "Avslutt abonnement" nederst i enhver e-post.
Vi bruker informasjonskapsler fra Facebook og Google for å måle effektiviteten av våre annonser. Du kan blokkere disse informasjonskapslene ved å avvise dem i vår informasjonskapselbanner.
14. Cost Analysis
14.1 Tool Costs (Monthly)
| Tool | Purpose | Cost (NOK) | Notes |
|---|---|---|---|
| Domain (getdrop.no) | Domain registration | 100 kr/year | Already paid via one.com |
| Vercel Hosting | Landing page hosting | 0 kr | Free tier (sufficient for landing page) |
| Plausible Analytics | Landing page analytics | 90 kr | €9/mo, GDPR-compliant |
| Resend | Email service | 0 kr (MVP) | Free tier: 3,000 emails/mo (sufficient for waitlist) |
| Mixpanel | In-app analytics | 200 kr | $20/mo for 1k users |
| Social Media Ads | Facebook + Instagram + Google | 10,000 kr | Testing budget (can scale up/down) |
| Design Tools (Canva Pro) | Social media graphics | 150 kr | For non-Figma assets |
| Mailchimp (Optional) | Email campaigns | 400 kr | If Resend not enough (10k contacts) |
Total Monthly Cost (MVP): ~440 kr Total with Ads: ~10,440 kr
14.2 Referral Program Budget
Assumptions:
- 1,000 users in first 3 months
- 50% referred by existing users (500 referrals)
- 80% complete first transfer (400 conversions)
- 50 kr reward per conversion (both referrer + referee)
Calculation:
400 conversions × 50 kr (referrer) = 20,000 kr
400 conversions × 50 kr (referee) = 20,000 kr
Total referral rewards: 40,000 kr
ROI:
- Cost per acquisition: 40,000 kr / 400 users = 100 kr/user
- LTV estimate (conservative): 500 kr/user (10 transfers × 50 kr avg fee)
- ROI: 500 kr / 100 kr = 5x
Budget Allocation:
- Referral rewards: 40,000 kr (Q1)
- Paid ads: 30,000 kr (Q1)
- Tools: 1,320 kr (Q1)
- Total Q1 Marketing Budget: 71,320 kr
15. Implementation Plan
15.1 Phase 1: Landing Page Optimization (Week 1-2)
Owner: John + Frontend builder agent
Tasks:
-
Add conversion tracking (Plausible)
- Sign up for Plausible account
- Add tracking script to index.html
- Configure goals (waitlist signup, CTA clicks)
- Test tracking (verify events in Plausible dashboard)
-
Optimize hero section
- Replace "Last ned gratis" with "Bli med på ventelisten"
- Add "De første 1000 får 5 gratis overføringer" subtext
- Replace phone mockup with real screenshot from Figma Make
-
Add FAQ section
- Create FAQ accordion component
- Add 5 common questions (Er Drop en bank?, Hvor mye koster det?, etc.)
- Add FAQ structured data (JSON-LD)
-
Add comparison table
- Create Drop vs Western Union vs Wise vs Bank table
- Add styling (match landing page design)
-
Mobile optimization
- Add sticky CTA bar on mobile
- Test on iPhone/Android (Safari, Chrome)
-
Page speed optimization
- Preload hero fonts
- Lazy load images below fold
- Minify CSS
- Test with Lighthouse (target: 95+ score)
Acceptance:
- Plausible tracking works (waitlist signups logged)
- Hero CTA updated with incentive
- FAQ section renders correctly
- Comparison table displays on desktop + mobile
- Mobile sticky bar appears below 768px width
- Lighthouse score >= 95
15.2 Phase 2: SEO Foundation (Week 3-4)
Owner: John + Content agent (Ollama)
Tasks:
-
Add structured data
- Add Organization schema to homepage
- Add FAQ schema to FAQ section
- Validate with Google Rich Results Test
-
Create sitemap.xml
- Generate sitemap with all pages
- Submit to Google Search Console
- Submit to Bing Webmaster Tools
-
Create robots.txt
- Allow all except /api/
- Add sitemap reference
-
Create blog infrastructure
- Create /blog/index.html (blog homepage)
- Create blog post template
- Write first 2 blog posts (Tyrkia guide, Drop vs WU)
-
Subpage creation
- Create /send-penger.html (dedicated remittance page)
- Create /qr-betaling.html (QR explainer)
- Create /priser.html (pricing comparison)
Acceptance:
- Structured data validates in Google Rich Results Test
- Sitemap submitted to Google + Bing
- robots.txt accessible at /robots.txt
- Blog homepage lists 2 posts
- 3 subpages created and indexed
15.3 Phase 3: UTM & Attribution (Week 5-6)
Owner: John + Backend builder agent
Tasks:
-
Implement UTM tracking
- Add client-side UTM capture to index.html
- Store UTM in localStorage
- Modify /api/waitlist to save UTM params
- Add utm_* columns to waitlist table
-
Update registration flow
- Modify /api/auth/register to capture UTM from localStorage
- Add utm_* columns to users table
- Test registration with UTM params
-
Create attribution reports
- SQL query: Waitlist signups by source
- SQL query: User registrations by source
- SQL query: Revenue by source (post-launch)
-
Add conversion pixels
- Add Facebook Pixel to landing page
- Add Google Ads conversion tracking
- Test pixel firing (Facebook Events Manager)
Acceptance:
- UTM params saved to waitlist table
- UTM params saved to users table
- Attribution reports run successfully
- Facebook Pixel tracks PageView + Lead
- Google Ads tracks conversions
15.4 Phase 4: Referral System (Week 7-10)
Owner: John + Backend builder agent
Tasks:
-
Database schema
- Create referral_codes table
- Create referral_tracking table
- Create referral_credits table
- Create indexes
-
Backend endpoints
- POST /api/referrals/generate-code
- POST /api/referrals/track-click
- Modify /api/auth/register (signup attribution)
- Modify /api/transactions/remittance (reward issuance)
-
Referral dashboard UI
- Create /profile/referrals page
- Referral link card
- Stats card (invites, conversions, earnings)
- Credits balance
- Referral history
-
Share functionality
- WhatsApp share button
- SMS share button
- Email share button
- Copy link button
-
Fraud prevention
- Implement self-referral check (device fingerprint)
- Implement minimum transfer amount (500 kr)
- Implement monthly credit cap (500 kr)
- Implement velocity check (10/day)
Acceptance:
- Referral code auto-generated on first login
- Referral link click tracked
- Signup attributed to referrer
- First transfer triggers reward issuance
- Referral dashboard displays stats
- Share buttons open WhatsApp/SMS/Email
- Fraud checks block abuse
15.5 Phase 5: App Store Listings (Week 11-12)
Owner: John + Designer agent (Ollama) + QA
Tasks:
-
iOS App Store listing
- Write app name, subtitle, description
- Select keywords
- Generate 6 screenshots from Figma Make export
- Create app preview video (30 sec)
- Submit for review (when app ready)
-
Google Play Store listing
- Write title, short description, full description
- Create feature graphic (1024x500)
- Generate 4 screenshots (Android ratio)
- Submit for review (when app ready)
-
ASO optimization
- Research keywords in App Store Connect
- A/B test icon variants (internal testing)
- Localize for NO + EN
Acceptance:
- iOS listing drafted (not submitted until app ready)
- Android listing drafted
- Screenshots match Figma design
- App preview video rendered and reviewed
- Keyword research documented
15.6 Phase 6: Email Campaigns (Week 13-14)
Owner: John + Backend builder agent
Tasks:
-
Waitlist nurture series
- Create 6 email templates (confirmation → launch)
- Set up automation triggers (day 0, 7, 14, 21, pre-launch -7, launch)
- Test emails (send to [email protected])
-
Onboarding series
- Create 3 email templates (welcome → first transfer nudge)
- Set up automation triggers (day 0, 3, 7)
- Test emails
-
Re-engagement series
- Create 3 email templates (gentle → win-back → survey)
- Set up automation triggers (day 30, 60, 90)
- Test emails
-
Marketing consent
- Add checkbox to registration form
- Record consent in consents table
- Add unsubscribe link to all emails
- Create unsubscribe endpoint
Acceptance:
- All email templates render correctly in Gmail/Outlook
- Automation triggers fire correctly (test with dummy users)
- Marketing consent checkbox works
- Unsubscribe link works
15.7 Phase 7: Analytics & Reporting (Week 15-16)
Owner: John + Data analyst agent (Ollama)
Tasks:
-
Mixpanel setup
- Create Mixpanel account
- Add Mixpanel SDK to app
- Implement 15 core events (user_registered, first_transfer_completed, etc.)
- Set People properties (email, name, utm_source, etc.)
-
Dashboards
- Create Acquisition Dashboard (visitors → verified users)
- Create Activation Dashboard (first transfer rate)
- Create Retention Dashboard (D1, D7, D30 retention)
- Create Referral Dashboard (viral coefficient)
- Create Revenue Dashboard (fee revenue, revenue per user)
-
Reports
- Weekly funnel report (automated, sent to Alem)
- Monthly cohort analysis
- Campaign performance report (ROI by channel)
Acceptance:
- Mixpanel events tracked in app
- 5 dashboards created in Mixpanel
- Weekly report automation set up
15.8 Phase 8: Social Media Launch (Week 17-18)
Owner: John + Marketer agent (Ollama)
Tasks:
-
Account setup
- Create @dropnorge Instagram
- Create facebook.com/dropnorge
- Create linkedin.com/company/drop-norge
- Design profile pictures + cover photos
-
Content calendar
- Create 30-day content calendar (spreadsheet)
- Design 12 Instagram posts (Canva)
- Write captions + hashtags
-
First month execution
- Schedule posts (Buffer or Hootsuite)
- Engage with comments
- Cross-post to LinkedIn
-
Paid ads (when budget available)
- Set up Facebook Ads Manager
- Create waitlist signup campaign
- Set budget: 5,000 kr/month (testing)
- Monitor daily, optimize weekly
Acceptance:
16. Success Metrics (3 Months Post-Launch)
16.1 Acquisition
| Metric | Target | Measurement |
|---|---|---|
| Waitlist signups | 5,000 | Waitlist table count |
| Waitlist → Registration | 40% | (Registrations / Waitlist signups) × 100 |
| Registration → BankID | 80% | (BankID verified / Registrations) × 100 |
| BankID → KYC Approved | 90% | (KYC approved / BankID verified) × 100 |
| Overall Conversion | 30% | (Verified users / Waitlist signups) × 100 |
16.2 Activation
| Metric | Target | Measurement |
|---|---|---|
| First transfer (within 7 days) | 60% | (Users with 1+ transfer / Verified users) × 100 |
| QR payment adoption | 20% | (Users with 1+ QR payment / Verified users) × 100 |
| Average first transfer | 3,000 kr | AVG(first transfer amount) |
16.3 Engagement
| Metric | Target | Measurement |
|---|---|---|
| DAU/MAU ratio | 25% | (Daily active users / Monthly active users) × 100 |
| Transfers per user per month | 2.5 | Total transfers / Active users |
| QR payments per user per month | 5 | Total QR payments / Active QR users |
16.4 Retention
| Metric | Target | Measurement |
|---|---|---|
| Day 1 retention | 60% | % of users who return day after signup |
| Day 7 retention | 40% | % of users who return within 7 days |
| Day 30 retention | 25% | % of users who return within 30 days |
16.5 Referral
| Metric | Target | Measurement |
|---|---|---|
| Referral rate | 30% | (Users who shared link / Total users) × 100 |
| Referral conversion | 50% | (Signups from referrals / Referral link clicks) × 100 |
| Viral coefficient | 0.65 | (Referral rate × Referral conversion) = 30% × 50% = 15% (Note: Revolut's 65% from referrals means 0.65 new users per existing user) |
16.6 Revenue
| Metric | Target | Measurement |
|---|---|---|
| Total fee revenue | 100,000 kr | SUM(transaction fee) |
| Revenue per user | 100 kr | Total revenue / Active users |
| Revenue per transfer | 40 kr | Total revenue / Total transfers |
16.7 Marketing
| Metric | Target | Measurement |
|---|---|---|
| Organic traffic (SEO) | 2,000 visitors/mo | Plausible analytics |
| Social media followers | 1,500 | Instagram + Facebook + LinkedIn |
| Blog subscribers | 500 | Email list opt-ins from blog |
| Cost per acquisition (CPA) | 150 kr | Total ad spend / New users |
17. Risk Mitigation
17.1 Key Risks
Risk 1: Low Referral Adoption
- Likelihood: Medium
- Impact: High (referral is primary acquisition channel)
- Mitigation:
- Increase incentive from 50 kr to 75 kr (test)
- Add gamification (leaderboard: "Top 10 referrers get 500 kr bonus")
- Make sharing easier (one-tap WhatsApp share)
- Add social proof ("2,340 people referred their friends")
Risk 2: High Customer Acquisition Cost (CAC)
- Likelihood: Medium
- Impact: High (unprofitable if CAC > LTV)
- Mitigation:
- Start with organic channels (SEO, content, social) before paid ads
- Set strict CPA targets (max 150 kr per user)
- Pause ads if CPA exceeds target 2 weeks in a row
- Focus on viral growth (referral program)
Risk 3: Poor App Store Visibility
- Likelihood: Medium
- Impact: High (low organic installs)
- Mitigation:
- ASO optimization (keyword research, compelling screenshots)
- Incentivize reviews (push notification after 3rd transfer: "Enjoying Drop? Leave a review")
- App Store ads (Apple Search Ads) with strict CPA
- Cross-promote on landing page
Risk 4: Email Deliverability Issues
- Likelihood: Low
- Impact: Medium (users miss onboarding emails)
- Mitigation:
- Use reputable ESP (Resend) with good sender reputation
- Authenticate domain (SPF, DKIM, DMARC)
- Monitor bounce rate (<5% acceptable)
- Avoid spam triggers (no ALL CAPS, excessive exclamation marks)
Risk 5: Referral Fraud
- Likelihood: Medium
- Impact: High (budget drain)
- Mitigation:
- Implement all fraud checks (self-referral, velocity, cap)
- Monitor referral patterns weekly
- Flag accounts with >10 referrals in 24h for manual review
- BankID verification required before rewards
18. Acceptance Criteria
18.1 Landing Page
- Hero CTA updated with incentive ("De første 1000...")
- FAQ section added (5 questions min)
- Comparison table added (Drop vs WU vs Wise vs Bank)
- Mobile sticky CTA bar added
- Plausible tracking installed and tested
- Lighthouse score >= 95
18.2 SEO
- Sitemap.xml created and submitted to Google/Bing
- robots.txt created
- Structured data (Organization + FAQ) added and validated
- 3 subpages created (/send-penger, /qr-betaling, /priser)
- 2 blog posts published
- All pages have unique title + meta description
18.3 UTM & Attribution
- UTM params captured from URL
- UTM params stored in waitlist + users tables
- Attribution reports created (SQL queries)
- Facebook Pixel installed and tracking
- Google Ads conversion tracking installed
18.4 Referral System
- Database schema created (3 tables + indexes)
- Referral code auto-generated on first login
- Referral link click tracked
- Signup attribution works
- First transfer triggers reward issuance
- Referral dashboard UI complete
- Share buttons functional (WhatsApp, SMS, Email)
- Fraud prevention rules implemented
18.5 App Store Listings
- iOS listing drafted (name, subtitle, description, keywords, screenshots, video)
- Android listing drafted (title, short desc, full desc, graphics, screenshots)
- ASO keyword research completed
- All screenshots match Figma design
18.6 Email Marketing
- Waitlist nurture series created (6 emails)
- Onboarding series created (3 emails)
- Re-engagement series created (3 emails)
- Marketing consent checkbox added to registration
- Unsubscribe link works
- All emails tested in Gmail + Outlook
18.7 Analytics
- Plausible installed (landing page)
- Mixpanel installed (app)
- 15 core events tracked (user_registered, first_transfer, etc.)
- 5 dashboards created (Acquisition, Activation, Retention, Referral, Revenue)
- Weekly funnel report automated
18.8 Social Media
- Instagram, Facebook, LinkedIn accounts created
- Profile pictures + bios complete
- 30-day content calendar created
- First 12 posts designed and scheduled
- Paid ads campaign created (5,000 kr budget)
19. Rollout Timeline
Pre-Launch (Weeks 1-10):
- Weeks 1-2: Landing page optimization
- Weeks 3-4: SEO foundation
- Weeks 5-6: UTM & attribution
- Weeks 7-10: Referral system
Launch Week (Week 11):
- Submit app to App Store + Play Store
- Send launch email to waitlist
- Publish launch blog post
- Post on social media (organic)
- Start paid ads (small budget: 2,000 kr/week)
Post-Launch (Weeks 12-16):
- Week 12: Monitor metrics daily, optimize landing page CTA (A/B test)
- Week 13: Scale ads if CPA < 150 kr
- Week 14: Publish 2nd + 3rd blog posts
- Week 15: Analyze first month data, create reports
- Week 16: Iterate on referral incentives based on data
20. Sources
This specification was informed by research on Norwegian fintech regulations, app store optimization best practices, and referral program patterns from successful fintech companies:
Norwegian Regulations:
- Fintech Laws and Regulations Report 2025-2026 Norway
- Marketing - regjeringen.no
- Act relating to the control of marketing and contract terms and conditions, etc - Lovdata
- Electronic marketing in Norway - Data Protection Laws of the World
App Store Optimization:
- Top ASO tips and best practices for 2026, brought to you by ASO experts
- App Store Optimization (ASO) Best Practices for 2026
- App Store Optimization Tips for Fintech Designers
- A short guide to optimising ASO strategies for fintech apps
Referral Programs & Fraud Prevention:
- How Revolut Turned Referrals into a $4B Growth Machine
- How to start a referral program for your fintech startup
- Design a Fraud-Proof Referral Program
- Revolut Referral Rewards: Refer-a-Friend Bonus and Referral Discounts 2026
END OF SPEC
Next Steps:
- Review this spec with Alem for approval
- Create implementation tasks in Mission Control
- Assign tasks to builder agents (Phase 1 → Phase 8)
- Begin Phase 1 (Landing Page Optimization)
Questions for Alem:
- Approve referral incentive structure (50 kr dual-sided)?
- Approve social media ad budget (10,000 kr/month testing)?
- Preferred analytics platform (Plausible + Mixpanel recommended)?
- Timeline for app launch (determines when to prepare App Store listings)?
- Any specific SEO keywords to prioritize beyond the list in Section 4.1?
No comments to display
No comments to display