# Comparison Pages Structure Reference


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

Complete breakdown of comparison page structure, sections, components, and data dependencies for creating and maintaining comparison pages.

## Table of Contents

1. [Page Structure Overview](#page-structure-overview)
2. [Template Selection](#template-selection)
3. [Head Section](#head-section)
4. [Body Sections](#body-sections)
5. [Component Dependencies](#component-dependencies)
6. [Data File Structure](#data-file-structure)
7. [Schema Structure](#schema-structure)
8. [Image Requirements](#image-requirements)

## Template Selection

Comparison pages use one of two templates:

- **`compare_template_details.php`** - For pages with competitor Details section (expandable features/integrations)
- **`compare_template_nodetails.php`** - For pages without competitor Details section (invisible placeholder for height alignment)

See `docs/guides/COMPARISON_PAGES_TEMPLATE_USAGE.md` for detailed template selection criteria and usage instructions.

## Page Structure Overview

Comparison pages follow a standardized structure optimized for SEO, performance, and user experience:

```
<!doctype html>
<html lang="de">
<head>
    <!-- Meta tags, schema, CSS -->
</head>
<body>
    <!-- Header -->
    <!-- Hero Section -->
    <!-- Company Logos Section -->
    <!-- Comparison Section -->
    <!-- Ordio Verteiler Section -->
    <!-- In bester Gesellschaft Section -->
    <!-- Comparison Carousel -->
    <!-- FAQs -->
    <!-- Footer -->
    <!-- Lead Capture Popup -->
</body>
</html>
```

## Head Section

### Required Meta Tags

```php
<title>{Competitor} Alternativen: Vergleich & Bewertung 2025 - Ordio</title>
<meta name="description" content="{Competitor} Alternativen im Vergleich 2025: Ordio vs {Competitor}. [Focus] für [Target Audience]. Finde die beste [Category]-Alternative." />
<meta name="keywords" content="{Competitor} Alternativen, {Competitor} Vergleich, {Competitor} [Feature], Ordio vs {Competitor}, [Category] Software" />
<meta name="author" content="Ordio GmbH">
<meta name="robots" content="index, follow" />
<meta name="apple-mobile-web-app-title" content="{Competitor} Alternativen 2025 - Ordio">
<meta name="theme-color" content="#ffffff">
```

### Canonical URL

```php
<link rel="canonical" href="https://www.ordio.com/alternativen/{competitor}-vergleich">
```

### Open Graph Tags

```php
<meta property="og:type" content="website">
<meta property="og:title" content="{Competitor} Alternativen: Vergleich & Bewertung 2025 - Ordio">
<meta property="og:description" content="{Competitor} Alternativen im Vergleich 2025: Ordio vs {Competitor}. [Description]">
<meta property="og:url" content="https://www.ordio.com/alternativen/{competitor}-vergleich">
<meta property="og:image" content="https://www.ordio.com/v2/img/content/ordio-alternativen.webp">
<meta property="og:image:alt" content="{Competitor} Alternativen Vergleich - Ordio vs {Competitor}">
<meta property="og:site_name" content="Ordio">
<meta property="og:locale" content="de_DE">
```

### Twitter Card Tags

```php
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{Competitor} Alternativen: Vergleich & Bewertung 2025 - Ordio">
<meta name="twitter:description" content="{Competitor} Alternativen im Vergleich 2025: Ordio vs {Competitor}. [Description]">
<meta name="twitter:image" content="https://www.ordio.com/v2/img/content/ordio-alternativen.webp">
```

### CSS Includes

```php
<?php
$aosScript = "true";  // Enable AOS animations
$swiperScript = "false";  // Disable Swiper (not used on comparison pages)
include '../base/head.php';
?>

<link rel="stylesheet" href="/v2/css/comparison-pages.css?v=<?php echo filemtime($_SERVER['DOCUMENT_ROOT'] . '/v2/css/comparison-pages.css'); ?>" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="/v2/css/comparison-pages.css"></noscript>
```

### Image Preload

```php
<!-- Preload LCP image (competitor logo) -->
<link rel="preload" href="/v2/img/alternativen/{competitor}-vergleich-logo-160w.webp" as="image" fetchpriority="high">
```

## Body Sections

### Header Include

```php
<?php
$headerwidth = "w-full";
include '../base/header.php';
?>
```

### Hero Section

**Structure:**

```php
<section>
    <div class="relative">
        <div class="absolute inset-0 flex flex-col" aria-hidden="true">
            <div class="flex-1 w-full"></div>
        </div>
        <div class="mx-auto max-w-md sm:max-w-2xl sm:px-6 lg:px-16 lg:max-w-7xl grid lg:grid-cols-2 lg:gap-6">
            <!-- Left Column: Text Content -->
            <div class="relative mx-auto max-w-md px-4 sm:max-w-3xl sm:px-6 lg:px-0">
                <div class="pt-12 sm:pt-16 lg:pt-20">
                    <h1 class="text-5xl sm:text-7xl font-gilroybold leading-[102%] tracking-[-1.5px]">
                        {Competitor} Alternativen: <span class="text-ordio-blue">Vergleich</span> & <span class="text-ordio-blue">Bewertung</span> 2025
                    </h1>
                    <p class="text-lg mt-6">
                        [Competitor description and positioning]
                    </p>
                    <!-- CTA Buttons -->
                    <?php
                    $ctaPositionLeft = 'true';
                    $ctaButtonsAOS = 'false';
                    $ctaButtonsLight = 'yes';
                    $showCallbackButton = 'yes';
                    include '../base/include_ctabuttons.php';
                    ?>
                </div>
            </div>
            <!-- Right Column: Visual Content -->
            <div class="relative mx-auto max-w-md px-4 sm:max-w-3xl sm:px-6 lg:px-0">
                <!-- Competitor logo and visual elements -->
            </div>
        </div>
    </div>
</section>
```

**Competitor Logo Image:**

```php
<img src="/v2/img/alternativen/{competitor}-vergleich-logo-160w.webp"
     srcset="/v2/img/alternativen/{competitor}-vergleich-logo-160w.webp 160w,
             /v2/img/alternativen/{competitor}-vergleich-logo-320w.webp 320w"
     sizes="(max-width: 640px) 160px, 160px"
     alt="{Competitor}"
     class="max-h-8 max-w-full object-contain"
     width="160"
     height="32"
     fetchpriority="high">
```

### Company Logos Section

**Structure:**

```php
<div class="uppercase tracking-widest text-center text-xs mt-0 font-inter600 mb-6">
    Täglich genutzt von +1.700 Unternehmen
</div>

<div class="relative mx-auto py-3 z-10 overflow-hidden max-w-6xl mx-auto mb-4">
    <div class="logo-slider flex gap-12 max-w-[2100px] mx-auto justify-start px-16" style="animation: slide 75s linear infinite;">
        <!-- Logo images (duplicated for seamless loop) -->
    </div>
    <!-- Gradient overlays -->
    <div class="absolute inset-y-0 left-0 w-32 bg-gradient-to-l from-transparent to-[#fbfbfb] dark:to-[#fbfbfb] z-10"></div>
    <div class="absolute inset-y-0 right-0 w-32 bg-gradient-to-r from-transparent to-[#fbfbfb] dark:to-[#fbfbfb] z-10"></div>
</div>
```

### Comparison Section

**Structure:**

```php
<section>
    <div class="text-center p-10 px-6 lg:px-20 pt-16 bg-[#fbfbfb] overflow-hidden">
        <div class="max-w-7xl mx-auto">
            <div class="max-w-2xl mx-auto">
                <div class="mx-auto w-[120px] font-inter600 text-xs bg-white px-5 py-3 mb-9 rounded-full uppercase shadow-sm">
                    Vergleich
                </div>
                <h2 class="text-5xl sm:text-7xl font-gilroybold leading-[102%] tracking-[-1.5px] mb-6 inline-block p-1 text-[#333333]">
                    Ordio vs. {Competitor}
                    <br><span class="block sm:inline text-2xl sm:text-4xl font-inter500 font-normal align-middle">Funktionsvergleich im Überblick</span>
                </h2>
            </div>
        </div>
    </div>

    <!-- OMR-Style Comparison Grid -->
    <div class="max-w-7xl mx-auto mt-8 mb-16 px-4">
        <div class="comparison-grid" x-data="{ ordioDetailsHeight: 0 }" @height-changed="ordioDetailsHeight = $event.detail.height">
            <!-- Ordio Column -->
            <div class="bg-white rounded-2xl shadow-lg border border-gray-100 overflow-hidden ordio-card comparison-card">
                <div class="bg-ordio-blue px-8 py-6">
                    <!-- Ordio header with logo and rating -->
                </div>
                <div class="p-8">
                    <div class="space-y-6">
                        <?php include '../components/ordio_comparison_content.php'; ?>
                        <!-- Star Rating Distribution -->
                        <!-- Ratings Section -->
                        <!-- Pricing Section -->
                        <!-- CTA Buttons -->
                    </div>
                </div>
            </div>
            <!-- Competitor Column -->
            <div class="bg-white rounded-2xl shadow-lg border border-gray-100 overflow-hidden personio-card comparison-card">
                <!-- Competitor content structure varies by template -->
            </div>
        </div>
    </div>
</section>
```

**Key Elements:**

- **Ordio Column:** Uses `ordio-card` class, includes `ordio_comparison_content.php`
- **Competitor Column:** Uses `personio-card` class (legacy naming), contains competitor-specific content
- **Height Synchronization:** Uses Alpine.js `x-data` and `@height-changed` event to sync column heights

### Competitor Column Structure Differences

**Details Template (`compare_template_details.php`):**
1. Product Description
2. **Expandable Details Section** (lines ~938-1030+):
   - Button: "{Competitor} Details"
   - Alpine.js `x-data="{ open: false }"` for expand/collapse
   - Features list ("Dazu zählen")
   - Integrations list ("Schnittstellen")
   - Special characteristics ("Das macht [Competitor] besonders")
   - Dispatches height changes for column synchronization
3. Star Rating Distribution
4. Ratings Section
5. Pricing Section

**No Details Template (`compare_template_nodetails.php`):**
1. Product Description
2. **Invisible Placeholder** (lines ~920-923):
   ```html
   <div class="hidden lg:block mb-6 transition-all duration-300 ease-in-out" 
        :style="{ height: ordioDetailsHeight + 'px' }">
       <!-- Invisible space that expands/collapses with Ordio Details -->
   </div>
   ```
   - Maintains height alignment with Ordio Details section
   - No competitor details shown
3. Star Rating Distribution
4. Ratings Section
5. Pricing Section

### Ordio Verteiler Section

**Structure:**

```php
<section id="section-3">
    <div class="relative w-full h-8 sm:h-24 bg-no-repeat bg-cover bg-[#fbfbfb]" style="background-image: url('data:image/svg+xml;utf8,...');">
    </div>

    <div class="bg-[#232529] text-center px-6 lg:px-8 pt-6 pb-24">
        <div class="max-w-4xl mx-auto">
            <div class="mx-auto w-[170px] font-inter600 text-xs bg-gray-100 px-5 py-3 mb-9 rounded-full uppercase">
                und vieles mehr…
            </div>
            <h2 class="text-5xl sm:text-7xl font-gilroybold leading-[102%] tracking-[-1.5px] text-white mb-6 p-1">
                Das macht Ordio besonders
            </h2>
        </div>

        <!-- Feature Cards Grid -->
        <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 max-w-7xl mx-auto mt-9 gap-9">
            <!-- 4 feature cards -->
        </div>

        <!-- Mobile Carousel -->
        <div x-data="{ activeSlide: 1, slides: 4 }" class="sm:hidden max-w-7xl mx-auto mt-3 overflow-hidden">
            <!-- Mobile slides -->
        </div>

        <!-- Testimonial -->
        <div class="mt-24 max-w-2xl mx-auto px-6 lg:px-8">
            <!-- Testimonial content -->
        </div>
    </div>
</section>
```

### In bester Gesellschaft Section

**Structure:**

```php
<section class="relative px-4">
    <div class="relative pt-16 pb-20 px-4 sm:px-6 lg:pt-24 lg:pb-28 lg:px-8">
        <div class="relative max-w-7xl mx-auto">
            <div class="sm:max-w-4xl mx-auto mb-16">
                <div class="mx-auto text-center w-[230px] font-inter600 text-xs bg-white px-5 py-3 mb-9 rounded-full uppercase shadow-sm">
                    Unendliche Möglichkeiten
                </div>
                <h2 class="text-center text-5xl sm:text-7xl font-gilroybold leading-[102%] tracking-[-1.5px] mb-6 inline-block p-1 text-[#333333]">
                    Ordio im Einsatz: Erfolgreiche Unternehmen, die gewechselt haben
                </h2>
                <!-- CTA Buttons -->
                <?php
                $ctaPositionLeft = 'false';
                $ctaButtonsAOS = 'false';
                $ctaButtonsLight = 'yes';
                $showCallbackButton = 'yes';
                include '../base/include_ctabuttons.php';
                ?>
            </div>

            <!-- Customer Stories Grid -->
            <div class="mt-12 max-w-lg mx-auto grid gap-5 lg:grid-cols-3 lg:max-w-none">
                <!-- 3 customer story cards -->
            </div>
        </div>
    </div>
</section>
```

### Comparison Carousel

**Include:**

```php
<?php include '../base/compare_carousel.php'; ?>
```

**Functionality:**

- Automatically filters out current competitor
- Displays other comparison pages in carousel
- Auto-rotates every 6 seconds
- Responsive: 4 cards desktop, 2 tablet, 1 mobile
- Uses Alpine.js for interactivity

### FAQs Section

**Structure:**

```php
<section class="py-12 sm:py-24 bg-[#fbfbfb] px-6" id="faq">
    <div class="max-w-5xl mx-auto">
        <h2 class="font-gilroybold text-4xl sm:text-5xl leading-[102%] tracking-[-1.5px] text-[#333333] mb-12 text-center">
            Häufige Fragen zu {Competitor} & [Category] Alternativen 2025
        </h2>

        <!-- FAQ Items -->
        <div class="mb-16">
            <div class="space-y-4">
                <details class="bg-white rounded-lg p-6 [&>summary::-webkit-details-marker]:hidden [&>summary::marker]:content-none group">
                    <summary class="font-inter600 text-lg cursor-pointer flex items-center justify-between hover:text-ordio-blue transition-colors duration-200">
                        <span>{Question}</span>
                        <svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
                        </svg>
                    </summary>
                    <div class="mt-4 text-gray-600 transition-all duration-300 ease-in-out">
                        <p class="mb-4">{Answer}</p>
                    </div>
                </details>
                <!-- More FAQ items -->
            </div>
        </div>
    </div>
</section>
```

### Footer Include

```php
<?php
$color_fill = '#fff';
$color_background = '#fbfbfb';
$rotate = '0';
$margin_bottom = 'mb-24';
include '../base/footer.php';
?>
```

### Lead Capture Popup

```php
<?php include '../components/lead-capture-popup.php'; ?>
```

## Component Dependencies

### ordio_comparison_content.php

**Location:** `v2/components/ordio_comparison_content.php`

**Purpose:** Renders dynamic Ordio content for comparison pages

**Data Source:** `v2/data/ordio_comparison_data.php`

**Structure:**

- Product Description
- Collapsible Details Section (Features, Target Audience, Pricing Info)
- Uses Alpine.js for accordion functionality
- Dispatches `height-changed` event for column synchronization

**Usage:**

```php
<?php include '../components/ordio_comparison_content.php'; ?>
```

### compare_carousel.php

**Location:** `v2/base/compare_carousel.php`

**Purpose:** Displays rotating carousel of other comparison pages

**Data Source:** `v2/data/tools_data.php`

**Functionality:**

- Filters out current competitor automatically
- Auto-rotates every 6 seconds
- Responsive breakpoints (4/2/1 cards)
- Navigation arrows and pagination dots
- Uses Alpine.js for state management

**Usage:**

```php
<?php include '../base/compare_carousel.php'; ?>
```

## Data File Structure

### tools_data.php

**Location:** `v2/data/tools_data.php`

**Structure:**

```php
$toolsData = [
    [
        'name' => 'Competitor Name',
        'slug' => 'competitor-slug',
        'description' => 'Short description',
        'logo' => 'competitor-logo.webp',
        'tags' => ['Tag1', 'Tag2', 'Tag3', 'Tag4', 'Tag5'],
        'filter_categories' => ['Category1', 'Category2']
    ],
    // More competitors...
];
```

**Required Fields:**

- `name`: Display name
- `slug`: URL slug (used for filtering and URLs)
- `description`: Short description (used in carousel)
- `logo`: Logo filename (without path)
- `tags`: Array of 4-5 tags for display
- `filter_categories`: Array for filtering functionality

### ordio_comparison_data.php

**Location:** `v2/data/ordio_comparison_data.php`

**Structure:**

```php
$ordio_data = [
    'description' => [
        'title' => 'Was ist Ordio?',
        'content' => '...'
    ],
    'details' => [
        'title' => 'Ordio Details',
        'sections' => [
            'features' => [
                'title' => '...',
                'description' => '...',
                'features' => ['Feature 1', 'Feature 2', ...]
            ],
            'target_audience' => [
                'title' => '...',
                'content' => '...'
            ],
            'pricing_info' => [
                'title' => '...',
                'content' => '...'
            ]
        ]
    ],
    'pricing' => [
        'title' => 'Preise',
        'plans' => [
            'starter' => [...],
            'plus' => [...],
            'pro' => [...]
        ]
    ]
];
```

## Schema Structure

### Complete Schema Graph

Comparison pages include multiple schema types in a `@graph` array:

1. **WebPage Schema**
2. **Article Schema**
3. **Table Schema** (comparison table)
4. **SoftwareApplication Schema** (competitor)
5. **BreadcrumbList Schema**
6. **FAQPage Schema**
7. **Product Schema** (Ordio)

See `docs/guides/COMPARISON_PAGES_ai/QUICK_REFERENCE.md` for complete schema templates.

## Image Requirements

### Logo Variants Required

**Regular Logos** (for carousel/cards):

- `{competitor}-logo-64w.webp`
- `{competitor}-logo-80w.webp`
- `{competitor}-logo-128w.webp`
- `{competitor}-logo-160w.webp`

**Comparison Logos** (for hero):

- `{competitor}-vergleich-logo-160w.webp`
- `{competitor}-vergleich-logo-320w.webp`

### Generation Script

```bash
node scripts/generate_responsive_logos.js
```

**Requirements:**

- Source images: `{competitor}-logo.webp` and `{competitor}-vergleich-logo.webp`
- Location: `v2/img/alternativen/`
- Format: WebP
- Script uses `sharp` for resizing and optimization

### Image Usage Patterns

**Hero Logo:**

```php
<img src="/v2/img/alternativen/{competitor}-vergleich-logo-160w.webp"
     srcset="/v2/img/alternativen/{competitor}-vergleich-logo-160w.webp 160w,
             /v2/img/alternativen/{competitor}-vergleich-logo-320w.webp 320w"
     sizes="(max-width: 640px) 160px, 160px"
     alt="{Competitor}"
     width="160"
     height="32"
     fetchpriority="high">
```

**Carousel Logo:**

```php
<img src="/v2/img/alternativen/{competitor}-logo-64w.webp"
     srcset="/v2/img/alternativen/{competitor}-logo-64w.webp 64w,
             /v2/img/alternativen/{competitor}-logo-128w.webp 128w"
     sizes="(max-width: 640px) 64px, 64px"
     alt="{Competitor} Logo"
     width="64"
     height="64"
     loading="lazy">
```

## Alpine.js Usage

### Height Synchronization

```php
<div class="comparison-grid" x-data="{ ordioDetailsHeight: 0 }" @height-changed="ordioDetailsHeight = $event.detail.height">
```

**Purpose:** Synchronizes column heights in comparison grid

**Implementation:** Components dispatch `height-changed` events, parent listens and adjusts

### Mobile Carousel

```php
<div x-data="{ activeSlide: 1, slides: 4 }" class="sm:hidden">
    <!-- Slides -->
    <div :style="'transform: translateX(-' + (100 * (activeSlide - 1)) + '%)'">
        <!-- Slide content -->
    </div>
    <!-- Navigation buttons -->
</div>
```

### FAQ Accordion

Uses native HTML `<details>` element with Alpine.js for enhanced styling and animations.

## CSS Classes Reference

### Comparison-Specific Classes

From `comparison-pages.css`:

- `.comparison-grid` - Main comparison grid container
- `.comparison-card` - Individual comparison card
- `.ordio-card` - Ordio column styling
- `.personio-card` - Competitor column styling (legacy naming)
- `.rating-bar-container` - Rating bar wrapper
- `.rating-bar-bg` - Rating bar background
- `.rating-bar-fill` - Rating bar fill
- `.star-svg` - Star icon (filled)
- `.checkmark-container` - Checkmark list container
- `.checkmark-icon` - Checkmark icon styling

### Utility Classes

- `.comparison-section` - Section wrapper
- `.rating-row` - Rating distribution row
- `.star-label` - Star rating label
- `.count-label` - Rating count label

## Performance Considerations

### Critical Rendering Path

1. **Preload LCP image** (competitor logo)
2. **Defer CSS** using `media="print"` trick
3. **Lazy load** below-fold images
4. **Optimize images** (WebP, responsive variants)

### Layout Stability

- **Explicit dimensions** on all images (prevents CLS)
- **Fixed heights** for carousel cards
- **Height synchronization** for comparison columns

### JavaScript Optimization

- **Alpine.js** loaded via CDN (deferred)
- **AOS animations** deferred with `requestIdleCallback`
- **Carousel auto-rotation** stops on user interaction

## Accessibility Features

- **Semantic HTML** (`<details>`, `<section>`, proper headings)
- **ARIA labels** on interactive elements
- **Keyboard navigation** support
- **Screen reader** friendly content
- **Touch targets** minimum 44x44px
- **Color contrast** meets WCAG AA standards

## Browser Support

- Modern browsers (Chrome, Firefox, Safari, Edge)
- Mobile browsers (iOS Safari, Chrome Mobile)
- Graceful degradation for older browsers
- Progressive enhancement approach
