# ShiftOps User Flow

**Last Updated:** 2026-01-09

Complete documentation of the ShiftOps user journey from search to report unlock and PDF export.

## User Flow Overview

```mermaid
flowchart TD
    Start([User visits /shiftops]) --> Search[Search Page Loads]
    Search --> Type[User types business name]
    Type --> Autocomplete[Google Places autocomplete shows suggestions]
    Autocomplete --> Select[User selects business]
    Select --> Validate{Validate Business}
    Validate -->|Invalid| Error[Show error message]
    Validate -->|Valid| Essential[Fetch Essential Data API]
    Error --> Type
    Essential --> Chat[Display Chat-Style Loading]
    Chat --> Location[Location Analysis Card]
    Location --> Online[Online Presence Card]
    Online --> Industry[Industry Insights Card]
    Industry --> Operational[Operational Insights Card]
    Operational --> Score[Score Preview Card]
    Score --> Redirect[Auto-Redirect Countdown 6s]
    Redirect --> Report[Report Page Loads]
    Report --> Check{Report Unlocked?}
    Check -->|No| Gate[Show Email Gate Overlay]
    Check -->|Yes| Display[Display Full Report]
    Gate --> Submit[User submits email]
    Submit --> HubSpot[Submit to HubSpot]
    HubSpot --> Unlock[Unlock Report]
    Unlock --> Display
    Display --> Enhanced[Background: Fetch Enhanced Data]
    Enhanced --> Update[Update UI with Enhanced Data]
    Display --> PDF[User clicks PDF Export]
    PDF --> Generate[Generate PDF]
    Display --> NPS[Show NPS Survey]
    NPS --> SubmitNPS[User submits NPS]
    SubmitNPS --> Complete([Flow Complete])
```

## Data Flow Diagram

```mermaid
flowchart LR
    User[User Input] --> Google[Google Places API]
    Google --> Frontend[Frontend shiftops.php]
    Frontend --> API[POST /v2/api/shiftops.php]
    API --> Cache{Cache Check}
    Cache -->|Hit| Return[Return Cached]
    Cache -->|Miss| Customer{Customer Match}
    Customer --> Scores[Calculate Scores]
    Scores --> Team[Estimate Team Size]
    Team --> Cost[Calculate Cost Savings]
    Cost --> Recs[Generate Recommendations]
    Recs --> Context[Get Context Data]
    Context --> Store[Store in Cache]
    Store --> Return
    Return --> Frontend
    Frontend --> Storage[localStorage: shiftops_report_data]
    Storage --> Redirect[Redirect to /shiftops-report]
    Redirect --> Report[Report Page Loads]
    Report --> Load[Load from localStorage]
    Load --> Render[Progressive Rendering]
    Render --> Gate{Email Gate?}
    Gate -->|Yes| Email[Email Form]
    Gate -->|No| Display[Display Report]
    Email --> HubSpot[Submit to HubSpot]
    HubSpot --> Display
    Display --> Enhanced[Background: Enhanced Data]
    Enhanced --> Update[Update UI]
```

## Phase 1: Search Page (`shiftops.php`)

### Initial Load

**Timing:** 0s

- Page loads with hero section, headline, rotating subheadline, and search input visible
- No default values or pre-filled content
- Google Places autocomplete ready for input
- Rotating subheadline cycles through 4 benefit messages every 3 seconds

**Code Location:** `v2/pages/shiftops.php` lines 1557-1562 (rotating text), lines 2076-2095 (rotation logic)

### Search Flow

**Timing:** User-initiated

1. **User Types Business Name** (0s)
   - Google Places autocomplete initialized with DACH region focus (Germany, Austria, Switzerland)
   - Autocomplete configured for `establishment` types only
   - Fields requested: place_id, name, formatted_address, address_components, geometry, types, website, opening_hours, photos, rating, user_ratings_total, formatted_phone_number, business_status, reviews, price_level, url, utc_offset_minutes, vicinity
   - Language set to German (`language: 'de'`)

2. **Autocomplete Shows Suggestions** (0.5-1s)
   - Dropdown appears below search input
   - Shows business name, address, and "powered by Google" attribution
   - User can navigate with keyboard or mouse

3. **User Selects Business** (1-2s)
   - `handlePlaceSelection(place)` function called
   - Business validation performed:
     - Checks for name and formatted_address
     - Checks business_status (must be OPERATIONAL)
     - Validates business types (prefers shift-based businesses)
   - If invalid: Error message displayed, user can retry
   - If valid: Analysis starts automatically

**Code Location:** `v2/pages/shiftops.php` lines 2106-2276 (autocomplete initialization and validation)

## Phase 2: Chat-Style Loading Screen

### Analysis Sequence

**Total Duration:** ~18 seconds (with delays for UX)

The chat-style interface displays progressive analysis results as they become available:

#### Step 1: User Query (0s)

- User message bubble appears: "Analysiere {business_name}"
- Generated from business name initials (e.g., "SN" for "Sushi Ninja")

**Code Location:** `v2/pages/shiftops.php` lines 2426-2429

#### Step 2: Location Analysis (1.5s)

- Thinking bubble appears with animated dots
- After 2s delay, updates to show:
  - Title: "📍 Standort & Wettbewerb"
  - Content: Address, competitor density, location score, embedded Google Map
- Content generated by `generateLocationContent(place, analysisData)`

**Code Location:** `v2/pages/shiftops.php` lines 2433-2440

#### Step 3: Online Presence (5.0s)

- Thinking bubble appears
- After 2s delay, updates to show:
  - Title: "🌟 Online-Präsenz"
  - Content: Rating, review count, website status, photo gallery (6 images)
- Content generated by `generateOnlinePresenceContent(place, analysisData)`

**Code Location:** `v2/pages/shiftops.php` lines 2443-2450

#### Step 4: Industry Insights (8.5s)

- Thinking bubble appears
- After 2s delay, updates to show:
  - Title: "💡 Branchen-Einblicke"
  - Content: Estimated team size, monthly labor costs, opening hours, peak times, optimization potential
- Content generated by `generateIndustryInsights(place, analysisData)`
- Data type: `industry-insights` (can be updated with enhanced data)

**Code Location:** `v2/pages/shiftops.php` lines 2453-2461

#### Step 5: Operational Insights (12.0s)

- Thinking bubble appears
- After 2s delay, updates to show:
  - Title: "⚡ Operative Erkenntnisse"
  - Content: Upcoming holidays, weather forecast, seasonal trends, recommendations
- Content generated by `generateOperationalInsights(place, analysisData)`
- Data type: `operational-insights` (can be updated with enhanced data)

**Code Location:** `v2/pages/shiftops.php` lines 2464-2472

#### Step 6: Score Preview (15.5s)

- Thinking bubble appears
- After 2s delay, updates to show:
  - Title: "📊 Deine Analyse"
  - Content: ShiftOps score (circular progress), pillar scores (horizontal bars), cost savings, grade, recommendations teaser
- Content generated by `generateScorePreviewContent(place, analysisData)`
- Data type: `score-preview`
- Animations initialized: Progress bars animate, score numbers count up

**Code Location:** `v2/pages/shiftops.php` lines 2475-2483, lines 3537-3560 (score animations)

#### Step 7: Auto-Redirect Countdown (18.0s)

- Redirect indicator appears with spinner
- Rotating messages displayed every 1 second:
  - "Analysiere deine Betriebsdaten..."
  - "Berechne individuelle Einsparpotenziale..."
  - "Generiere maßgeschneiderte Empfehlungen..."
  - "Erstelle detaillierte Benchmarks..."
  - "Formuliere Quick-Win-Strategien..."
  - "Finalisiere deinen Report..."
- After 6 seconds total (24s from start), redirects to `/shiftops-report`

**Code Location:** `v2/pages/shiftops.php` lines 4285-4329

### Data Fetching During Loading

**Essential Mode API Call** (Blocking, < 2s target):

- POST to `/v2/api/shiftops.php` with `mode='essential'`
- Includes all Google Places data
- Returns: Business info, ShiftOps score, cost savings, location analysis, online presence, context data, recommendations, customer match info
- Stored in `window.shiftOpsAnalysis` and `localStorage['shiftops_report_data']`

**Enhanced Mode API Call** (Background, non-blocking, 3-5s target):

- POST to `/v2/api/shiftops.php` with `mode='enhanced'` (or no mode parameter)
- Fetches in background while chat sequence displays
- Returns: Enhanced analysis with website performance, competitor analysis, full weather forecast
- Stored in `window.shiftOpsAnalysisEnhanced` and `localStorage['shiftops_enhanced_data']`
- Updates chat sections when available via `updateChatWithEnhancedData()`

**Code Location:** `v2/pages/shiftops.php` lines 2339-2380 (data fetching), lines 4732-4877 (API functions)

## Phase 3: Report Page (`shiftops-report.php`)

### Page Load

**Timing:** Immediate after redirect

1. **Data Loading from localStorage**
   - Primary: `shiftops_report_data` (essential analysis)
   - Enhanced: `shiftops_enhanced_data` (if available)
   - Fallback: `shiftops_analysis_data` (legacy support)
   - Unlock status: `shiftops_report_unlocked` (boolean)

2. **Data Validation**
   - Checks for required fields: `business_info`, `shiftops_score`
   - Validates score structure (total_score, pillar_scores, grade)
   - Checks if data needs refresh or recalculation
   - If invalid/missing: Redirects back to `/shiftops`

**Code Location:** `v2/pages/shiftops-report.php` lines 5237-5583 (data loading and validation)

### Progressive Rendering

**Phase 1: Priority Sections** (Immediate)

- Hero section with ShiftOps score (circular progress indicator)
- Pillar scores (horizontal progress bars)
- Cost savings cards (monthly/annual savings, ROI)
- Business information header

**Phase 2: Secondary Sections** (100ms delay)

- Location analysis
- Online presence
- Recommendations (if available)
- Competitive positioning (if enhanced data available)

**Phase 3: Data-Dependent Sections** (Background)

- Weather forecast (7 days)
- Upcoming holidays
- Competitor analysis (if enhanced data available)
- Enhanced recommendations (if enhanced data available)

**Code Location:** `v2/pages/shiftops-report.php` lines 7914-8088 (progressive data loading)

### Email Gating Flow

**When Required:** Before viewing full report content

**Visual State:**
- Report content blurred (backdrop-filter: blur(3px))
- Blur overlay active (semi-transparent white)
- Unlock modal centered on screen

**Modal Content:**
- Title: "Dein Report ist bereit!"
- Description: "Gib deine E-Mail-Adresse ein, um den vollständigen Report zu sehen"
- Form fields:
  - Email (required, validated)
  - Name (optional)
  - Phone (optional)
- Submit button: "Report freischalten"
- Privacy note: "Wir schützen deine Daten. Keine Spam-Mails."

**Unlock Process:**

1. User enters email and submits form
2. Client-side validation: Email format check
3. POST to `/v2/api/shiftops-hubspot.php`
4. HubSpot form submission (Form ID: `41d07332-6697-4daa-b27e-dd60515f9c0f`)
5. On success:
   - `shiftops_report_unlocked` set to `'true'`
   - `shiftops_email` stored
   - `shiftops_unlock_timestamp` stored
   - Blur overlay removed
   - Modal hidden
   - Full report content visible
6. On error: Error message displayed, user can retry

**Code Location:** `v2/pages/shiftops-report.php` lines 6400-6572 (email gating logic)

### Enhanced Data Updates

**Background Loading** (During email gate or after unlock):

- If enhanced data not yet available, fetches in background
- Updates sections that benefit from enhanced data:
  - Recommendations (priority-ranked with ROI estimates)
  - Competitive analysis (competitor count, market position)
  - Weather insights (full 16-day forecast)
  - Holiday insights (upcoming holidays with impact)

**Code Location:** `v2/pages/shiftops-report.php` lines 6574-6652 (enhanced data loading)

## Phase 4: Report Interaction

### PDF Export

**Trigger:** Click "PDF herunterladen" button in report header

**Process:**
1. `generatePDF()` function called from `shiftops-pdf-generator.js`
2. Extracts all report data using `extractExportData(data)`
3. Determines which sections to include using `shouldIncludeSection()`
4. Converts HTML sections to images using html2canvas
5. Generates multi-page PDF using jsPDF
6. Includes Ordio branding and visual layout matching report design
7. File name: `shiftops-report-{business-name}-{timestamp}.pdf`
8. Downloads automatically

**Content Included:**
- Business information (name, address, website, rating, reviews)
- ShiftOps score (total score, pillar scores, grade)
- Cost savings breakdown (monthly/annual savings, ROI, breakdown by category)
- Location analysis (competitor density, urban/suburban classification)
- Online presence (rating, photos, reviews analysis)
- Opening hours analysis
- Photo gallery (if available)
- Google reviews (if available)
- Weather forecast (7 days)
- Upcoming holidays
- Competitive positioning (if enhanced mode data available)
- Recommendations (quick wins, high value, strategic)

**Code Location:** `v2/js/shiftops-pdf-generator.js` (complete file)

### NPS Survey

**Display:** After report unlock (one-time display)

**Trigger Conditions:**
- Report is unlocked
- `shiftops_nps_submitted` is not `'true'`
- `shiftops_nps_dismissed` is not `'true'`
- Survey card not already displayed

**Survey Content:**
- Question: "Wie wahrscheinlich ist es, dass du ShiftOps weiterempfehlen würdest?"
- Scale: 0-10 (0 = sehr unwahrscheinlich, 10 = sehr wahrscheinlich)
- Optional feedback text field
- Submit button: "Absenden"
- Dismiss button: "Später"

**Submission Process:**
1. User selects score (0-10 integer)
2. Optionally enters feedback text
3. Clicks "Absenden"
4. POST to `/v2/api/shiftops-nps.php`
5. Validates NPS score (must be 0-10 integer)
6. Calculates NPS category (Promoter 9-10, Passive 7-8, Detractor 0-6)
7. Submits to HubSpot form (Form ID: `804459f7-c18d-4da6-8a0b-a81f44bb8275`)
8. Logs rich NPS data to `logs/shiftops-nps.log`
9. Sets `shiftops_nps_submitted` to `'true'`
10. Survey card removed

**Code Location:** `v2/pages/shiftops-report.php` lines 12000+ (NPS survey display), `v2/api/shiftops-nps.php` (submission endpoint)

## Error Handling

### Search Page Errors

- **Invalid Business Selection:** Error message displayed, user can retry search
- **API Timeout:** Fallback data used, analysis continues with limited data
- **Network Failure:** Error message displayed, user can retry

### Report Page Errors

- **Missing Data:** Redirects to `/shiftops` to start new analysis
- **Corrupted localStorage:** Clears corrupted data, redirects to `/shiftops`
- **API Failure:** Uses fallback data, shows available sections only
- **Email Validation Error:** Inline error message, form remains visible
- **HubSpot Submission Failure:** Error message displayed, user can retry

## State Management

### localStorage Keys

**Primary Data:**
- `shiftops_report_data`: Complete essential analysis object (JSON string)
- `shiftops_enhanced_data`: Enhanced analysis object (JSON string, wrapped in object with timestamp)

**Status Keys:**
- `shiftops_report_unlocked`: Boolean flag ('true'/'false')
- `shiftops_email`: Email address used for unlock
- `shiftops_unlock_timestamp`: ISO timestamp of unlock
- `shiftops_nps_submitted`: Boolean flag ('true'/'false')
- `shiftops_nps_dismissed`: Boolean flag ('true'/'false')
- `ordio_original_referrer`: Original referrer before same-site redirect (for attribution)

**Legacy/Backup Keys:**
- `shiftops_data`: Old format (may exist in older sessions)
- `shiftops_analysis_data`: Fallback data structure

## Timing Summary

| Phase | Step | Timing | Duration |
|-------|------|--------|----------|
| Search | Page load | 0s | - |
| Search | User types | User-initiated | - |
| Search | Autocomplete | 0.5-1s | - |
| Search | Business selection | 1-2s | - |
| Loading | Essential API call | 0-2s | < 2s |
| Loading | User query bubble | 0s | - |
| Loading | Location analysis | 1.5s | 2s delay |
| Loading | Online presence | 5.0s | 2s delay |
| Loading | Industry insights | 8.5s | 2s delay |
| Loading | Operational insights | 12.0s | 2s delay |
| Loading | Score preview | 15.5s | 2s delay |
| Loading | Redirect countdown | 18.0s | 6s |
| Report | Page load | 24s | Immediate |
| Report | Progressive rendering | 24s | 100ms delay |
| Report | Email gate display | 24s | Immediate |
| Report | Enhanced data fetch | 24s+ | 3-5s (background) |
| Report | PDF export | User-initiated | 2-5s |
| Report | NPS survey | After unlock | User-initiated |

**Total Time to Report:** ~24 seconds (including chat sequence delays)

## Related Documentation

- [Technical Implementation](03-technical-implementation.md) - Code structure and functions
- [API Endpoints](05-api-endpoints.md) - API request/response formats
- [Scoring System](04-scoring-system.md) - Score calculation details
