Skip to main content

Overview

The Adosa Real Estate website uses a PHP proxy to submit lead and contact forms to the eGO Real Estate API. This architecture solves CORS issues and provides a unified interface for form submissions.

Architecture

Browser (Form) → PHP Proxy → eGO API
                 (CORS Safe)  (AuthorizationToken)
The flow:
  1. User submits form on the website
  2. JavaScript calls /api/proxy.php with form data
  3. PHP proxy forwards request to eGO API with authentication
  4. PHP returns standardized JSON response
  5. JavaScript displays success/error message

LeadService Class

The LeadService class in src/services/api/leads.ts handles all lead and contact submissions.

Property Lead Submission

Used when a visitor inquires about a specific property:
LeadService.submitPropertyLead({
  name: "John Doe",
  email: "[email protected]",
  phone: "+34 600 123 456",
  property_id: "ADO1234",
  message: "I'm interested in this property"
});

Form Data Structure

name
string
required
Full name of the person submitting the lead
email
string
required
Email address for contact
phone
string
required
Phone number with international format recommended
property_id
string
required
Property reference ID from the eGO system (e.g., “ADO1234”)
message
string
Optional message from the visitor

Implementation

The method constructs URL parameters and sends to the proxy:
static async submitPropertyLead(lead: any) {
  const params = new URLSearchParams({
    NAM: lead.name,
    EML: lead.email,
    PHO: lead.phone,
    OBS: `REFERENCIA: ${lead.property_id}\n\n${lead.message || ''}`,
    RID: lead.property_id,
    CTY: "4" // 4 = wants to ask for more info (Lead)
  });

  const fetchUrl = `/api/proxy.php?type=Lead&${params.toString()}`;
  const response = await fetch(fetchUrl);
  const data = await response.json();
  
  return { 
    success: data.success, 
    message: "Request sent successfully" 
  };
}

eGO API Parameters

NAM
string
required
Name parameter for eGO API
EML
string
required
Email parameter for eGO API
PHO
string
required
Phone parameter for eGO API
OBS
string
Observations/message text. Includes property reference and user message
RID
string
required
Reference ID - the property ID being inquired about
CTY
string
required
Contact type: "4" = wants to ask for more info (Lead)

General Contact Submission

Used for general contact form (not tied to a specific property):
LeadService.submitGeneralContact({
  name: "Jane Smith",
  email: "[email protected]",
  phone: "+34 600 987 654",
  message: "I'd like to schedule a consultation"
});

Implementation

static async submitGeneralContact(contact: any) {
  const params = new URLSearchParams({
    NAM: contact.name,
    EML: contact.email,
    PHO: contact.phone,
    OBS: contact.message || '',
    CTY: "1", // 1 = looking to buy a property (Contact)
  });

  const fetchUrl = `/api/proxy.php?type=Contact&${params.toString()}`;
  const response = await fetch(fetchUrl);
  const data = await response.json();
  
  return { 
    success: data.success, 
    message: "Contact sent successfully" 
  };
}
Key difference: Contact endpoint uses CTY: "1" and does not require RID parameter.

PHP Proxy

The PHP proxy at public/api/proxy.php handles server-side API communication.

Configuration

$api_token = "u2fW9rOg0Oz5rPGVh+7wowfgDt4IiCugRCFDrohuR3vJzZIwRzFzgfdM3YDqDuN5";
$base_url = "https://websiteapi.egorealestate.com/v1";
The API token is hardcoded in the PHP file. In production, this should be moved to environment variables or a secure configuration file.

CORS Headers

The proxy sets permissive CORS headers:
header("Content-Type: application/json");
header("Access-Control-Allow-Origin: *");
This allows the frontend to make requests from any domain during development and production.

Request Flow

  1. Extract Parameters:
$type = isset($_GET['type']) ? $_GET['type'] : 'Properties';
$params = $_GET;
unset($params['type']); // Remove internal proxy parameter
  1. Build Target URL:
$endpoint = $type; // "Lead" or "Contact"
$query = http_build_query($params);
$url = $base_url . "/" . $endpoint . "?" . $query;
  1. Configure cURL:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // CDMON compatibility

$headers = [
    "AuthorizationToken: $api_token",
    "Accept: application/json",
    "User-Agent: AdosaRealEstate/1.0"
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  1. Execute and Return:
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// IIS Bypass: Always return 200 to client
http_response_code(200);

echo json_encode([
    "success" => ($http_code >= 200 && $http_code < 300),
    "ego_code" => $http_code,
    "ego_response" => json_decode($response) ?: $response,
    "curl_error" => $curl_err,
]);

IIS Bypass Strategy

The proxy always returns HTTP 200 to the client, even if the eGO API returns an error:
// IIS Bypass: Always return 200 so JS can read error body
http_response_code(200);
This solves an issue where IIS servers block error responses. The JavaScript checks the success field in the JSON response instead of the HTTP status code.

Response Structure

success
boolean
required
true if eGO API returned 2xx status code, false otherwise
ego_code
number
required
The actual HTTP status code from the eGO API
ego_response
object
required
Parsed JSON response from eGO API, or raw text if not JSON
curl_error
string
cURL error message if request failed at network level
debug_url
string
Full URL that was requested (for debugging)
debug_method
string
HTTP method used (always “GET” for eGO API)

Error Handling

Both submitPropertyLead() and submitGeneralContact() include try-catch error handling:
try {
  const response = await fetch(fetchUrl);
  const data = await response.json();

  if (!data.success) {
    console.error("❌ eGO Error:", data.ego_code, data.ego_response);
    throw new Error(`eGO Error: ${data.ego_code}`);
  }

  return { success: true, message: "Request sent successfully" };
} catch (error: any) {
  console.error("❌ Critical failure:", error);
  return { success: false, message: "Error sending request" };
}
Important: Methods return { success: false } instead of throwing errors, allowing the UI to display user-friendly error messages.

Contact Type Codes

The CTY parameter defines the type of contact:
CodeTypeDescription
"1"ContactGeneral inquiry - looking to buy a property
"4"LeadSpecific property inquiry - wants more info
These codes are defined by the eGO Real Estate API specification.

Frontend Integration

Example of using LeadService in an Astro component:
---
import { LeadService } from '../services/api/leads';
---

<form id="property-form">
  <input name="name" required />
  <input name="email" type="email" required />
  <input name="phone" required />
  <textarea name="message"></textarea>
  <input type="hidden" name="property_id" value={propertyId} />
  <button type="submit">Send</button>
</form>

<script>
  const form = document.getElementById('property-form');
  
  form.addEventListener('submit', async (e) => {
    e.preventDefault();
    const formData = new FormData(form);
    
    const result = await LeadService.submitPropertyLead({
      name: formData.get('name'),
      email: formData.get('email'),
      phone: formData.get('phone'),
      property_id: formData.get('property_id'),
      message: formData.get('message')
    });
    
    if (result.success) {
      alert('Thank you! We will contact you soon.');
      form.reset();
    } else {
      alert('Error sending form. Please try again.');
    }
  });
</script>

Security Considerations

  1. API Token Exposure: The PHP proxy keeps the API token server-side, preventing exposure in client-side code
  2. CORS Protection: While the proxy allows all origins (*), this is acceptable for public lead forms
  3. Rate Limiting: The eGO API may rate limit requests. Consider implementing client-side throttling for forms
  4. Input Validation: Always validate and sanitize user input before submission
  5. SSL/TLS: All requests use HTTPS to encrypt data in transit

Testing

Test lead submission with curl:
curl "https://yourdomain.com/api/proxy.php?type=Lead&NAM=Test&[email protected]&PHO=123456789&RID=ADO1234&CTY=4&OBS=Test%20message"
Expected response:
{
  "success": true,
  "ego_code": 200,
  "ego_response": { ... },
  "curl_error": ""
}

Build docs developers (and LLMs) love