# Comparison Pages Template Analysis


**Last Updated:** 2025-11-20

## Overview

This document contains a deep analysis of the two existing comparison page templates, identifying all customization points, differences, and common patterns to inform the creation of a unified template.

## Template Files Analyzed

- `v2/pages/compare_template_details.php` (~2326 lines)
- `v2/pages/compare_template_nodetails.php` (~2232 lines)

## Key Differences

### Primary Difference: Details Section

**Details Template (lines ~1010-1065)**:

- Contains expandable "Details" section with Alpine.js
- Shows competitor features, integrations, and special characteristics
- Button text: `{COMPETITOR_DETAILS_BUTTON}`
- Three subsections:
  - "Dazu zählen:" - Features list
  - "u. a. sind folgende Schnittstellen vorhanden:" - Integrations list
  - "Das macht {competitor} besonders:" - Special characteristics list

**No Details Template (lines ~956-959)**:

- Contains invisible placeholder div for height alignment
- Uses Alpine.js binding: `:style="{ height: ordioDetailsHeight + 'px' }"`
- Hidden on mobile: `class="hidden lg:block"`
- No content inside, just maintains layout alignment

### Similarities (95%+ identical)

Both templates share:

- Identical header structure with meta tags
- Identical schema.org JSON-LD structure
- Identical hero section layout
- Identical comparison grid layout
- Identical Ordio column (left side)
- Identical star rating distribution section
- Identical category ratings section
- Identical pricing section
- Identical FAQ structure
- Identical footer and includes

## Customization Points Identified

### 1. Meta Tags & SEO (15 fields)

**Title**:

- Pattern: `{COMPETITOR} Alternativen: Vergleich & Bewertung 2025 - Ordio`
- Location: Line ~81 (details), ~76 (nodetails)

**Description**:

- Pattern: `{COMPETITOR} Alternativen im Vergleich 2025: Ordio vs {COMPETITOR}. {COMPETITOR_FOCUS}. Finde die beste {COMPETITOR_CATEGORY} Alternative.`
- Location: Line ~82 (details), ~77 (nodetails)

**Keywords**:

- Pattern: `{COMPETITOR} Alternativen, {COMPETITOR} Vergleich, {COMPETITOR_CATEGORY} Software, {COMPETITOR_FOCUS}, Ordio vs {COMPETITOR}, {COMPETITOR_CATEGORY}`
- Location: Line ~83 (details), ~78 (nodetails)

**Canonical URL**:

- Pattern: `https://www.ordio.com/alternativen/{competitor-slug}-vergleich`
- Location: Line ~97 (details), ~92 (nodetails)

**Open Graph Tags** (7 fields):

- og:title, og:description, og:url, og:image, og:image:alt, og:site_name, og:locale
- Location: Lines ~105-117 (details), ~100-112 (nodetails)

### 2. Schema.org Structured Data (6 schema types)

**WebPage Schema**:

- @id, url, name, description, dateModified
- Location: Lines ~127-147 (details), ~122-142 (nodetails)

**Article Schema**:

- headline, description, datePublished, dateModified
- Location: Lines ~149-176 (details), ~144-171 (nodetails)

**Table Schema**:

- about, description, mainEntity (Ordio and Competitor products)
- Location: Lines ~178-235 (details), ~173-230 (nodetails)

**Product Schema (Competitor)**:

- name, brand, offers (price, priceCurrency, unitText), aggregateRating
- Location: Lines ~211-235 (details), ~206-230 (nodetails)

**SoftwareApplication Schema**:

- name, description, applicationCategory, offers, aggregateRating
- Location: Lines ~237-261 (details), ~232-256 (nodetails)

**BreadcrumbList Schema**:

- itemListElement with 3 items (Home, Alternativen, Competitor)
- Location: Lines ~263-285 (details), ~258-280 (nodetails)

**FAQPage Schema**:

- mainEntity array with Question/Answer pairs
- Location: Lines ~287-290 (details), ~282-285 (nodetails)
- Placeholder: `{COMPETITOR_FAQ_SCHEMA_ITEMS}`

### 3. Hero Section (8 fields)

**Competitor Logo**:

- Image src: `/v2/img/alternativen/{competitor}-vergleich-logo-160w.webp`
- Image srcset: 160w, 320w variants
- Image sizes: `(max-width: 640px) 160px, 160px`
- Alt text: `{COMPETITOR_LOGO_ALT}`
- CSS class: `{COMPETITOR_LOGO_CLASS}` (e.g., "brightness-0 invert")
- Width/height: 160x32
- Location: Lines ~315-340 (details), ~310-335 (nodetails)

**Hero Text**:

- H1: `{COMPETITOR} Alternativen: Vergleich & Bewertung 2025`
- Description: `Welche Alternativen zu {COMPETITOR} gibt es? Entdecke den detaillierten Vergleich zwischen Ordio und {COMPETITOR}: Preise, Funktionen und Bewertungen im direkten Vergleich. Finde die beste {COMPETITOR_CATEGORY} Alternative für {COMPETITOR_FOCUS}.`
- Location: Lines ~342-345 (details), ~337-340 (nodetails)

**Preload Link** (in head):

- href: `/v2/img/alternativen/{competitor}-vergleich-logo-160w.webp`
- Location: Line ~103 (details), ~98 (nodetails)

### 4. Comparison Section Heading

- Text: `Ordio vs. {COMPETITOR}`
- Location: Lines ~702-705 (details), ~697-700 (nodetails)

### 5. Competitor Column - Header (4 fields)

**Logo**:

- Same as hero logo (160w, 320w variants)
- Location: Lines ~934-941 (details), ~929-936 (nodetails)

**Rating Display**:

- Star icons (5 SVGs with conditional fill based on rating)
- Rating value: `{COMPETITOR_RATING}`
- Review count: `{COMPETITOR_REVIEWS} Bewertungen`
- Location: Lines ~943-961 (details), ~938-956 (nodetails)

### 6. Competitor Column - Product Description (2 fields)

**Heading**:

- Details template: `Entwickelt mit und für kleine und mittelständische Unternehmen` (customizable)
- No Details template: `Was ist {COMPETITOR}?`
- Location: Line ~1004 (details), ~950 (nodetails)

**Description Text**:

- Placeholder: `{COMPETITOR_DESCRIPTION}`
- Location: Line ~1006 (details), ~952 (nodetails)

### 7. Competitor Column - Details Section

**Details Template Only** (lines ~1010-1065):

- `button_text`: `{COMPETITOR_DETAILS_BUTTON}`
- `features`: Array of feature items with checkmark SVG
- `integrations`: Array of integration items with checkmark SVG
- `special`: Array of special characteristic items with checkmark SVG

**No Details Template** (lines ~956-959):

- Invisible placeholder div with dynamic height

### 8. Competitor Column - Star Rating Distribution (11 fields)

**Overall Rating Display**:

- Star SVGs (5 stars with partial fill)
- Rating value displayed
- Location: Lines ~1070-1084 (details), ~965-979 (nodetails)

**Distribution Bars** (5 rows for 5★, 4★, 3★, 2★, 1★):

- Each row contains:
  - Label: "5★", "4★", etc.
  - Progress bar with percentage width
  - Tooltip with percentage
  - Count label
- Data needed per row:
  - Percentage (for bar width)
  - Count (for count label)
- Location: Lines ~1085-1137 (details), ~980-1032 (nodetails)

### 9. Competitor Column - Category Ratings (4 ratings)

Each rating contains:

- SVG circular progress indicator
- Score value (e.g., 9.7)
- Category name (Benutzerfreundlichkeit, Erfüllung der Anforderungen, Kundensupport, Einfache Einrichtung)
- Category context (e.g., "Zeiterfassung")
- Category average (e.g., "Kategorie-Durchschnitt: 9")

Data needed:

- Score (numeric, e.g., 9.7)
- Stroke dasharray for circular progress (calculated from score)
- Category name
- Category context
- Category average

Location: Lines ~1141-1221 (details), ~1036-1116 (nodetails)

### 10. Competitor Column - Pricing Section

**Pricing Plans** (variable number):
Each plan card contains:

- Plan name (e.g., "Digitale Stechuhr")
- Plan description (e.g., "Zeiterfassung per App")
- Price (e.g., "€3,19")
- Unit (e.g., "/ User / Monat")

Data structure needed:

```php
[
    'name' => 'Plan Name',
    'description' => 'Plan description',
    'price' => '3.19',
    'unit' => 'User / Monat'
]
```

Location: Lines ~1225-1269 (details), ~1120-1164 (nodetails)

### 11. FAQ Section (2 fields)

**FAQ Title**:

- Pattern: `Häufige Fragen zu {COMPETITOR} & {COMPETITOR_CATEGORY} Alternativen 2025`
- Location: Lines ~1850-1852 (details), ~1745-1747 (nodetails)

**FAQ Items**:

- HTML structure: `<details>` elements with question/answer
- Schema structure: JSON array of Question/Answer objects
- Placeholder: `{COMPETITOR_FAQ_ITEMS}` (HTML)
- Placeholder: `{COMPETITOR_FAQ_SCHEMA_ITEMS}` (JSON)
- Location: Lines ~1855-1858 (FAQ HTML), ~287-290 (FAQ schema details), ~282-285 (FAQ schema nodetails)

### 12. Additional Schema Fields

**Schema Name** (may differ from display name):

- Example: "ClockIn" vs "Clockin"
- Used in: SoftwareApplication schema, Product schema
- Location: Various schema sections

**Schema Description**:

- Fuller description for schema
- Used in: SoftwareApplication schema
- Location: Line ~241 (details), ~236 (nodetails)

## Placeholder Count Summary

Total placeholders identified: **45+**

By category:

- Basic info: 4 (name, slug, category, focus)
- Logo/images: 3 (alt, class, paths)
- Meta tags: 8 (title, description, keywords, canonical, OG tags)
- Schema: 12 (various schema fields)
- Hero: 2 (heading, description)
- Ratings: 11 (overall, distribution 5 rows x 2 fields each)
- Category ratings: 4 (4 categories x score/average)
- Product description: 2 (heading, text)
- Details section: 4 (button, features, integrations, special)
- Pricing: Variable (typically 3-4 plans)
- FAQ: 2+ (title, items array)

## Common Patterns

### 1. Star Rating Rendering

**Full Star**:

```html
<svg class="w-5 h-5" viewBox="0 0 20 20" fill="#facc15">
  <path
    d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z"
  />
</svg>
```

**Partial Star** (e.g., 90% for 4.9 rating):

```html
<svg class="w-5 h-5 relative" viewBox="0 0 20 20">
  <path
    fill="#d1d5db"
    d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z"
  />
  <path
    fill="#facc15"
    d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z"
    clip-path="inset(0 10% 0 0)"
  />
</svg>
```

Calculation: Partial star percentage = (rating - floor(rating)) \* 100
Example: 4.9 → 90% fill → clip-path="inset(0 10% 0 0)"

### 2. Rating Bar Rendering

```html
<div class="rating-row">
  <span class="star-label text-gray-600">5★</span>
  <div class="flex-1 rating-bar-bg bg-gray-200 rounded-full mx-3">
    <div class="rating-bar-container">
      <div
        class="rating-bar-fill bg-gray-500 rounded-full"
        style="width: 96%"
        data-percentage="96%"
      ></div>
      <div
        class="rating-tooltip"
        role="tooltip"
        aria-label="5-Star Rating: 96%"
      >
        96%
      </div>
    </div>
  </div>
  <span class="count-label text-gray-600">316</span>
</div>
```

### 3. Category Rating Rendering

```html
<div class="flex items-center space-x-4">
  <div class="relative w-16 h-16 flex-shrink-0">
    <svg class="w-16 h-16 transform -rotate-90" viewBox="0 0 36 36">
      <path
        class="text-gray-300"
        stroke="currentColor"
        stroke-width="3"
        fill="none"
        d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
      />
      <path
        class="text-blue-500"
        stroke="currentColor"
        stroke-width="3"
        stroke-linecap="round"
        fill="none"
        stroke-dasharray="97, 100"
        d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
      />
    </svg>
    <div class="absolute inset-0 flex items-center justify-center">
      <span class="text-lg font-bold text-gray-900">9.7</span>
    </div>
  </div>
  <div>
    <p class="text-sm font-medium text-gray-900">Benutzerfreundlichkeit</p>
    <p class="text-xs text-gray-500">Zeiterfassung</p>
    <p class="text-xs text-gray-500">Kategorie-Durchschnitt: 9</p>
  </div>
</div>
```

Calculation: stroke-dasharray = (score / 10 \* 100) + ", 100"
Example: 9.7 → 97, 100

### 4. Pricing Plan Rendering

```html
<div class="bg-gray-50 rounded-lg p-4">
  <div class="flex justify-between items-start mb-2">
    <div>
      <h5 class="font-medium text-gray-900 mb-1">Plan Name</h5>
      <p class="text-xs text-gray-500">Plan description</p>
    </div>
    <div class="text-right">
      <span class="text-2xl font-bold text-ordio-blue">€3,19</span>
      <p class="text-sm text-gray-600">/ User / Monat</p>
    </div>
  </div>
</div>
```

### 5. Details Section Feature List

```html
<div class="flex items-center text-sm text-gray-600 checkmark-container">
  <svg class="w-4 h-4 mr-2 checkmark-icon" fill="#10b981" viewBox="0 0 20 20">
    <path
      fill-rule="evenodd"
      d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
      clip-rule="evenodd"
    ></path>
  </svg>
  Feature text here
</div>
```

## Recommendations for Unified Template

### 1. Use Conditional Rendering for Details Section

```php
<?php if ($competitorData['has_details']): ?>
    <!-- Render expandable Details section -->
<?php else: ?>
    <!-- Render invisible placeholder div -->
<?php endif; ?>
```

### 2. Create Helper Functions

Essential helper functions:

- `renderStarRating($rating)` - Generate 5 stars with partial fill
- `renderRatingBar($starLevel, $count, $percentage)` - Generate rating bar row
- `renderCategoryRating($name, $score, $category, $average)` - Generate category rating circle
- `renderPricingPlan($plan)` - Generate pricing card
- `renderFeatureItem($text)` - Generate checkmark list item
- `generateSchema($competitorData)` - Generate all JSON-LD schemas
- `generateMetaTags($competitorData)` - Generate all meta tags

### 3. Data Validation

Required validations:

- Check presence of required fields
- Validate data types (ratings are numeric, counts are integers)
- Validate ranges (ratings 0-5, percentages 0-100)
- Validate array structures (rating distribution, pricing plans)

### 4. FAQ Placeholder Structure

```php
'faq' => [
    'title' => 'Häufige Fragen zu {Competitor} & {Category} Alternativen 2025',
    'items' => [
        // Placeholder: Will be optimized based on SEO reports per competitor
        // Keep one example for structure:
        [
            'question' => 'Was kostet {Competitor}?',
            'answer' => 'Placeholder answer...'
        ]
    ]
]
```

## Next Steps

1. Create data structure file with validation functions
2. Create helper functions file with all rendering functions
3. Create unified template using conditional rendering
4. Test with both has_details=true and has_details=false cases
5. Create comprehensive documentation
