# Event Form Production Fixes

**Last Updated:** 2026-01-28

## Overview

Comprehensive fixes for event lead capture form HubSpot submission issues in production, addressing CORB errors, header placement, response headers, and output buffering.

## Critical Fix: Header Placement

**Problem:** Headers were set BEFORE includes, causing "headers already sent" errors if any included file output anything (whitespace, BOM, errors).

**Solution:** Moved headers to AFTER includes, matching working APIs (`collect-lead.php`, `submit-template.php`).

**Pattern:**

```php
// ✅ CORRECT: Includes FIRST
require_once __DIR__ . '/../config/hubspot-config.php';
require_once __DIR__ . '/../config/hubspot-api-helpers.php';
require_once __DIR__ . '/../helpers/logger.php';

// THEN headers
header('Content-Type: application/json; charset=utf-8');
header('X-Content-Type-Options: nosniff');
header('Cache-Control: no-cache, must-revalidate');
```

## Critical Issues Fixed

### 1. Response Headers (FIXED)

**Problem:**

- Missing `charset=utf-8` in Content-Type header
- Missing `X-Content-Type-Options: nosniff` header
- Missing `Cache-Control` header
- **Impact:** CORB errors, JSON parsing issues

**Solution:**

- Added proper headers to all JSON responses
- Created `outputJsonResponse()` helper function for consistency
- All responses now include:
  - `Content-Type: application/json; charset=utf-8`
  - `X-Content-Type-Options: nosniff`
  - `Cache-Control: no-cache, must-revalidate`

**Files Modified:**

- `v2/api/event-lead-capture.php` - Added headers to all response points

### 2. Output Buffering (FIXED)

**Problem:**

- No output buffering cleanup
- Potential whitespace/errors before JSON
- **Impact:** Invalid JSON, CORB errors

**Solution:**

- Added `ob_start()` at beginning of file
- Added `ob_end_clean()` before all JSON outputs
- Ensures clean JSON output

**Files Modified:**

- `v2/api/event-lead-capture.php` - Added output buffering

### 3. Missing Directories (FIXED)

**Problem:**

- Logs directory doesn't exist (`logs_writable: false`)
- Lock directory doesn't exist (`lock_dir_writable: false`)
- **Impact:** Errors cannot be logged, file locking fails

**Solution:**

- Added defensive directory creation in API endpoint
- Creates directories with proper permissions (0755)
- Handles errors gracefully with fallback to error_log

**Files Modified:**

- `v2/api/event-lead-capture.php` - Added directory creation

### 4. Error Handling (FIXED)

**Problem:**

- No shutdown handler for fatal errors
- Fatal errors could return HTML instead of JSON
- **Impact:** API contract broken, frontend errors

**Solution:**

- Added shutdown handler for fatal errors
- Ensures JSON response even on fatal errors
- Improved exception handling

**Files Modified:**

- `v2/api/event-lead-capture.php` - Added shutdown handler

### 5. Frontend JSON Parsing (FIXED)

**Problem:**

- No error handling for malformed JSON
- Could fail silently on CORB errors
- **Impact:** Form shows success but data doesn't submit

**Solution:**

- Improved JSON parsing with try/catch
- Better error detection for CORB/CORS issues
- Enhanced error messages

**Files Modified:**

- `v2/js/event-form.js` - Improved JSON parsing

## Implementation Details

### Helper Function: `outputJsonResponse()`

**Location:** `v2/api/event-lead-capture.php`

**Purpose:** Ensures consistent, clean JSON responses with proper headers

**Usage:**

```php
outputJsonResponse([
    'success' => true,
    'message' => 'Success message',
    'data' => [...]
], 200);
```

**Implementation:**

```php
function outputJsonResponse($data, $httpCode = 200) {
    ob_end_clean();
    header('Content-Type: application/json; charset=utf-8');
    header('X-Content-Type-Options: nosniff');
    header('Cache-Control: no-cache, must-revalidate');
    http_response_code($httpCode);
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}
```

### Directory Creation

**Location:** `v2/api/event-lead-capture.php` (after includes)

**Implementation:**

```php
$logsDir = __DIR__ . '/../logs';
$locksDir = __DIR__ . '/../../writable/locks';

if (!is_dir($logsDir)) {
    @mkdir($logsDir, 0755, true);
    if (!is_dir($logsDir) || !is_writable($logsDir)) {
        error_log("Event Lead Capture: Warning - Logs directory not writable: $logsDir");
    }
}

if (!is_dir($locksDir)) {
    @mkdir($locksDir, 0755, true);
    if (!is_dir($locksDir) || !is_writable($locksDir)) {
        error_log("Event Lead Capture: Warning - Locks directory not writable: $locksDir");
    }
}
```

### Shutdown Handler

**Location:** `v2/api/event-lead-capture.php` (before JSON input)

**Purpose:** Catch fatal errors and return valid JSON

**Implementation:**

```php
register_shutdown_function(function() {
    $error = error_get_last();
    if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        while (ob_get_level() > 0) {
            ob_end_clean();
        }
        if (!headers_sent()) {
            header('Content-Type: application/json; charset=utf-8');
            header('X-Content-Type-Options: nosniff');
            header('Cache-Control: no-cache, must-revalidate');
            http_response_code(500);
        }
        // Log and return JSON error response
        echo json_encode([
            'success' => false,
            'message' => 'An internal error occurred.'
        ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        exit;
    }
});
```

## Testing

### Production Test Script

**File:** `v2/scripts/test-production-submission.php`

**Usage:**

```bash
php v2/scripts/test-production-submission.php https://www.ordio.com
```

**Tests:**

- Response headers (Content-Type, X-Content-Type-Options, Cache-Control)
- JSON validity
- Response structure
- CORB issues
- Error handling

### Browser Testing

1. **Open DevTools:**
   - Navigate to `/events/intergastra-2026-tablet`
   - Open DevTools → Network tab

2. **Submit Form:**
   - Fill form with test data
   - Submit form
   - Check Network tab for `/v2/api/event-lead-capture.php`

3. **Verify Headers:**
   - Click on request → Headers tab
   - Verify response headers:
     - `Content-Type: application/json; charset=utf-8`
     - `X-Content-Type-Options: nosniff`
     - `Cache-Control: no-cache, must-revalidate`

4. **Check Response:**
   - Click on request → Response tab
   - Verify JSON is valid
   - Check for `success: true` and `contactId`

5. **Check Console:**
   - Open Console tab
   - Look for CORB errors
   - Should see no CORB errors

### Diagnostics Endpoint

**URL:** `https://www.ordio.com/v2/api/event-lead-capture-diagnostics.php?password=elc-diagnostic-2026&test=true`

**Checks:**

- Configuration (API token, form GUID, portal ID)
- API connectivity
- Test submission
- Directory permissions

## Files Modified

**Core Files:**

- `v2/api/event-lead-capture.php` - All fixes applied
- `v2/js/event-form.js` - Improved JSON parsing

**New Files:**

- `v2/scripts/test-production-submission.php` - Production testing script

**Documentation:**

- `docs/systems/forms/EVENT_FORM_IMPLEMENTATION.md` - Added production troubleshooting
- `docs/systems/forms/EVENT_FORM_HUBSPOT_FIX_SUMMARY.md` - Updated with production fixes
- `docs/systems/forms/EVENT_FORM_PRODUCTION_FIXES.md` - This file
- `.cursor/rules/api-endpoints-core.mdc` - Added header requirements

## Deployment Checklist

Before deploying to production:

- [ ] Run production test script: `php v2/scripts/test-production-submission.php https://www.ordio.com`
- [ ] Verify directories exist: `ls -la v2/logs/` and `ls -la v2/writable/locks/`
- [ ] Test form submission in browser DevTools
- [ ] Verify response headers are correct
- [ ] Check for CORB errors in console
- [ ] Submit test form and verify in HubSpot
- [ ] Monitor logs: `tail -f v2/logs/event-lead-capture-$(date +%Y-%m-%d).log`

## Success Criteria

- [x] Response headers include charset, X-Content-Type-Options, Cache-Control
- [x] Output buffering cleanup before all JSON outputs
- [x] Directories created defensively
- [x] Shutdown handler for fatal errors
- [x] Frontend JSON parsing improved
- [x] Production test script created
- [x] Documentation updated
- [x] Cursor rules updated
- [ ] Browser testing completed (requires manual testing)
- [ ] HubSpot verification completed (requires manual testing)
- [ ] CORB errors verified resolved (requires browser testing)

## Related Documentation

- `docs/systems/forms/EVENT_FORM_IMPLEMENTATION.md` - Complete implementation guide
- `docs/systems/forms/EVENT_FORM_HUBSPOT_FIX_SUMMARY.md` - Initial fix summary
- `.cursor/rules/api-endpoints-core.mdc` - API endpoint patterns
