# Ordio Loop Partner Platform – Documentation

**Last Updated:** 2026-04-10

**Icons:** Partner app UI uses a shared SVG icon registry (no emoji). Reference: [ORDIO_LOOP_ICONOGRAPHY.md](./ORDIO_LOOP_ICONOGRAPHY.md); admin preview: `/partner/icon-preview`.

This document provides an overview of the Ordio Loop partner platform: how it works, what each section does, and how it integrates with HubSpot. Copy and paste this content into Notion for easy reference.

---

## What is Ordio Loop?

Ordio Loop is Ordio's affiliate partner program. Partners earn monthly recurring revenue (MRR) by referring customers to Ordio. When a referred lead becomes a customer, the partner receives a percentage of that customer's MRR based on their partner level.

**How it works:** Partners share referral links; referred users submit forms (demo booking, lead capture, etc.); leads are attributed automatically; when a deal is closed, sales sets affiliate properties on the deal; partners earn a share of MRR based on their level.

**Key URLs:**
- Dashboard: `ordio.com/partner/dashboard`
- Login: `ordio.com/partner/login`
- Registration: `ordio.com/partner/register`
- Partner program landing: `ordio.com/partner`

---

## Platform Sections (Sidebar)

| Tab | Route | Purpose |
|-----|-------|---------|
| **Dashboard** | /partner/dashboard | Overview: KPIs (Leads, Qualified Leads, **Deals as Offen/Gewonnen**, MRR), Schnellstart tips, Conversion Funnel chart, MRR trend, Lead trend, Recent Activity |
| **Leads** | /partner/leads | Table of referred leads with status filters (Neu, Qualifiziert, Deal, Gewonnen). Filter „Deal“ = contact **lifecycle** (Opportunity), not HubSpot deal objects; hint links to Earnings |
| **Earnings** | /partner/earnings | MRR breakdown (Active/Paused/Cancelled), **deal list (pipeline + won + lost)**; commission columns only for closed-won with MRR; MRR trend chart, MRR-Anteil |
| **Referral-URLs** | /partner/referral-urls | Quick links (Startseite, Schichtplanung, Zeiterfassung, Preise), page selector table, UTM form with presets (Newsletter, LinkedIn, E-Mail, WhatsApp, Blog/Website), Material & Vorlagen (logo, approved copy) |
| **Resources** | /partner/resources | Asset library (logos, images, PDFs, videos); filter by type, tag, category |
| **Levels** | /partner/levels | Current level, progress to next level, badges, achievements |
| **Leaderboard** | /partner/leaderboard | Top partners by MRR (e.g. "Top Partner (February 2026)"); your rank when applicable |
| **Verwaltung** (Admin) | /partner/admin | Admin-only: partner list, status, sync trigger, level override |
| **Einstellungen** | /partner/settings | Profile (name editable; email and Partner ID read-only), password |

---

## HubSpot Integration

```mermaid
flowchart TD
    subgraph referral [Referral Flow - Automatic]
        A1[Partner shares link] --> A2[User clicks and submits form]
        A2 --> A3[Contact gets affiliate_partner_id]
    end
    subgraph sales [Deal Attribution - Manual]
        B1[Sales creates deal] --> B2[Sales sets affiliate props on deal]
    end
    subgraph sync [Dashboard]
        A3 --> C1[HubSpot sync hourly on server]
        B2 --> C1
        C1 --> C2[Partner sees leads and MRR]
    end
```

### Partner Registration and HubSpot

- Partners register at ordio.com/partner/register (name, email, password).
- Each partner receives a unique **Partner ID** in the format `AP-YYYYMMDD-XXXXXX` (e.g. `AP-20260129-ABC123`).
- A partner record is created in HubSpot as a custom object (`affiliate_partner`).

### How Referred Leads Are Linked

1. Partner shares a referral link: `https://www.ordio.com/?affiliate=AP-20260129-ABC123`
2. User clicks the link – the `affiliate` parameter is stored in a cookie.
3. User submits a form (demo, lead capture, etc.) on ordio.com.
4. The system automatically sets on the **Contact**:
   - `affiliate_partner_id` = Partner ID (e.g. `AP-20260129-ABC123`)
   - `affiliate_referral_date` = Date of form submission

**Finding attributed leads in HubSpot:** In Contacts, filter by `Affiliate Partner ID` is not empty, or search for a specific partner ID: `affiliate_partner_id:AP-20260129-ABC123`.

**Internal Slack (#loop-updates):** New partner registrations and **partner-attributed leads** post structured Block Kit messages. Website forms notify immediately; contacts first linked in HubSpot (e.g. manual `affiliate_partner_id`) are picked up on the **hourly affiliate sync** (with dedupe so the same lead is not posted twice). Optional: a HubSpot workflow can POST to `v2/api/slack-loop-lead-attribution-webhook.php` with a shared secret for instant CRM-driven alerts. Details: `docs/systems/affiliate/SLACK_LOOP_UPDATES.md`.

### Deal Attribution (Sales Responsibility)

- **Leads (Contacts):** Attribution is automatic via `affiliate_partner_id`.
- **Deals:** Attribution is **manual** – sales must set affiliate properties on deals when a referred lead converts to a customer.

**When creating or updating a deal for a referred customer:**

1. Open the contact record and check if `Affiliate Partner ID` is set.
2. If yes, set on the **Deal**:
   - `affiliate_partner_id` = Partner ID (copy from contact)
   - `affiliate_mrr` = Monthly recurring revenue (e.g. 89 for €89/month)
   - `affiliate_subscription_status` = Active, Paused, or Cancelled

**Update `affiliate_subscription_status` when customers pause or cancel their subscription.**

**All three properties must be set on the deal** for MRR to appear in the partner dashboard. If the contact has `Affiliate Partner ID` but the deal does not, the deal will not count toward partner earnings.

### HubSpot Properties and Expected Values

**Contact properties (set automatically):**

| Property | Type | Values |
|----------|------|--------|
| `affiliate_partner_id` | Text | Partner ID, e.g. `AP-20260129-ABC123` |
| `affiliate_referral_date` | Date | YYYY-MM-DD |

**Deal properties (set by sales):**

| Property | Type | Values |
|----------|------|--------|
| `affiliate_partner_id` | Text | Partner ID (copy from contact) |
| `affiliate_mrr` | Number | e.g. 89 (€89/month) |
| `affiliate_subscription_status` | Enum | Active, Paused, Cancelled |

### UTM Parameters (Optional for Campaign Tracking)

Partners can add UTM parameters to their links (utm_source, utm_medium, utm_campaign, utm_content, utm_term) to analyze which campaigns perform best. **Partner attribution** is always via `affiliate_partner_id` (from the `affiliate` URL parameter); UTM is for campaign analytics only.

**Recommended values for partner links:**
- `utm_source` = affiliate or partner
- `utm_medium` = referral (or email/social)

UTM data uses the same HubSpot properties as other traffic. Filter partner reports by `affiliate_partner_id` or `utm_source=affiliate`.

### Automation Option

A HubSpot workflow can automatically copy `affiliate_partner_id` from the contact to the deal when a deal is created and the contact has `affiliate_partner_id` set. This reduces manual work and ensures consistent attribution. Sales can still set `affiliate_mrr` and `affiliate_subscription_status` manually.

### Automated Sync (HubSpot → Partner Dashboard)

Dashboard data (leads, deals, MRR) is pulled from HubSpot via an **automated sync**. **Production:** run **hourly** on the app server (`php v2/cron/sync-affiliate-hubspot.php` via cron — see `v2/cron/crontab-production.txt` and [CRON_SYNC_RUNBOOK.md](./CRON_SYNC_RUNBOOK.md)). A **GitHub Actions** job may also call a webhook **twice daily** as backup; freshness for partners still follows the server schedule. When sales sets affiliate properties on a deal, the partner will see the update after the next sync. Admins can trigger a manual sync from Verwaltung ("Sync mit HubSpot") if needed (rate-limited).

---

## Partner Levels and MRR

Levels are calculated based on won deals in the last 90 days (rolling window).

```mermaid
flowchart LR
    Beginner[Beginner 0 deals] -->|20%| Starter[Starter 1-5]
    Starter -->|25%| Partner[Partner 6-10]
    Partner -->|30%| Pro[Pro 11+]
```

| Level | Deals in 90 Days | MRR Share |
|-------|------------------|-----------|
| Beginner | 0 | 0% (display only until first deal) |
| Starter | 1–5 | 20% |
| Partner | 6–10 | 25% |
| Pro | 11+ | 30% |

**MRR formula:** Partner MRR = Σ(Deal MRR × Partner Level MRR Share %)

**Example:** Deal MRR €89/month, Partner level (25% share) → Partner earns €22.25/month from that deal.

---

## Data Updates

- HubSpot sync is scheduled **hourly on the production server** (see CRON_SYNC_RUNBOOK). Dashboard data refreshes on page load from the cached sync result.
- Level updates occur after each sync based on the rolling 90-day window.
- Leaderboard reflects cache updates after each successful sync (hourly when server cron is primary).

---

## Admin (Verwaltung)

The Admin tab is visible only to partners with admin access. It includes:

- **Partner list:** Search, filter by status (Aktiv, Deaktiviert, Ausstehend) and level, pagination, CSV export; columns include Leads, Deals, MRR, last activity
- **Partner actions:** Activate, deactivate, assign or revoke admin
- **Sync mit HubSpot:** Manual trigger to run the sync immediately
- **Level override:** Admins can set a manual level for strategic partners (e.g. Pro for 6 months); overridden partners show a "manuell" badge (e.g. "Pro manuell")
- **Admins:** Assign or revoke admin access; **Letzte Aktionen** shows audit log of changes

---

## Troubleshooting

**Deal not showing in partner dashboard**
- Check that `affiliate_partner_id`, `affiliate_mrr`, and `affiliate_subscription_status` are all set on the deal
- Ensure deal stage is Closed Won
- Wait for next server sync (typically hourly), use Admin manual sync if allowed, or wait for backup webhook run

**Contact has Affiliate Partner ID but deal does not**
- Sales did not set affiliate properties when creating the deal
- Open the deal, copy `affiliate_partner_id` from the contact, and set all three affiliate properties on the deal

**MRR calculation incorrect**
- Verify `affiliate_mrr` matches the actual monthly subscription amount
- Verify `affiliate_subscription_status` is correct (Active, Paused, Cancelled)
- Verify partner level is correct (affects MRR share percentage)
