Docs
Integration Examples

Integration Examples

Real-world examples and code samples for integrating with the Evon API.

This guide provides practical examples and integration patterns for common use cases with the Evon API.

Lead Capture Form Integration

HTML Form with JavaScript

Create a lead capture form that submits to the Evon API:

<!DOCTYPE html>
<html>
<head>
    <title>Lead Capture Form</title>
</head>
<body>
    <form id="leadForm">
        <div>
            <label for="firstName">First Name:</label>
            <input type="text" id="firstName" name="firstName" required>
        </div>
        <div>
            <label for="lastName">Last Name:</label>
            <input type="text" id="lastName" name="lastName" required>
        </div>
        <div>
            <label for="email">Email:</label>
            <input type="email" id="email" name="email" required>
        </div>
        <div>
            <label for="phone">Phone:</label>
            <input type="tel" id="phone" name="phone" required>
        </div>
        <button type="submit">Submit</button>
    </form>
 
    <script>
        const API_KEY = 'your_api_key_here';
        const API_BASE = 'https://dev.api.evoncrm.com';
 
        document.getElementById('leadForm').addEventListener('submit', async (e) => {
            e.preventDefault();
 
            const formData = new FormData(e.target);
            const leadData = {
                firstName: formData.get('firstName'),
                lastName: formData.get('lastName'),
                email: formData.get('email'),
                phone: formData.get('phone'),
                locale: 'EN_US'
            };
 
            try {
                const response = await fetch(`${API_BASE}/api/leads`, {
                    method: 'POST',
                    headers: {
                        'X-API-Key': API_KEY,
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(leadData)
                });
 
                const result = await response.json();
 
                if (response.ok) {
                    alert('Lead submitted successfully!');
                    e.target.reset();
                } else {
                    alert(`Error: ${result.error}`);
                }
            } catch (error) {
                alert('Network error. Please try again.');
            }
        });
    </script>
</body>
</html>

React Integration

React Hook for API Calls

import { useState, useCallback } from 'react';
 
const useEvonAPI = () => {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
 
  const API_KEY = process.env.REACT_APP_EVON_API_KEY;
  const API_BASE = 'https://dev.api.evoncrm.com';
 
  const makeRequest = useCallback(async (endpoint, options = {}) => {
    setLoading(true);
    setError(null);
 
    try {
      const response = await fetch(`${API_BASE}${endpoint}`, {
        ...options,
        headers: {
          'X-API-Key': API_KEY,
          'Content-Type': 'application/json',
          ...options.headers,
        },
      });
 
      const data = await response.json();
 
      if (!response.ok) {
        throw new Error(data.error || 'API request failed');
      }
 
      return data;
    } catch (err) {
      setError(err.message);
      throw err;
    } finally {
      setLoading(false);
    }
  }, [API_KEY]);
 
  const createLead = useCallback(async (leadData) => {
    return makeRequest('/api/leads', {
      method: 'POST',
      body: JSON.stringify(leadData),
    });
  }, [makeRequest]);
 
  const getOrganization = useCallback(async () => {
    return makeRequest('/organization');
  }, [makeRequest]);
 
  return {
    loading,
    error,
    createLead,
    getOrganization,
    makeRequest,
  };
};
 
// Usage in component
const LeadForm = () => {
  const { createLead, loading, error } = useEvonAPI();
  const [formData, setFormData] = useState({
    firstName: '',
    lastName: '',
    email: '',
    phone: '',
  });
 
  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const result = await createLead(formData);
      alert('Lead created successfully!');
      setFormData({ firstName: '', lastName: '', email: '', phone: '' });
    } catch (err) {
      // Error is handled by the hook
    }
  };
 
  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        placeholder="First Name"
        value={formData.firstName}
        onChange={(e) => setFormData({ ...formData, firstName: e.target.value })}
        required
      />
      <input
        type="text"
        placeholder="Last Name"
        value={formData.lastName}
        onChange={(e) => setFormData({ ...formData, lastName: e.target.value })}
        required
      />
      <input
        type="email"
        placeholder="Email"
        value={formData.email}
        onChange={(e) => setFormData({ ...formData, email: e.target.value })}
        required
      />
      <input
        type="tel"
        placeholder="Phone"
        value={formData.phone}
        onChange={(e) => setFormData({ ...formData, phone: e.target.value })}
        required
      />
      <button type="submit" disabled={loading}>
        {loading ? 'Submitting...' : 'Submit'}
      </button>
      {error && <div style={{ color: 'red' }}>{error}</div>}
    </form>
  );
};

WordPress Plugin Integration

PHP Integration for WordPress

<?php
/**
 * Evon API Integration for WordPress
 */
 
class EvonAPI {
    private $api_key;
    private $base_url = 'https://dev.api.evoncrm.com';
 
    public function __construct($api_key) {
        $this->api_key = $api_key;
    }
 
    private function make_request($endpoint, $method = 'GET', $data = null) {
        $url = $this->base_url . $endpoint;
 
        $args = [
            'method' => $method,
            'headers' => [
                'X-API-Key' => $this->api_key,
                'Content-Type' => 'application/json',
            ],
            'timeout' => 30,
        ];
 
        if ($data) {
            $args['body'] = json_encode($data);
        }
 
        $response = wp_remote_request($url, $args);
 
        if (is_wp_error($response)) {
            throw new Exception('Request failed: ' . $response->get_error_message());
        }
 
        $status_code = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
 
        if ($status_code !== 200 && $status_code !== 201) {
            throw new Exception($data['error'] ?? 'API request failed');
        }
 
        return $data;
    }
 
    public function create_lead($lead_data) {
        return $this->make_request('/api/leads', 'POST', $lead_data);
    }
 
    public function get_organization() {
        return $this->make_request('/organization');
    }
}
 
// Hook into Contact Form 7 submission
add_action('wpcf7_mail_sent', 'evon_handle_contact_form_submission');
 
function evon_handle_contact_form_submission($contact_form) {
    $api_key = get_option('evon_api_key');
    if (!$api_key) return;
 
    $submission = WPCF7_Submission::get_instance();
    $posted_data = $submission->get_posted_data();
 
    $lead_data = [
        'firstName' => $posted_data['first-name'] ?? '',
        'lastName' => $posted_data['last-name'] ?? '',
        'email' => $posted_data['email'] ?? '',
        'phone' => $posted_data['phone'] ?? '',
        'locale' => 'EN_US'
    ];
 
    try {
        $evon_api = new EvonAPI($api_key);
        $result = $evon_api->create_lead($lead_data);
 
        // Log success
        error_log('Evon lead created: ' . json_encode($result));
    } catch (Exception $e) {
        // Log error
        error_log('Evon API error: ' . $e->getMessage());
    }
}
 
// Admin settings page
add_action('admin_menu', 'evon_admin_menu');
 
function evon_admin_menu() {
    add_options_page(
        'Evon API Settings',
        'Evon API',
        'manage_options',
        'evon-api-settings',
        'evon_settings_page'
    );
}
 
function evon_settings_page() {
    if (isset($_POST['evon_api_key'])) {
        update_option('evon_api_key', sanitize_text_field($_POST['evon_api_key']));
        echo '<div class="notice notice-success"><p>Settings saved!</p></div>';
    }
 
    $api_key = get_option('evon_api_key', '');
    ?>
    <div class="wrap">
        <h1>Evon API Settings</h1>
        <form method="post">
            <table class="form-table">
                <tr>
                    <th scope="row">API Key</th>
                    <td>
                        <input type="text" name="evon_api_key" value="<?php echo esc_attr($api_key); ?>" class="regular-text" />
                        <p class="description">Enter your Evon API key from the dashboard.</p>
                    </td>
                </tr>
            </table>
            <?php submit_button(); ?>
        </form>
    </div>
    <?php
}
?>

Advanced Form Tracking

Complete Form with Conversion Tracking

class EvonFormTracker {
    constructor(apiKey, options = {}) {
        this.apiKey = apiKey;
        this.baseUrl = options.baseUrl || 'https://dev.api.evoncrm.com';
        this.sessionId = null;
    }
 
    async createSession(formData = {}) {
        try {
            const response = await fetch(`${this.baseUrl}/api/forms/session`, {
                method: 'POST',
                headers: {
                    'X-API-Key': this.apiKey,
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    formTitle: formData.title || 'Lead Form',
                    formDescription: formData.description || 'Website lead capture',
                    locale: formData.locale || 'EN_US',
                    link: window.location.href
                })
            });
 
            const result = await response.json();
            if (response.ok) {
                this.sessionId = result.data.sessionId;
                return result;
            }
            throw new Error(result.error);
        } catch (error) {
            console.error('Failed to create form session:', error);
            throw error;
        }
    }
 
    async submitForm(formData, conversionData = {}) {
        if (!this.sessionId) {
            throw new Error('No active session. Call createSession() first.');
        }
 
        try {
            const payload = {
                sessionId: this.sessionId,
                data: formData,
                eventName: conversionData.eventName || 'form_submit',
                conversionValue: conversionData.value || 0,
                currency: conversionData.currency || 'USD',
                userAgent: navigator.userAgent,
                ipAddress: await this.getClientIP(),
                fbp: this.getFacebookPixel(),
                fbc: this.getFacebookClickId()
            };
 
            const response = await fetch(`${this.baseUrl}/api/forms/data`, {
                method: 'POST',
                headers: {
                    'X-API-Key': this.apiKey,
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(payload)
            });
 
            const result = await response.json();
            if (response.ok) {
                return result;
            }
            throw new Error(result.error);
        } catch (error) {
            console.error('Failed to submit form:', error);
            throw error;
        }
    }
 
    async getClientIP() {
        try {
            const response = await fetch('https://api.ipify.org?format=json');
            const data = await response.json();
            return data.ip;
        } catch {
            return null;
        }
    }
 
    getFacebookPixel() {
        // Extract Facebook browser pixel from cookie
        const match = document.cookie.match(/_fbp=([^;]+)/);
        return match ? match[1] : null;
    }
 
    getFacebookClickId() {
        // Extract Facebook click ID from URL or cookie
        const urlParams = new URLSearchParams(window.location.search);
        const fbc = urlParams.get('fbclid');
        return fbc ? `fb.1.${Date.now()}.${fbc}` : null;
    }
}
 
// Usage example
const formTracker = new EvonFormTracker('your_api_key_here');
 
document.getElementById('leadForm').addEventListener('submit', async (e) => {
    e.preventDefault();
 
    try {
        // Create session if not exists
        if (!formTracker.sessionId) {
            await formTracker.createSession({
                title: 'Product Interest Form',
                description: 'Customer showing interest in our products'
            });
        }
 
        // Collect form data
        const formData = new FormData(e.target);
        const leadData = {
            firstName: formData.get('firstName'),
            lastName: formData.get('lastName'),
            email: formData.get('email'),
            phone: formData.get('phone'),
            product: formData.get('product')
        };
 
        // Submit with conversion tracking
        const result = await formTracker.submitForm(leadData, {
            eventName: 'lead_generation',
            value: 50.00, // Lead value
            currency: 'USD'
        });
 
        // Show success message
        alert('Thank you! Your information has been submitted.');
        e.target.reset();
 
        // Track in Google Analytics if available
        if (typeof gtag !== 'undefined') {
            gtag('event', 'form_submit', {
                event_category: 'engagement',
                event_label: 'lead_form'
            });
        }
 
    } catch (error) {
        alert('There was an error submitting your information. Please try again.');
        console.error('Form submission error:', error);
    }
});

Error Handling Best Practices

Robust Error Handling

class EvonAPIClient {
    constructor(apiKey, options = {}) {
        this.apiKey = apiKey;
        this.baseUrl = options.baseUrl || 'https://dev.api.evoncrm.com';
        this.retryAttempts = options.retryAttempts || 3;
        this.retryDelay = options.retryDelay || 1000;
    }
 
    async request(endpoint, options = {}) {
        const url = `${this.baseUrl}${endpoint}`;
        const config = {
            ...options,
            headers: {
                'X-API-Key': this.apiKey,
                'Content-Type': 'application/json',
                ...options.headers,
            },
        };
 
        for (let attempt = 1; attempt <= this.retryAttempts; attempt++) {
            try {
                const response = await fetch(url, config);
                const data = await response.json();
 
                if (response.ok) {
                    return data;
                }
 
                // Handle specific error cases
                switch (response.status) {
                    case 400:
                        throw new ValidationError(data.error, data.details);
                    case 401:
                        throw new AuthenticationError(data.error);
                    case 403:
                        throw new AuthorizationError(data.error);
                    case 404:
                        throw new NotFoundError(data.error);
                    case 409:
                        throw new ConflictError(data.error);
                    case 429:
                        // Rate limit - wait before retry
                        if (attempt < this.retryAttempts) {
                            const resetTime = response.headers.get('X-RateLimit-Reset');
                            const waitTime = resetTime ?
                                (resetTime * 1000) - Date.now() :
                                this.retryDelay * attempt;
                            await this.sleep(waitTime);
                            continue;
                        }
                        throw new RateLimitError(data.error);
                    case 500:
                        // Server error - retry with exponential backoff
                        if (attempt < this.retryAttempts) {
                            await this.sleep(this.retryDelay * Math.pow(2, attempt - 1));
                            continue;
                        }
                        throw new ServerError(data.error);
                    default:
                        throw new APIError(`HTTP ${response.status}: ${data.error}`);
                }
            } catch (error) {
                if (error instanceof TypeError && error.message.includes('fetch')) {
                    // Network error
                    if (attempt < this.retryAttempts) {
                        await this.sleep(this.retryDelay * attempt);
                        continue;
                    }
                    throw new NetworkError('Network connection failed');
                }
 
                if (attempt === this.retryAttempts) {
                    throw error;
                }
            }
        }
    }
 
    sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
}
 
// Custom error classes
class APIError extends Error {
    constructor(message) {
        super(message);
        this.name = 'APIError';
    }
}
 
class ValidationError extends APIError {
    constructor(message, details) {
        super(message);
        this.name = 'ValidationError';
        this.details = details;
    }
}
 
class AuthenticationError extends APIError {
    constructor(message) {
        super(message);
        this.name = 'AuthenticationError';
    }
}
 
class AuthorizationError extends APIError {
    constructor(message) {
        super(message);
        this.name = 'AuthorizationError';
    }
}
 
class NotFoundError extends APIError {
    constructor(message) {
        super(message);
        this.name = 'NotFoundError';
    }
}
 
class ConflictError extends APIError {
    constructor(message) {
        super(message);
        this.name = 'ConflictError';
    }
}
 
class RateLimitError extends APIError {
    constructor(message) {
        super(message);
        this.name = 'RateLimitError';
    }
}
 
class ServerError extends APIError {
    constructor(message) {
        super(message);
        this.name = 'ServerError';
    }
}
 
class NetworkError extends APIError {
    constructor(message) {
        super(message);
        this.name = 'NetworkError';
    }
}

Testing Your Integration

Unit Tests with Jest

// evon-api.test.js
import { EvonAPI } from './evon-api';
 
// Mock fetch
global.fetch = jest.fn();
 
describe('EvonAPI', () => {
    let api;
 
    beforeEach(() => {
        api = new EvonAPI('test-api-key');
        fetch.mockClear();
    });
 
    test('should create lead successfully', async () => {
        const mockResponse = {
            success: true,
            data: {
                id: 'lead-123',
                firstName: 'John',
                lastName: 'Doe',
                email: 'john@example.com'
            }
        };
 
        fetch.mockResolvedValueOnce({
            ok: true,
            json: async () => mockResponse
        });
 
        const leadData = {
            firstName: 'John',
            lastName: 'Doe',
            email: 'john@example.com',
            phone: '+1-555-123-4567'
        };
 
        const result = await api.createLead(leadData);
 
        expect(fetch).toHaveBeenCalledWith(
            'https://dev.api.evoncrm.com/api/leads',
            expect.objectContaining({
                method: 'POST',
                headers: expect.objectContaining({
                    'X-API-Key': 'test-api-key',
                    'Content-Type': 'application/json'
                }),
                body: JSON.stringify(leadData)
            })
        );
 
        expect(result).toEqual(mockResponse);
    });
 
    test('should handle validation errors', async () => {
        const mockError = {
            error: 'Datos inválidos',
            details: [
                {
                    path: ['email'],
                    message: 'Email inválido'
                }
            ]
        };
 
        fetch.mockResolvedValueOnce({
            ok: false,
            status: 400,
            json: async () => mockError
        });
 
        const invalidLeadData = {
            firstName: 'John',
            lastName: 'Doe',
            email: 'invalid-email',
            phone: '+1-555-123-4567'
        };
 
        await expect(api.createLead(invalidLeadData))
            .rejects
            .toThrow('Datos inválidos');
    });
});

These examples provide a solid foundation for integrating the Evon API into various applications and platforms. Remember to always handle errors gracefully, implement proper retry logic, and follow security best practices when storing API keys.