Skip to main content

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)

SEO Meta Tags Present:

<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:


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

Target Sources:

  1. Norwegian fintech blogs: kryptografen.no, shifter.no, digi.no
  2. Business directories: proff.no, 1881.no (ALAI Holding AS listing → link to Drop)
  3. Press releases: mynewsdesk.com, newswire.no
  4. Partner pages: SpareBank 1 partner page (if approved)
  5. 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):


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):

  1. Hero/Dashboard — Shows total balance + "Send" and "QR Betal" buttons

    • Caption: "Din banksaldo. Alle transaksjoner. Én app."
  2. Send Money Flow — Shows "Velg land" → "Skriv beløp" → "Se gebyr" → "Send"

    • Caption: "Send til 30+ land med 0.5% gebyr"
  3. Fee Comparison — Visual chart: Drop (0.5%) vs Western Union (7%) vs Wise (1%)

    • Caption: "Spar opptil 90% på gebyrer"
  4. QR Payment — Shows QR scanner screen + "Skann og betal"

    • Caption: "Betal i butikk med QR-kode"
  5. Transaction History — Shows recent transactions with dates, amounts, statuses

    • Caption: "Full kontroll over alle transaksjoner"
  6. 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:

  1. 0-5s: Problem — "Sender du penger hjem?" → show high Western Union fees
  2. 5-10s: Solution — "Drop gir deg 0.5% gebyr" → show app interface
  3. 10-15s: Demo — Show send flow (select country → amount → confirm)
  4. 15-20s: QR feature — Show QR scan + payment confirmation
  5. 20-25s: Social proof — "2,340 nordmenn på ventelisten"
  6. 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:

  1. Referrer (Maria) shares link: getdrop.no?ref=maria123
  2. 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."
  3. Sara verifies BankID → completes first transfer (1,000 kr) → gets 50 kr credit
  4. 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:

<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 facebook cpc utm_source=facebook&utm_medium=cpc&utm_campaign=launch_2026
Instagram Ads instagram cpc utm_source=instagram&utm_medium=cpc&utm_campaign=qr_promo
Google Ads google cpc utm_source=google&utm_medium=cpc&utm_campaign=send_penger
LinkedIn Organic linkedin social utm_source=linkedin&utm_medium=social&utm_campaign=alem_post
Email Newsletter email 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

<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_log table

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):

  1. "Slik sender du penger til Tyrkia fra Norge" (target: "send penger til tyrkia")
  2. "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
LinkedIn HIGH Business audience, partnerships, press Company updates, thought leadership 3x/week
Instagram MEDIUM Consumers, visual storytelling Features, user stories, behind-the-scenes 5x/week
Facebook 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
  • 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:

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.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 consents table 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:

  1. 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)
  2. 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
  3. 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)
  4. Add comparison table

    • Create Drop vs Western Union vs Wise vs Bank table
    • Add styling (match landing page design)
  5. Mobile optimization

    • Add sticky CTA bar on mobile
    • Test on iPhone/Android (Safari, Chrome)
  6. 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:

  1. Add structured data

    • Add Organization schema to homepage
    • Add FAQ schema to FAQ section
    • Validate with Google Rich Results Test
  2. Create sitemap.xml

    • Generate sitemap with all pages
    • Submit to Google Search Console
    • Submit to Bing Webmaster Tools
  3. Create robots.txt

    • Allow all except /api/
    • Add sitemap reference
  4. Create blog infrastructure

    • Create /blog/index.html (blog homepage)
    • Create blog post template
    • Write first 2 blog posts (Tyrkia guide, Drop vs WU)
  5. 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:

  1. 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
  2. Update registration flow

    • Modify /api/auth/register to capture UTM from localStorage
    • Add utm_* columns to users table
    • Test registration with UTM params
  3. Create attribution reports

    • SQL query: Waitlist signups by source
    • SQL query: User registrations by source
    • SQL query: Revenue by source (post-launch)
  4. 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:

  1. Database schema

    • Create referral_codes table
    • Create referral_tracking table
    • Create referral_credits table
    • Create indexes
  2. Backend endpoints

    • POST /api/referrals/generate-code
    • POST /api/referrals/track-click
    • Modify /api/auth/register (signup attribution)
    • Modify /api/transactions/remittance (reward issuance)
  3. Referral dashboard UI

    • Create /profile/referrals page
    • Referral link card
    • Stats card (invites, conversions, earnings)
    • Credits balance
    • Referral history
  4. Share functionality

    • WhatsApp share button
    • SMS share button
    • Email share button
    • Copy link button
  5. 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:

  1. 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)
  2. 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)
  3. 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:

  1. 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])
  2. Onboarding series

    • Create 3 email templates (welcome → first transfer nudge)
    • Set up automation triggers (day 0, 3, 7)
    • Test emails
  3. Re-engagement series

    • Create 3 email templates (gentle → win-back → survey)
    • Set up automation triggers (day 30, 60, 90)
    • Test emails
  4. 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:

  1. 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.)
  2. 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)
  3. 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:

  1. Account setup

    • Create @dropnorge Instagram
    • Create facebook.com/dropnorge
    • Create linkedin.com/company/drop-norge
    • Design profile pictures + cover photos
  2. Content calendar

    • Create 30-day content calendar (spreadsheet)
    • Design 12 Instagram posts (Canva)
    • Write captions + hashtags
  3. First month execution

    • Schedule posts (Buffer or Hootsuite)
    • Engage with comments
    • Cross-post to LinkedIn
  4. 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:

  • All 3 social accounts live
  • 30-day content calendar completed
  • First 12 posts designed
  • Posts scheduled for first week

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:

App Store Optimization:

Referral Programs & Fraud Prevention:


END OF SPEC

Next Steps:

  1. Review this spec with Alem for approval
  2. Create implementation tasks in Mission Control
  3. Assign tasks to builder agents (Phase 1 → Phase 8)
  4. Begin Phase 1 (Landing Page Optimization)

Questions for Alem:

  1. Approve referral incentive structure (50 kr dual-sided)?
  2. Approve social media ad budget (10,000 kr/month testing)?
  3. Preferred analytics platform (Plausible + Mixpanel recommended)?
  4. Timeline for app launch (determines when to prepare App Store listings)?
  5. Any specific SEO keywords to prioritize beyond the list in Section 4.1?