Skip to content

Getting Started ​

Overview ​

FluentAffiliate is a self-hosted WordPress affiliate program management plugin by WPManageNinja (v1.6.0). It requires PHP 7.4+ and WordPress 5.0+. The plugin manages affiliates, tracks referrals, processes payouts, and integrates with e-commerce plugins through a two-class connector pattern.

All data is stored in custom database tables (prefixed fa_) rather than WordPress post types. There is no dependency on external SaaS services — the plugin runs entirely within your WordPress installation.

Architecture ​

Backend — MVC using the WPFluent framework (a custom Laravel-inspired framework). Entry point: fluent-affiliate.php → boot/app.php → Application instance.

LayerDescriptionLocation
RouterWPFluent Router over WP REST APIapp/Http/Routes/api.php
ControllersPHP classes returning arrays auto-serialized to JSONapp/Http/Controllers/
PoliciesRoute-level authorization (one per route group)app/Http/Policies/
ModelsEloquent-like ORM on custom fa_ tablesapp/Models/
ServicesBusiness logic (AffiliateService, PermissionManager, etc.)app/Services/
HooksWordPress action/filter registrations and handlersapp/Hooks/
IntegrationsE-commerce connectors (BaseConnector pattern)app/Modules/Integrations/

REST API — Registered at wp-json/fluent-affiliate/v2/ via app/Http/Routes/api.php on the rest_api_init hook.

Request Lifecycle ​

Frontend Admin SPA — Vue 3 + Element Plus, hash routing, served from resources/admin/. Compiled output in assets/admin/.

Affiliate Portal SPA — Separate Vue 3 application, served from resources/Customer/. Compiled output in assets/public/.

Background jobs — WooCommerce Action Scheduler (bundled). Hourly (fluent_affiliate_scheduled_hour_jobs) and daily (fluent_affiliate_scheduled_daily_jobs) jobs registered during plugin boot.

Authentication ​

All REST API endpoints require authentication. Use WordPress Application Passwords for external API clients.

  1. Go to WordPress Admin → Users → Profile.
  2. Scroll to the Application Passwords section.
  3. Enter a name for the application, then click Add New Application Password.
  4. Copy the generated password — it is only shown once.

Pass credentials as a Base64-encoded HTTP Basic Authorization header:

bash
# Base64-encode username:application_password
curl -H "Authorization: Basic $(echo -n 'admin:xxxx xxxx xxxx xxxx xxxx xxxx' | base64)" \
  https://yoursite.com/wp-json/fluent-affiliate/v2/affiliates

Nonce Authentication (browser / admin SPA) ​

From a browser context where the user is already logged in to WordPress, use the X-WP-Nonce header:

javascript
fetch('/wp-json/fluent-affiliate/v2/affiliates', {
    headers: { 'X-WP-Nonce': wpApiSettings.nonce }
})

The built-in admin SPA injects the nonce as window.fluentAffiliateAdmin.nonce and sends it automatically via the internal REST client (resources/admin/Bits/Rest.js).

Response Envelope ​

All API responses are JSON. Successful responses return HTTP 200 (or 201 for creates) with a plain JSON object whose keys depend on the endpoint:

json
// List response
{ "affiliates": [ { "id": 1, "user_id": 5, "status": "active", ... } ] }

// Single resource
{ "affiliate": { "id": 1, "user_id": 5, ... } }

// Paginated list
{
  "affiliates": [...],
  "total": 142,
  "per_page": 15,
  "current_page": 1,
  "last_page": 10
}

// Mutation success
{ "message": "Affiliate has been created", "affiliate": { ... } }

Error responses default to HTTP 422 (or another 4xx code) and always include a message key:

json
{ "message": "The selected group could not be found" }

There is no top-level data wrapper — the resource key (affiliates, referral, payout, etc.) is always at the root of the response object.

Authorization ​

Route groups use policy classes for authorization. Each policy implements verifyRequest() for baseline access and per-method checks for granular permissions.

PolicyRoute prefixWho can access
AffiliatePolicy/affiliatesUsers with read_all_affiliates or manage_all_affiliates
ReferralPolicy/referralsUsers with read_all_referrals or manage_all_referrals
PayoutPolicy/payoutsUsers with read_all_payouts or manage_all_payouts
VisitPolicy/visitsUsers with read_all_visits
AdminPolicy/settingsWordPress manage_options or manage_all_data
UserPolicy/portalAny authenticated WordPress user
ReportPolicy/reportsUsers holding at least one FluentAffiliate permission (PermissionManager::hasAnyPermission())

All permission checks delegate to FluentAffiliate\App\Services\PermissionManager. WordPress administrators (users with manage_options) always pass all policy checks.

Custom Permissions ​

FluentAffiliate defines 8 granular permissions that can be assigned to any WordPress user. They are stored in the plugin's own fa_meta table (object_type = 'user_meta', meta_key = '_fa_access_permissions') — not in WordPress user meta — and are independent of WordPress roles.

PermissionDescription
read_all_affiliatesView all affiliate records
manage_all_affiliatesCreate, update, delete affiliates
read_all_referralsView all referrals
manage_all_referralsCreate, update, delete referrals
read_all_visitsView visit/click records
read_all_payoutsView payout batches
manage_all_payoutsCreate and process payouts
manage_all_dataFull settings and data management access

Assign permissions programmatically:

php
use FluentAffiliate\App\Models\Meta;
use FluentAffiliate\App\Services\PermissionManager;

// setPermissions() validates the set and collapses redundant read/manage pairs
$permissions = PermissionManager::setPermissions([
    'read_all_affiliates',
    'read_all_referrals',
    'read_all_payouts',
]);

$meta = Meta::where('object_type', 'user_meta')
    ->where('object_id', $userId)
    ->where('meta_key', '_fa_access_permissions')
    ->first();

if ($meta) {
    $meta->value = $permissions;
    $meta->save();
} else {
    Meta::create([
        'object_type' => 'user_meta',
        'object_id'   => $userId,
        'meta_key'    => '_fa_access_permissions',
        'value'       => $permissions,
    ]);
}

Admins with manage_options bypass this table entirely — see the Permission Manager guide.

Hook Prefix ​

All custom action and filter hooks use the fluent_affiliate/ prefix:

php
do_action('fluent_affiliate/referral_created', $referral);
apply_filters('fluent_affiliate/portal_menu_items', $menuItems);

This prefix is consistent across all hooks fired by both the free plugin and the Pro add-on.

Plugin Constants ​

ConstantDescription
FLUENT_AFFILIATE_DIRAbsolute server path to the plugin directory (with trailing slash)
FLUENT_AFFILIATE_URLURL to the plugin directory (with trailing slash)
FLUENT_AFFILIATE_VERSIONCurrent plugin version string
FLUENT_AFFILIATE_PLUGIN_BASENAMEPlugin basename string (e.g. fluent-affiliate/fluent-affiliate.php) — used for activation hooks and plugin row links
FLUENT_AFFILIATE_PRODefined (with plugin version) when the Pro add-on is active

Pro Plugin ​

FluentAffiliate Pro extends the core plugin with additional integrations, affiliate groups, creative assets, multi-domain tracking, and subscription renewal commissions. The FLUENT_AFFILIATE_PRO constant signals that Pro features are available.

php
if ( defined( 'FLUENT_AFFILIATE_PRO' ) ) {
    // Pro features are available — safe to call Pro-only APIs
}

Endpoints and hooks that require Pro are labeled PRO throughout this documentation.

FluentAffiliate developer documentation