# Twilio High Charge Notification Widget — GHL Extension

A GoHighLevel (GHL) browser extension script that injects a real-time **SMS spend pill** into the GHL header, giving agents and admins instant visibility into Twilio usage — with a built-in payment modal to top up funds, configure auto-reload, and manage billing thresholds without leaving the CRM.

---

## Overview

This self-contained IIFE script runs inside GHL and does two things:

1. **Polls a backend feed** to fetch the current location's Twilio SMS spend and renders a color-coded pill badge in the GHL header.
2. **Opens a payment modal** when the pill is clicked, allowing users to add funds to their SMS budget, enable auto-reload, set billing thresholds, and add or change a payment card — all without leaving GHL.

The script adapts its UI based on whether the account uses a **legacy included-$200 plan** or a **dedicated usage-based billing** model.

---

## Features

- **Live SMS spend pill** — Color-coded badge injected into the GHL header controls bar
- **Spend-aware color coding** — Green → Yellow → Orange → Red as usage climbs
- **Animated pulse dot** — Draws attention when spend is high or over budget
- **Dual billing model support** — Different UI layouts for legacy and dedicated billing accounts
- **Configurable top-up amounts** — Preset $100/$200 options plus a custom amount input
- **Auto-reload toggle** — Set an automatic reload amount that triggers when budget runs low; turning it off prompts a confirmation warning
- **Billing threshold selector** (dedicated accounts) — Choose between $100 or $200 billing trigger intervals
- **Card on file display** — Shows saved card type, last four digits, and expiry
- **Add new card** — Slide-in side panel with a Stax.js-powered card form (PCI-compliant tokenization)
- **Confirmation overlay** — Two-step confirmation before any charge is processed
- **Invoice download link** — Returned after a successful payment
- **Route change awareness** — Re-fetches usage when navigating to the dashboard

---

## Installation

This script is designed to be injected via a GHL custom JavaScript block or a Chrome extension content script targeting `app.gohighlevel.com`.

1. Copy the full script.
2. Paste it into your GHL location's **Custom JavaScript** field, or load it via your extension's content script.
3. Ensure the following are available on the page:
   - **jQuery** (`$`) — used for AJAX calls and DOM manipulation
   - **Stax.js** (`https://js.staxpayments.com/stax.js`) — loaded dynamically on demand; no pre-loading required
4. The backend PHP files (`feed.php`, `charge.php`) must be deployed at the configured `BASE` URL.

---

## Configuration

| Setting | Location in Code | Description |
|---|---|---|
| `BASE` URL | Top of script | Base URL for `feed.php` and `charge.php` backend endpoints |
| Pill injection target | `getTwillioUsage()` | Looks for `.hl_header--controls` in the GHL DOM |
| Route change trigger | `routeChangeEvent` listener | Re-fetches usage when navigating to the dashboard path |
| Stax.js SDK URL | `_twInitStaxJs()` | `https://js.staxpayments.com/stax.js` |
| Default top-up amount | `selectedOption = 200` | Pre-selected amount shown when modal first opens |
| Custom amount range | `_twCustomAmt()` | Enforced min $25, max $1,000 |

The `stax_web_token` and `stax_id` values are returned dynamically from the `charge.php?action=info` endpoint and are unique per client account.

---

## How It Works

### 1. Pill Injection

On load (and after route changes to the dashboard), `getTwillioUsage()` reads the current `location_id` from the URL and calls `feed.php`. Based on the response:

| Spend vs. Budget | Pill Color | Dot Behavior |
|---|---|---|
| Under $100 (legacy) | 🟢 Green | Static |
| $100–$149 (legacy) | 🟡 Yellow | Static |
| $150–$199 (legacy) | 🟠 Orange | Slow pulse |
| $200+ / over budget | 🔴 Red | Fast pulse |
| Dedicated (any spend) | 🔵 Blue | Static |

Clicking the pill opens the payment modal.

### 2. Modal Load

On open, the modal calls `charge.php?action=info` to fetch detailed account data including usage, remaining budget, billing model, card info, and Stax credentials. The modal then renders one of two layouts based on the `billing_model` field.

---

## Billing Models

### Legacy Included-$200

The account has a $200 included SMS budget. The modal shows:

- Overage amount prominently if over budget
- A usage progress bar
- Preset top-up options ($200 recommended, $100 conservative)
- Custom amount and auto-reload controls
- Card on file with option to use a different card
- Loss-aversion warning and ROI reminder

### Dedicated (Usage-Based)

The account is billed directly based on usage in threshold increments. The modal shows:

- Current total spend
- Total billed vs. unbilled usage
- Explanation of the threshold billing model
- Threshold selector ($100 or $200 per billing cycle)
- Card on file

---

## Payment Flow

1. User clicks the SMS pill → modal opens and fetches account data.
2. User selects a top-up amount (preset or custom) and optionally enables auto-reload.
3. User clicks **"Add $X & Keep Outreach Running"**.
4. A **confirmation overlay** appears showing the exact charge amount, card being charged, and auto-reload details.
5. User clicks **"Confirm & Pay"** → `_twProcessPayment()` POSTs to `charge.php`.
6. On success:
   - The CTA button updates to show the new budget total.
   - A success message appears with an optional **invoice download link**.
   - The pill badge refreshes after 2 seconds.
7. On failure, an error message is shown and the button is re-enabled.

---

## Card Management (Stax.js)

When no card is on file, or the user clicks **"Use different card"**, a slide-in side panel appears containing:

- Cardholder name input
- Card number field (Stax.js iframe)
- Expiry input
- CVV field (Stax.js iframe)
- Save Card button

Card data is tokenized client-side via `staxInstance.tokenize()` — raw card numbers are never sent to the backend. On success, the card is stored in Stax and the main charge button becomes active.

The Stax.js SDK is loaded lazily from `https://js.staxpayments.com/stax.js` only when the card form is needed.

---

## API Endpoints

All requests go to the configured `BASE` URL.

| Request | Endpoint | Method | Purpose |
|---|---|---|---|
| Fetch pill data | `feed.php?location_id=...` | GET | Returns MTD usage and billing model for the pill |
| Fetch modal data | `charge.php?action=info&location_id=...` | GET | Returns full account info: usage, card, Stax token |
| Process payment | `charge.php` | POST | Charges the card on file for the selected amount |
| Set threshold | `charge.php` | POST `action: set_threshold` | Updates the billing threshold for dedicated accounts |

### Expected `feed.php` Response

```json
{
  "success": true,
  "data": {
    "mtd_usage": 142.50,
    "billing_model": "legacy_included_200"
  }
}
```

### Expected `charge.php?action=info` Response

```json
{
  "success": true,
  "client": {
    "usage": 142.50,
    "included": 200,
    "remaining": 57.50,
    "usage_percent": 71,
    "billing_model": "legacy_included_200",
    "has_card": true,
    "card_info": {
      "card_type": "Visa",
      "card_last_four": "4242",
      "card_exp": "12/27"
    },
    "stax_web_token": "web_token_here",
    "stax_id": "stax_customer_id_here"
  }
}
```

### Expected `charge.php` POST Response (success)

```json
{
  "success": true,
  "new_included": 400,
  "new_remaining": 257.50,
  "invoice_id": "txn_abc123"
}
```

---

## Code Structure

```
IIFE
├── Style injection                  — All CSS injected into <head> on load
├── getTwillioUsage()                — Fetches usage and renders the pill badge
├── createModal()                    — Injects the modal + card panel HTML into <body>
├── openModal() / closeModal()       — Shows/hides the overlay
├── loadModal()                      — Calls charge.php info endpoint
├── renderModal(client)              — Renders legacy or dedicated billing UI
│
├── Card Management
│   ├── _twInitStaxJs()              — Loads Stax.js SDK on demand
│   ├── _twSetupStaxForm()           — Initializes Stax card/CVV iframes
│   ├── _twShowNewCard()             — Toggles the card side panel
│   └── _twSaveCard()                — Tokenizes card via Stax.js and updates UI
│
├── Payment Controls
│   ├── _twPick(el, amt)             — Handles preset option card selection
│   ├── _twCustomAmt(val)            — Handles custom amount input
│   ├── _twUpdateCta()               — Updates CTA button label with current amount
│   ├── _twCharge()                  — Shows confirmation overlay
│   └── _twProcessPayment()          — Posts charge to backend
│
├── Dedicated Billing
│   └── _twSetThreshold(val, el)     — Updates billing threshold via POST
│
├── _twLogo(type)                    — Returns inline SVG for Visa/Mastercard/Amex/generic
├── Auto-reload confirmation         — change listener on #tw-reload-check
└── Route change listener            — Re-fetches usage on dashboard navigation
```

---