# Conversion Rate Optimization (CRO)

**Meta-Description:** Conversion Rate Optimization für SaaS. Landing Pages, User Funnels, Micro-Conversions und datengetriebene Optimierung.

**Keywords:** CRO, Conversion Rate, Landing Page, User Funnel, Micro-Conversions, UX Optimization, Growth Hacking

---

## Einführung

**Conversion Rate Optimization (CRO)** maximiert den Wert bestehenden Traffics. Statt mehr Besucher zu kaufen, werden bestehende Nutzer besser konvertiert. Dieser Guide zeigt systematische Ansätze für **Landing Pages**, **Funnels** und **Micro-Conversions**.

---

## CRO Overview

```
┌─────────────────────────────────────────────────────────────┐
│              CONVERSION OPTIMIZATION FUNNEL                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  TOFU (Top of Funnel):                                     │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Awareness → Interest                               │   │
│  │  ├── Landing Page Views                            │   │
│  │  ├── Blog Post Reads                               │   │
│  │  ├── Social Media Clicks                           │   │
│  │  └── Target: Reduce Bounce Rate                    │   │
│  └─────────────────────────────────────────────────────┘   │
│                           ↓                                 │
│  MOFU (Middle of Funnel):                                  │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Consideration → Intent                             │   │
│  │  ├── Email Signups                                 │   │
│  │  ├── Free Trial Starts                             │   │
│  │  ├── Demo Requests                                 │   │
│  │  └── Target: Increase Lead Quality                 │   │
│  └─────────────────────────────────────────────────────┘   │
│                           ↓                                 │
│  BOFU (Bottom of Funnel):                                  │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Purchase → Retention                               │   │
│  │  ├── Trial to Paid Conversion                      │   │
│  │  ├── Checkout Completion                           │   │
│  │  ├── Upsells / Cross-sells                         │   │
│  │  └── Target: Maximize Revenue                      │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Key Metrics:                                               │
│  ├── Conversion Rate = Conversions / Visitors × 100        │
│  ├── Micro-Conversion Rate (Email, Trial, etc.)            │
│  ├── Revenue per Visitor (RPV)                             │
│  └── Customer Acquisition Cost (CAC)                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘
```

---

## Landing Page Optimization

```tsx
// components/landing/OptimizedHero.tsx
'use client';

import { useState } from 'react';
import { track } from '@/lib/analytics';

interface HeroProps {
  headline: string;
  subheadline: string;
  ctaText: string;
  ctaUrl: string;
  trustBadges: string[];
  videoUrl?: string;
}

export function OptimizedHero({
  headline,
  subheadline,
  ctaText,
  ctaUrl,
  trustBadges,
  videoUrl
}: HeroProps) {
  const [videoPlaying, setVideoPlaying] = useState(false);

  const handleCTAClick = () => {
    track('hero_cta_clicked', {
      headline,
      ctaText
    });
  };

  const handleVideoPlay = () => {
    setVideoPlaying(true);
    track('hero_video_played');
  };

  return (
    <section className="relative py-20 lg:py-32">
      <div className="container mx-auto px-4">
        <div className="grid lg:grid-cols-2 gap-12 items-center">
          {/* Copy Side */}
          <div className="space-y-6">
            {/* Social Proof Mini */}
            <div className="flex items-center gap-2 text-sm text-gray-600">
              <span className="flex -space-x-2">
                {[1, 2, 3, 4, 5].map(i => (
                  <img
                    key={i}
                    src={`/avatars/${i}.jpg`}
                    alt=""
                    className="w-8 h-8 rounded-full border-2 border-white"
                  />
                ))}
              </span>
              <span>Join 10,000+ happy customers</span>
            </div>

            {/* Headline - Max 6 words */}
            <h1 className="text-4xl lg:text-6xl font-bold leading-tight">
              {headline}
            </h1>

            {/* Subheadline - Benefits focused */}
            <p className="text-xl text-gray-600 max-w-lg">
              {subheadline}
            </p>

            {/* CTA Group */}
            <div className="flex flex-col sm:flex-row gap-4">
              <a
                href={ctaUrl}
                onClick={handleCTAClick}
                className="btn-primary text-lg px-8 py-4 text-center"
              >
                {ctaText}
              </a>
              <span className="text-sm text-gray-500 self-center">
                No credit card required
              </span>
            </div>

            {/* Trust Badges */}
            <div className="flex flex-wrap gap-4 pt-4">
              {trustBadges.map((badge, i) => (
                <div
                  key={i}
                  className="flex items-center gap-2 text-sm text-gray-600"
                >
                  <CheckIcon className="w-5 h-5 text-green-500" />
                  {badge}
                </div>
              ))}
            </div>
          </div>

          {/* Visual Side */}
          <div className="relative">
            {videoUrl ? (
              <VideoPlayer
                url={videoUrl}
                onPlay={handleVideoPlay}
                playing={videoPlaying}
              />
            ) : (
              <img
                src="/hero-image.webp"
                alt="Product screenshot"
                className="rounded-lg shadow-2xl"
              />
            )}
          </div>
        </div>
      </div>
    </section>
  );
}
```

```tsx
// components/landing/SocialProof.tsx
interface Testimonial {
  quote: string;
  author: string;
  role: string;
  company: string;
  avatar: string;
  logo: string;
  metric?: string;
}

export function SocialProofSection({
  testimonials
}: {
  testimonials: Testimonial[]
}) {
  return (
    <section className="py-20 bg-gray-50">
      <div className="container mx-auto px-4">
        {/* Logos Bar */}
        <div className="text-center mb-12">
          <p className="text-sm text-gray-500 mb-6">
            Trusted by leading companies
          </p>
          <div className="flex flex-wrap justify-center items-center gap-8 opacity-60">
            {testimonials.map((t, i) => (
              <img
                key={i}
                src={t.logo}
                alt={t.company}
                className="h-8 grayscale hover:grayscale-0 transition"
              />
            ))}
          </div>
        </div>

        {/* Testimonials Grid */}
        <div className="grid md:grid-cols-3 gap-8">
          {testimonials.map((testimonial, i) => (
            <TestimonialCard key={i} {...testimonial} />
          ))}
        </div>

        {/* Aggregate Stats */}
        <div className="grid grid-cols-2 md:grid-cols-4 gap-8 mt-16 text-center">
          <Stat value="10,000+" label="Active Users" />
          <Stat value="99.9%" label="Uptime" />
          <Stat value="4.9/5" label="Customer Rating" />
          <Stat value="24/7" label="Support" />
        </div>
      </div>
    </section>
  );
}

function TestimonialCard({
  quote,
  author,
  role,
  company,
  avatar,
  metric
}: Testimonial) {
  return (
    <div className="bg-white p-6 rounded-xl shadow-sm">
      {metric && (
        <div className="text-3xl font-bold text-blue-600 mb-4">
          {metric}
        </div>
      )}
      <blockquote className="text-gray-700 mb-4">
        "{quote}"
      </blockquote>
      <div className="flex items-center gap-3">
        <img
          src={avatar}
          alt={author}
          className="w-12 h-12 rounded-full"
        />
        <div>
          <div className="font-semibold">{author}</div>
          <div className="text-sm text-gray-500">{role}, {company}</div>
        </div>
      </div>
    </div>
  );
}
```

---

## Funnel Tracking

```typescript
// lib/cro/funnel.ts
export interface FunnelStep {
  id: string;
  name: string;
  pagePattern: string | RegExp;
  requiredEvents?: string[];
}

export interface FunnelConfig {
  id: string;
  name: string;
  steps: FunnelStep[];
}

export const signupFunnel: FunnelConfig = {
  id: 'signup',
  name: 'Signup Funnel',
  steps: [
    { id: 'landing', name: 'Landing Page', pagePattern: '/' },
    { id: 'pricing', name: 'Pricing Page', pagePattern: '/pricing' },
    { id: 'signup-start', name: 'Signup Started', pagePattern: '/signup', requiredEvents: ['signup_form_viewed'] },
    { id: 'signup-complete', name: 'Signup Complete', pagePattern: '/welcome', requiredEvents: ['signup_completed'] },
    { id: 'onboarding', name: 'Onboarding', pagePattern: '/onboarding' },
    { id: 'activated', name: 'Activated', pagePattern: '/dashboard', requiredEvents: ['first_action_completed'] }
  ]
};

// Funnel Analytics
export async function getFunnelAnalytics(
  funnelId: string,
  startDate: Date,
  endDate: Date
): Promise<FunnelAnalytics> {
  const funnel = funnels.get(funnelId);
  if (!funnel) throw new Error(`Funnel ${funnelId} not found`);

  const stepData = await Promise.all(
    funnel.steps.map(async (step, index) => {
      const count = await getStepCount(step, startDate, endDate);
      const previousCount = index > 0
        ? await getStepCount(funnel.steps[index - 1], startDate, endDate)
        : count;

      return {
        step: step.name,
        count,
        conversionRate: previousCount > 0 ? (count / previousCount) * 100 : 100,
        dropoffRate: previousCount > 0 ? ((previousCount - count) / previousCount) * 100 : 0
      };
    })
  );

  const overallConversion = stepData[0].count > 0
    ? (stepData[stepData.length - 1].count / stepData[0].count) * 100
    : 0;

  return {
    funnel: funnel.name,
    period: { start: startDate, end: endDate },
    steps: stepData,
    overallConversion
  };
}
```

```tsx
// components/analytics/FunnelVisualization.tsx
'use client';

interface FunnelStep {
  step: string;
  count: number;
  conversionRate: number;
  dropoffRate: number;
}

export function FunnelVisualization({ steps }: { steps: FunnelStep[] }) {
  const maxCount = Math.max(...steps.map(s => s.count));

  return (
    <div className="space-y-4">
      {steps.map((step, index) => {
        const width = (step.count / maxCount) * 100;
        const isLastStep = index === steps.length - 1;

        return (
          <div key={step.step} className="relative">
            {/* Step Bar */}
            <div className="flex items-center gap-4">
              <div className="w-32 text-sm font-medium">{step.step}</div>
              <div className="flex-1 h-12 bg-gray-100 rounded-lg overflow-hidden">
                <div
                  className="h-full bg-blue-500 flex items-center justify-end px-4 transition-all"
                  style={{ width: `${width}%` }}
                >
                  <span className="text-white font-semibold">
                    {step.count.toLocaleString()}
                  </span>
                </div>
              </div>
              <div className="w-20 text-right">
                <span className={`text-sm font-medium ${
                  step.conversionRate >= 50 ? 'text-green-600' : 'text-red-600'
                }`}>
                  {step.conversionRate.toFixed(1)}%
                </span>
              </div>
            </div>

            {/* Dropoff Indicator */}
            {!isLastStep && step.dropoffRate > 0 && (
              <div className="ml-32 pl-4 py-2 text-sm text-red-500">
                ↳ {step.dropoffRate.toFixed(1)}% dropoff ({Math.round(step.count * step.dropoffRate / 100).toLocaleString()} users)
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
}
```

---

## Micro-Conversions

```typescript
// lib/cro/micro-conversions.ts
export const microConversions = {
  engagement: [
    { id: 'scroll_depth_50', name: 'Scrolled 50%', weight: 1 },
    { id: 'scroll_depth_90', name: 'Scrolled 90%', weight: 2 },
    { id: 'time_on_page_60s', name: '60s on page', weight: 2 },
    { id: 'video_played', name: 'Video Played', weight: 3 },
    { id: 'video_completed', name: 'Video Completed', weight: 5 }
  ],
  intent: [
    { id: 'pricing_viewed', name: 'Viewed Pricing', weight: 5 },
    { id: 'feature_comparison', name: 'Compared Features', weight: 4 },
    { id: 'faq_expanded', name: 'Expanded FAQ', weight: 2 },
    { id: 'live_chat_started', name: 'Started Live Chat', weight: 8 }
  ],
  lead: [
    { id: 'email_captured', name: 'Email Signup', weight: 10 },
    { id: 'demo_requested', name: 'Demo Request', weight: 15 },
    { id: 'trial_started', name: 'Trial Started', weight: 20 }
  ]
};

// Calculate Lead Score
export function calculateLeadScore(events: string[]): number {
  let score = 0;

  Object.values(microConversions).flat().forEach(conversion => {
    if (events.includes(conversion.id)) {
      score += conversion.weight;
    }
  });

  return score;
}

// hooks/useMicroConversions.ts
'use client';

import { useEffect, useCallback } from 'react';
import { track } from '@/lib/analytics';

export function useMicroConversions() {
  // Scroll Depth Tracking
  useEffect(() => {
    let maxScroll = 0;
    const milestones = [25, 50, 75, 90];
    const triggered = new Set<number>();

    const handleScroll = () => {
      const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
      const scrollPercent = Math.round((window.scrollY / scrollHeight) * 100);

      if (scrollPercent > maxScroll) {
        maxScroll = scrollPercent;

        milestones.forEach(milestone => {
          if (scrollPercent >= milestone && !triggered.has(milestone)) {
            triggered.add(milestone);
            track(`scroll_depth_${milestone}`);
          }
        });
      }
    };

    window.addEventListener('scroll', handleScroll, { passive: true });
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  // Time on Page Tracking
  useEffect(() => {
    const milestones = [30, 60, 120, 300];
    let elapsed = 0;

    const interval = setInterval(() => {
      elapsed += 1;

      if (milestones.includes(elapsed)) {
        track(`time_on_page_${elapsed}s`);
      }
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  // Track specific actions
  const trackMicro = useCallback((eventId: string, metadata?: Record<string, unknown>) => {
    track(eventId, metadata);
  }, []);

  return { trackMicro };
}
```

---

## Form Optimization

```tsx
// components/forms/OptimizedSignupForm.tsx
'use client';

import { useState, useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { track } from '@/lib/analytics';

const signupSchema = z.object({
  email: z.string().email('Please enter a valid email'),
  password: z.string().min(8, 'Password must be at least 8 characters'),
  name: z.string().min(2, 'Name is required')
});

type SignupData = z.infer<typeof signupSchema>;

export function OptimizedSignupForm() {
  const [step, setStep] = useState(1);
  const [startTime] = useState(Date.now());

  const {
    register,
    handleSubmit,
    formState: { errors, isSubmitting },
    watch
  } = useForm<SignupData>({
    resolver: zodResolver(signupSchema),
    mode: 'onBlur'
  });

  // Track form interactions
  useEffect(() => {
    track('signup_form_viewed');
  }, []);

  const email = watch('email');

  useEffect(() => {
    if (email && email.includes('@')) {
      track('signup_email_entered');
    }
  }, [email]);

  const onSubmit = async (data: SignupData) => {
    const timeToComplete = Date.now() - startTime;

    track('signup_form_submitted', {
      timeToComplete,
      step
    });

    try {
      await createAccount(data);
      track('signup_completed', { timeToComplete });
    } catch (error) {
      track('signup_error', { error: (error as Error).message });
    }
  };

  // Field focus tracking
  const trackFieldFocus = (field: string) => {
    track('form_field_focused', { field });
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
      {/* Progress Indicator */}
      <div className="flex gap-2 mb-6">
        {[1, 2, 3].map(s => (
          <div
            key={s}
            className={`h-1 flex-1 rounded ${
              s <= step ? 'bg-blue-600' : 'bg-gray-200'
            }`}
          />
        ))}
      </div>

      {/* Step 1: Email */}
      {step >= 1 && (
        <div>
          <label className="block text-sm font-medium mb-2">
            Work Email
          </label>
          <input
            type="email"
            {...register('email')}
            onFocus={() => trackFieldFocus('email')}
            className="w-full px-4 py-3 border rounded-lg focus:ring-2 focus:ring-blue-500"
            placeholder="you@company.com"
            autoComplete="email"
          />
          {errors.email && (
            <p className="text-red-500 text-sm mt-1">{errors.email.message}</p>
          )}
        </div>
      )}

      {/* Step 2: Password */}
      {step >= 2 && (
        <div>
          <label className="block text-sm font-medium mb-2">
            Create Password
          </label>
          <input
            type="password"
            {...register('password')}
            onFocus={() => trackFieldFocus('password')}
            className="w-full px-4 py-3 border rounded-lg"
            placeholder="8+ characters"
          />
          {errors.password && (
            <p className="text-red-500 text-sm mt-1">{errors.password.message}</p>
          )}
          {/* Password Strength */}
          <PasswordStrengthMeter password={watch('password') || ''} />
        </div>
      )}

      {/* CTA Button */}
      <button
        type={step < 2 ? 'button' : 'submit'}
        onClick={() => step < 2 && setStep(step + 1)}
        disabled={isSubmitting}
        className="w-full py-4 bg-blue-600 text-white rounded-lg font-semibold hover:bg-blue-700 disabled:opacity-50"
      >
        {isSubmitting ? 'Creating account...' : step < 2 ? 'Continue' : 'Create Free Account'}
      </button>

      {/* Trust Signals */}
      <div className="flex items-center justify-center gap-4 text-sm text-gray-500">
        <span className="flex items-center gap-1">
          <LockIcon className="w-4 h-4" />
          Secure
        </span>
        <span>No credit card required</span>
        <span>Cancel anytime</span>
      </div>
    </form>
  );
}
```

---

## CRO Checklist

| Element | Best Practice |
|---------|--------------|
| **Headline** | Clear value proposition, max 6 words |
| **CTA** | Action-oriented, contrasting color |
| **Social Proof** | Numbers, logos, testimonials |
| **Trust Signals** | Security badges, guarantees |
| **Forms** | Progressive, minimal fields |
| **Mobile** | Touch-friendly, fast loading |
| **Urgency** | Scarcity, limited time (honest!) |
| **Exit Intent** | Offer value, not desperation |

---

## Fazit

Conversion Rate Optimization erfordert:

1. **Datenanalyse**: Funnels und Micro-Conversions tracken
2. **User Research**: Verstehen warum Nutzer konvertieren
3. **Testing**: Systematisches A/B Testing
4. **Iteration**: Kontinuierliche Verbesserung

Kleine Verbesserungen summieren sich zu großen Ergebnissen.

---

## Bildprompts

1. "Conversion funnel visualization, colorful stages with dropoff points"
2. "Landing page wireframe with CRO annotations, best practices highlighted"
3. "A/B test results dashboard, winner variant celebration"

---

## Quellen

- [CXL Conversion Optimization Guide](https://cxl.com/blog/conversion-optimization-guide/)
- [Unbounce Landing Page Best Practices](https://unbounce.com/landing-page-articles/)
- [Hotjar CRO Resources](https://www.hotjar.com/conversion-rate-optimization/)
- [Neil Patel CRO Guide](https://neilpatel.com/blog/conversion-rate-optimization/)
