v1.0.0

Addons

The Clientra CRM addon system allows extending core functionality with optional modules. Addons are installed as self-contained packages in the /public/addons/ directory and loaded dynamically after the main application initializes.

Addon Architecture

Directory Structure

public/addons/ ├── meta-ads/ ← Addon directory (slug) │ ├── addon.json ← Metadata and configuration │ ├── addon.js ← Main JavaScript entry point │ ├── addon.php ← PHP API handler (optional) │ └── assets/ ← Addon-specific assets ├── wasabi-storage/ │ ├── addon.json │ └── addon.js └── api-webhooks/ ├── addon.json └── addon.js

addon.json Schema

json
{
  "slug":        "meta-ads",
  "name":        "Meta Ads Integration",
  "version":     "1.2.0",
  "description": "Facebook and Instagram lead ads integration",
  "author":      "Clientra",
  "requires":    "1.0.0",
  "permissions": ["admin"],
  "sidebar": {
    "label":  "Meta Ads",
    "icon":   "📱",
    "route":  "meta-ads",
    "section": "Integrations"
  },
  "database_tables": [
    "meta_accounts",
    "meta_form_mappings",
    "meta_lead_queue",
    "meta_settings",
    "meta_webhook_logs"
  ]
}

Loading Mechanism

Addons are loaded after the main application initializes:

  1. On startup, app.js calls api.listAddons() to get enabled addons
  2. For each enabled addon, a <script> tag is injected loading /addons/{slug}/addon.js
  3. The addon's addon.js registers itself with the app, adds sidebar links, and registers routes
  4. Database tables are created/migrated on first activation via the Addons admin page

Meta Ads Integration

Slug: meta-ads  |  Page: MetaAds.js

Integrates with Facebook and Instagram Lead Ads to automatically import leads into the CRM. Uses the Meta Webhooks API to receive real-time lead notifications.

Features

  • Multiple Meta ad account management
  • Per-form field mapping (Meta lead fields → CRM lead fields)
  • Real-time webhook listener for new leads
  • Lead queue with manual or automatic processing
  • Campaign attribution preserved on imported leads
  • Webhook event log for debugging
  • Per-account enable/disable toggle
  • Lead source statistics by campaign and date

Setup Guide

Create a Meta App

Go to developers.facebook.com, create a new app of type "Business", and add the "Lead Ads Retrieval" product.

Get API Credentials

From your Meta App dashboard, copy the App ID and App Secret. Generate a Page Access Token for the Facebook Page connected to your lead ads.

Configure in Clientra

Navigate to Meta Ads → Settings and enter your App ID, App Secret, and Page Access Token. Set the Webhook Verify Token to a secure random string.

text
Webhook URL: https://yourdomain.com/webhooks/meta-leads.php
Verify Token: (your random string from Meta Ads settings)
Configure Webhook in Meta

In your Meta App, go to Webhooks, subscribe to leadgen events on your Page. Enter the Webhook URL and Verify Token from the previous step.

Map Lead Form Fields

In Meta Ads → Form Mappings, map each Meta lead form's fields to the corresponding CRM lead fields (name, phone, email, etc.).

Lead Queue Processing

Incoming Meta leads are stored in the meta_lead_queue table. They can be processed:

  • Manually: Review leads in the Meta Ads page and click "Process Queue"
  • Automatically: Set up a cron job to call ?action=meta_process_queue periodically
bash
# Process Meta lead queue every 5 minutes via cron
*/5 * * * * curl -s -b "clientra_session=SESSION_TOKEN" \
  "https://yourdomain.com/api.php?action=meta_process_queue" \
  -X POST > /dev/null 2>&1

Wasabi Cloud Storage

Slug: wasabi-storage  |  Page: StorageManager.js

Replaces local file storage with Wasabi S3-compatible cloud storage. Provides a file management interface and migration tool for moving existing uploads to the cloud.

Features

  • S3-compatible API (Wasabi, AWS S3, Cloudflare R2)
  • Transparent file upload redirect (no code changes needed in pages)
  • Browser-based file manager with folder view
  • One-click migration from local storage to Wasabi
  • Storage usage statistics
  • Per-bucket access control

Setup Guide

Create a Wasabi Account and Bucket

Sign up at wasabi.com, create a storage bucket, and generate an Access Key and Secret Key with appropriate permissions.

Configure Storage Settings

In Settings → Storage, change "Storage Type" to wasabi and enter your credentials.

SettingExample
Storage Typewasabi
Wasabi Bucketclientra-uploads
Wasabi Regionus-east-1
Access Keyyour_access_key
Secret Keyyour_secret_key
Endpointhttps://s3.wasabisys.com
Test Connection

Use the "Test Connection" button in Settings to verify your credentials work. A successful test confirms the CRM can upload and retrieve files.

Migrate Existing Files (Optional)

In the Storage Manager page, use the "Migrate to Wasabi" tool to upload all existing local files to your bucket. This preserves all file paths and updates database references.

API & Webhooks Addon

Slug: api-webhooks

Provides REST API access with API key authentication and outbound webhook subscriptions. Designed for third-party integrations.

Features

  • API key management (create, revoke, usage limits)
  • OAuth 2.0 client registration for trusted applications
  • Rate limiting tiers (requests per minute)
  • Outbound webhook subscriptions per event type
  • API request logging with response codes

Rate Limiting Tiers

TierRequests/minDescription
Free30Basic read access
Standard120Full CRUD access
Premium600High-volume integrations

Webhook Events

EventTrigger
lead.createdNew lead added to CRM
lead.updatedLead status or details changed
deal.wonDeal moved to Won stage
deal.lostDeal moved to Lost stage
property.createdNew property listed
contact.createdNew contact added

Creating Custom Addons

You can create custom addons to extend Clientra CRM with your own features. Here's the minimal structure needed:

Minimum File Structure

public/addons/my-addon/ ├── addon.json ← Required: metadata ├── addon.js ← Required: JS entry point └── addon.php ← Optional: PHP API endpoints

addon.js Structure

javascript
// public/addons/my-addon/addon.js
(function() {
  // 1. Define your page class
  class MyAddonPage {
    render() {
      return `
        <div class="page">
          <div class="page-header">
            <div>
              <h1 class="page-title">My Addon</h1>
            </div>
          </div>
          <div class="card">
            <p>My addon content here</p>
          </div>
        </div>
      `;
    }

    init() {
      // Called when the page is navigated to
    }
  }

  // 2. Register with the app
  if (window.app) {
    // Add sidebar link
    window.app.addSidebarLink({
      label: 'My Addon',
      icon:  '🔌',
      route: 'my-addon',
      section: 'Addons'
    });

    // Register page route
    window.router.addRoute('my-addon', () => {
      const page = new MyAddonPage();
      document.getElementById('app').innerHTML = page.render();
      page.init();
    });
  }
})();

Adding PHP API Endpoints

php
<?php
// public/addons/my-addon/addon.php
// Handles: /api.php?action=my_addon_action

// api.php discovers and includes addon PHP files
// Your action is dispatched from the main switch statement

case 'my_addon_data':
    // Authenticate (always check session)
    if (!$_SESSION['user_id']) {
        http_response_code(401);
        exit(json_encode(['success' => false]));
    }

    // Query your addon's tables
    $stmt = $pdo->prepare("SELECT * FROM my_addon_data WHERE user_id = ?");
    $stmt->execute([$_SESSION['user_id']]);

    echo json_encode([
        'success' => true,
        'data'    => $stmt->fetchAll()
    ]);
    break;
ℹ Installing an Addon
Upload the addon folder to /public/addons/{slug}/, then go to the Addons page in Clientra CRM and click "Activate". The system will run any database migrations and enable the addon.