System Reference Guide

BannerConnect

Self-hosted affiliate banner program — partner management, click tracking, commission automation, and payment processor webhooks.

PHP / SQLite3 Bootstrap 5.3.2 Stripe + Square PHPMailer
01

System Overview

Partners place an HTML banner on their website. When a visitor clicks, a 30-day tracking cookie is set. If that visitor later completes a purchase — via Stripe, Square, or a manually entered sale — commission is calculated at the partner's rate and queued for payout.

Admin

Full Control

Manages partners, banners, sales, payouts, and all settings. Session key: bc_admin_id

Partner

Dashboard Access

Views clicks, commissions, payouts, and copies embed codes. Session key: bc_partner_id

Visitor

Public Pages

Sees the landing page, registration, and login. No session required.

02

File & Directory Structure

bannerconnect/
├── admin/
│ ├── includes/
│ │ ├── config.php ← main config, all shared functions
│ │ ├── header.php ← admin sidebar layout
│ │ └── footer.php
│ ├── database/
│ │ ├── bannerconnect.db ← SQLite database
│ │ ├── database.sql ← schema
│ │ └── setup.php ← one-time setup (?key=lastcall_setup_2024)
│ ├── index.php ← admin dashboard
│ ├── partners.php ← partner management
│ ├── banners.php ← banner management
│ ├── record-sale.php ← manual sale entry
│ ├── payouts.php ← commission payouts
│ ├── settings.php ← all system settings
│ └── login.php ← admin login
├── assets/
│ ├── css/ ← partner portal CSS
│ ├── uploads/ ← banner images, logo, cover
│ └── postoffice/ ← forgot-password, reset, verify
├── includes/
│ ├── config.php ← thin wrapper → admin/includes/config.php
│ ├── header.php ← partner portal navbar
│ ├── footer.php
│ └── logout.php
├── partners/
│ ├── partner_dashboard.php
│ ├── partner_leads.php
│ ├── partner_login.php
│ ├── partner_profile.php
│ ├── partner_register.php
│ └── partner_verify.php
├── banner.php ← click tracker & cookie setter
├── lead-verify.php ← email verification for leads
├── login.php ← combined admin/partner login
├── stripe-webhook.php ← Stripe payment receiver
├── square-webhook.php ← Square payment receiver
└── index.php ← public landing page
Dead legacy files — safe to delete: admin/partners/admin_partners.php and partners/partner-register.php (hyphen). Neither is linked to from anywhere and both call functions that don't exist in the BC config (require_admin(), is_logged_in()). They would fatal-error if accessed.
03

How It Works — End to End

Partner Onboarding

1
Partner registers at /partners/partner_register.php — status set to unverified
2
Email verification Partner clicks link → partner_verify.php?token=… — status becomes active
3
Admin approves From Partners page — approval email sent automatically
4
Admin creates banner Uploads image in admin/banners.php, assigns to partner
5
Partner embeds code Copies the <a><img></a> embed from their dashboard and pastes it on their site

Click & Cookie Flow

When a visitor clicks the banner, banner.php does exactly three things:

1
Validate Looks up banner and verifies both the banner and its partner are active. Redirects to destination if either is not.
2
Log click Inserts a row in banner_clicks and increments banners.click_count. Visitor is never blocked if this fails.
3
Set cookie & redirect Sets bc_ref cookie and sends visitor to destination_url.

Sale Recording — Three Paths

MethodSource valueTrigger
Stripe webhookstripe_webhookcheckout.session.completed or payment_intent.succeeded
Square webhooksquare_webhookpayment.completed
Admin manualmanualAdmin fills out Record Sale form

All three paths insert a sales row with sale_status='confirmed' and commission_status='pending'.

Payout Flow

1
Admin selects partner In admin/payouts.php, clicks Pay Out next to a partner with pending commissions
2
Batch created All pending confirmed sales for that partner are fetched; one payouts record created; payout_items rows link each sale
3
Sales marked paid All included sales updated to commission_status='paid'
4
Partner notified Payout summary email sent automatically
05

Partner Portal

Pages

PagePathPurpose
Login/partners/partner_login.phpPartner sign-in
Register/partners/partner_register.phpSelf-registration with email verification
Verify/partners/partner_verify.php?token=…Email confirmation link
Dashboard/partners/partner_dashboard.phpStats, banners, embed codes, commissions
Clicks/partners/partner_leads.phpPaginated click log (20 per page)
Profile/partners/partner_profile.phpEdit business info, change password

Partner Statuses

StatusMeaning
unverifiedRegistered — email not yet confirmed
pendingEmail verified — awaiting admin approval
activeFully approved — can log in
suspendedBlocked by admin

Session Keys Set on Partner Login

$_SESSION['bc_partner_id']int — partner primary key
$_SESSION['bc_partner_email']string
$_SESSION['bc_partner_name']string — contact_name
$_SESSION['bc_partner_company']string — company_name
$_SESSION['bc_partner_rate']float — commission_rate
06

Admin Panel

Pages

PagePathPurpose
Dashboard/admin/index.phpStats, pending approvals, recent sales
Partners/admin/partners.phpApprove, suspend, reactivate, update commission rates
Banners/admin/banners.phpCreate, toggle, delete banners; copy embed codes
Record Sale/admin/record-sale.phpManually enter a sale with commission preview
Payouts/admin/payouts.phpPay out pending commissions, view history
Settings/admin/settings.phpAll configuration — general, branding, Stripe, Square
Login/admin/login.phpAdmin-only sign-in (users table, role=admin)

Managing Banners

Create via the Add Banner modal — select an active partner, enter a title, upload an image (JPG/PNG/GIF/WebP, max 5MB). Status defaults to active. The embed code URL format:

https://a1appbuilders.com/addons/bannerconnect/banner.php?b={banner_id}

Toggle pauses/activates. Delete removes the DB record and the uploaded image file.

Managing Partners

Filter by status tab. Commission rate is an inline editable number field — save with the ✓ button. The Approve action sets status to active and sends an approval email. Delete is permanent and removes all partner data (requires confirmation).

Recording a Manual Sale

Use admin/record-sale.php for Stripe/Square payments that missed the webhook, or for invoiced/Zelle payments. Commission is calculated live as a preview. Required: partner + sale amount. If the partner has notify_on_sale = 1, they receive an email automatically.

Processing Payouts

The left panel shows all partners with pending commissions. Click Pay Out to pre-fill the form, set the date, add optional notes (e.g. "Paid via Zelle #123"), then submit. All pending commissions for that partner are marked paid in one atomic operation and the partner is emailed a summary.

07

Payment Processor Integration

Stripe

PropertyValue
Webhook URLhttps://a1appbuilders.com/addons/bannerconnect/stripe-webhook.php
Register inStripe Dashboard → Developers → Webhooks
Eventscheckout.session.completed, payment_intent.succeeded
SignatureVerified via Stripe SDK Webhook::constructEvent()
Duplicate guardChecks processor_transaction_id before inserting

Square

PropertyValue
Webhook URLhttps://a1appbuilders.com/addons/bannerconnect/square-webhook.php
Register inSquare Developer Dashboard → Webhooks
Eventpayment.completed
Affiliate dataPayment note field: bc_partner:5,bc_banner:3
SignatureHMAC-SHA256 of notification_url + raw_body
Both webhooks do NOT start sessions — they are called by external servers. Both verify the request signature before any processing and reject duplicate processor_transaction_id values silently with a 200 response.
08

Settings Reference

All settings are stored in the settings table as key/value pairs and managed from admin/settings.php.

General

KeyDescriptionDefault
destination_urlWhere banner clicks redirect tohttps://a1appbuilders.com/
cookie_daysAffiliate cookie lifetime in days30
default_commission_rateSuggested rate for new partners
admin_emailOverride contact email shown on public pages

Branding

KeyDescription
site_nameSite name shown in nav, emails, and page titles
site_taglineTagline on public landing page
footer_textFooter text in the partner portal
primary_colorPrimary brand color (hex)
secondary_colorSecondary brand color (hex)
accent_colorAccent color (hex)
text_colorBody text color (hex)
bg_colorPage background color (hex)
logo_pathFilename of uploaded logo (stored in assets/uploads/)
cover_imageFilename of uploaded hero/cover image

Stripe Keys

stripe_public_key  ·  stripe_secret_key  ·  stripe_webhook_secret

Square Keys

square_access_token  ·  square_location_id  ·  square_application_id  ·  square_webhook_secret

09

Email Notifications

All email goes through bc_email() in admin/includes/config.php, which wraps send_mail() (PHPMailer over SMTP). SMTP credentials are defined as constants — not stored in the database.

ConstantValue
SMTP_HOSTsmtp.gmail.com
SMTP_USERa1appbuilders@gmail.com
SMTP_PORT587 (STARTTLS)
EMAIL_NAMEA1 App Builders
ADMIN_EMAILsupport@a1appbuilders.com

Emails Sent Automatically

TriggerRecipient
Partner registersPartner (verify link) + Admin (new registration notice)
Admin approves partnerPartner (approval + login link)
Stripe webhook firesPartner (if notify_on_sale = 1)
Square webhook firesPartner (if notify_on_sale = 1)
Manual sale recordedPartner (if notify_on_sale = 1)
Payout processedPartner (payout summary)
Lead email verifiedBanner owner + Partner (if notify_on_lead = 1)
10

Session & Security

Session Timeout — Two-Layer Enforcement

Timeout is 30 minutes (SESSION_TIMEOUT = 1800). Two layers prevent stale sessions:

1 · Cookie Lifetime

session_set_cookie_params(['lifetime' => SESSION_TIMEOUT]) expires the browser cookie after 30 minutes of inactivity.

2 · Server-Side Check

After session_start(), compares bc_last_activity timestamp. If expired: destroys session, regenerates ID, starts fresh.

if (isset($_SESSION['bc_last_activity'])
    && (time() - $_SESSION['bc_last_activity']) > SESSION_TIMEOUT) {
    session_unset();
    session_destroy();
    session_start();
    session_regenerate_id(true);
}
$_SESSION['bc_last_activity'] = time();

CSRF Protection

Every POST form includes a hidden csrf_token field. Generated by csrf_token(), verified by verify_csrf(). Token stored in $_SESSION['bc_csrf'].

Auth Guards

require_bc_admin();    // redirects to /admin/login.php if not admin
require_bc_partner();  // redirects to /partners/login.php if not partner
                        // returns partner array on success

Security Headers

Set after session_start() in every request:

X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
11

Database

Engine: SQLite3 only. Path: admin/database/bannerconnect.db. WAL mode + foreign keys enabled on every connection.

Never use PDO anywhere in this project. Never call $db->open() or $db->close() — the constructor/destructor handles connection lifecycle automatically.
$db = new Database();
$stmt = $db->conn->prepare("SELECT ...");
$stmt->bindValue(':key', $val, SQLITE3_TEXT);
$row = $stmt->execute()->fetchArray(SQLITE3_ASSOC);

Core Tables

TablePurpose
usersAdmin accounts
partnersPartner accounts and profile data
bannersBanner records, linked to a partner
banner_clicksOne row per banner click (IP, UA, referer)
salesCommission-eligible sales from all sources
payoutsPayout batch records
payout_itemsIndividual sales included in each payout
settingsKey/value configuration store
activity_logAll significant system actions
login_logLogin attempts — success and failure

Key Sales Columns

ColumnValues
sale_statusconfirmed
commission_statuspendingpaid
sourcestripe_webhook, square_webhook, manual
payment_processorstripe, square, manual, zelle, other
12

Logs & Error Handling

PHP Error Log

bannerconnect/logs/php_errors.log — created automatically if the directory doesn't exist.

Activity Log

activity_log table via bc_log_activity(). Fields: actor type/id/name, action, IP.

Login Log

login_log table via bc_log_login(). Records both successes and failures with IP and user agent.

All DB operations and mail sends are wrapped in try/catch. A logging or email failure will never cause a 500 error.

13

Config Reference

File: admin/includes/config.php — included by every PHP file in the system.

Path Constants

ConstantResolves to
BC_DIR.../bannerconnect/
ADMIN_DIR.../bannerconnect/admin/
SITE_ROOT.../a1appbuilders.com/
DB_PATHadmin/database/bannerconnect.db
UPLOADS_DIRassets/uploads/ (server path)
LOGS_DIRbannerconnect/logs/

Web Path Constants

ConstantValue
WEB_ROOT/addons/bannerconnect
ADMIN_WEB_ROOT/addons/bannerconnect/admin
PARTNER_WEB_ROOT/addons/bannerconnect/partners
UPLOADS_WEB/addons/bannerconnect/assets/uploads

Shared Functions

FunctionPurpose
get_setting($db, $key, $default)Read value from settings table
set_setting($db, $key, $value)Upsert value into settings table
sanitize($v)htmlspecialchars wrapper
post($k)trim($_POST[$k])
get($k)trim($_GET[$k])
csrf_token()Return or generate session CSRF token
verify_csrf($token)Validate submitted CSRF token
require_bc_admin()Auth guard — admin only
require_bc_partner()Auth guard — partner only; returns partner array
send_mail($to, $subject, $body)Raw PHPMailer send
bc_email($to, $subject, $html)Branded email wrapper around send_mail
bc_log_activity($db, $type, $id, $name, $action)Write to activity_log
bc_log_login($db, $type, $id, $email, $status)Write to login_log
14

Commission Tiers

Rates are set per-partner by admin from the Partners page — there is no automatic tier progression. When a rate is updated, the embed code stays the same; only the commission calculation changes.

TierDefault RateBanner ColorHow to Earn
Starter10%🔵 BlueDefault on account approval
Level 212%🩵 CyanAdmin rate increase
Level 314%🟢 GreenAdmin rate increase
Level 416%🟡 GoldAdmin rate increase
Level 518%🟣 PurpleAdmin rate increase
⭐ Elite20%🔴 RedTop performers only
Banner image files are separate from the commission rate. If you want the visual color change to reflect the new tier, update the banner image in Admin → Banners and give the partner a new embed code.