> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cello.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration QA Checklist

> Comprehensive checklist for testing and verifying Cello referral system integrations

# Cello Integration QA Checklist

## Purpose

This document provides a comprehensive checklist for testing and verifying the Cello referral system integration. Use this to ensure all features have been properly implemented according to the acceptance criteria defined in the [React + Node.js Integration Guide](/resources/react-nodejs-integration).

## How to Use This Checklist

* Check off each item as you verify it works correctly
* Phase 1 items are mandatory for Cello to function
* Phase 2 items are optional enhancements but highly recommended
* Refer to the Integration Guide for implementation details and troubleshooting
* Test in both sandbox and production environments where applicable

***

## Pre-Flight: API Credential Verification

Run this before testing anything else. All subsequent steps depend on valid API credentials.

* [ ] `CELLO_ACCESS_KEY_ID` and `CELLO_SECRET_ACCESS_KEY` sourced from **[portal.cello.so/integrations/accesskeys](https://portal.cello.so/integrations/accesskeys)** (not product settings - these are a separate credential pair)
* [ ] Call `POST https://api.sandbox.cello.so/token` with your `CELLO_ACCESS_KEY_ID` and `CELLO_SECRET_ACCESS_KEY` and confirm you receive a `201` response with an `accessToken`
* [ ] If using a proxied/hosted environment (e.g. Replit, Vercel), confirm secrets are updated in **both** the development and deployment environments separately - they are not always synced automatically
* [ ] Pre-flight check passed - proceed to Step 1

<Warning>
  If you receive a 401: stop here - do not proceed until credentials are resolved. Common causes: wrong credential pair (product secret ≠ access key), credentials saved to wrong environment (deployment vs development), or key partially copied from portal.
</Warning>

***

## Step 1: Server-Side Helpers

### Acceptance Criteria

* [ ] `createCelloJwt()` generates a valid HS512 JWT with `productId`, `productUserId`, `iat` claims only
* [ ] `getCelloScriptUrl()` returns correct URL based on environment
* [ ] `buildCelloBootConfig()` returns config with `productUserDetails` including `firstName`, `lastName`, `fullName`, `email`
* [ ] No sensitive data (product secret) is exposed to the client

***

## Step 2: Referral Widget (Authenticated Users)

### Phase 1 - Basic Widget Functionality (Mandatory)

* [ ] Token endpoint returns `{ enabled: true, bootConfig: {...} }` for authenticated users
* [ ] Token endpoint returns `{ enabled: false }` for unauthenticated users
* [ ] Cello script loads without CORS errors in browser Network tab
* [ ] Console shows no "User is not authorized" errors
* [ ] Widget opens when clicking the launcher button
* [ ] Notification badges appear on the launcher (test with your own referral link)

### Phase 1 - Custom Launcher with Dynamic Labels (REQUIRED If Using Custom Launcher)

* [ ] Dynamic reward label displays on launcher (e.g., "Earn €1000" not just "Earn")
* [ ] **Label updates within 1-2 seconds on FIRST LOGIN** (test with fresh session, not just page refresh)
* [ ] Browser console shows successful `getLabels` call
* [ ] Launcher degrades gracefully if labels fail to load (shows fallback text e.g. "Invite & Earn")
* [ ] Labels persist correctly during navigation within SPA (don't require page refresh)

### Phase 2 - Enhanced Error Handling & Loading States (Optional but Recommended)

* [ ] Widget boot errors are logged with detailed information
* [ ] Failed API calls include request/response details in logs
* [ ] Retry logic attempts boot up to 3 times on failure
* [ ] Attribution errors don't block page load or form submission
* [ ] Launcher shows loading state while fetching labels (visual feedback)
* [ ] User sees appropriate feedback for connection issues (if implementing UI indicators)

***

## Step 3: Public Attribution

### Phase 1 - Core Attribution (Mandatory)

* [ ] Attribution script loads on public pages (check Network tab)
* [ ] `window.CelloAttribution` function is available after script loads
* [ ] Visiting `/?ucc=TEST123` stores the referral code
* [ ] `useCelloAttribution()` hook returns the stored UCC
* [ ] Referrer name displays on signup page when visiting via referral link

<Note>
  **IMPORTANT!** Once you have completed this part of the verifications, add your domain to Cello Portal Landing Page Settings: [https://portal.cello.so/setup/user-experience/landing-page](https://portal.cello.so/setup/user-experience/landing-page)
</Note>

### Phase 2 - Enhanced Attribution (Optional)

* [ ] Hook returns error states for debugging
* [ ] Referrer name displays on signup page when visiting via referral link
* [ ] Campaign configuration fetched alongside UCC and referrer name
* [ ] Campaign discount displays correctly on signup page (e.g., "30% off your first 3 months")
* [ ] Signup banner shows only referrer name when no discount is configured (social proof)
* [ ] Discount format adjusts for singular vs plural months ("month" vs "months")
* [ ] Timeout errors are non-blocking and logged clearly
* [ ] Attribution failures don't crash the page

***

## Step 4: Signup Event Tracking

### Phase 1 - Core Event Tracking (Mandatory)

* [ ] `fetchCelloAccessToken()` successfully retrieves and caches access token
* [ ] Signup with referral code triggers `emitReferralUpdatedEvent()`
* [ ] Server logs show `POST /events` returning status 200
* [ ] Cello dashboard shows the new signup event
* [ ] User model stores `referralCode` field
* [ ] Signup without referral code works normally (no errors)
* [ ] Server logs confirm the full event payload sent to Cello includes `price: 0` and `currency: ""` alongside `ucc` and `newUserId`

### Phase 2 - Referral Code Validation (Optional but Recommended)

* [ ] `validateReferralCode()` successfully validates valid referral codes (returns `true` or valid object)
* [ ] `validateReferralCode()` correctly identifies invalid codes (returns `false` or invalid object)
* [ ] Invalid referral codes are NOT stored in user model
* [ ] Invalid referral codes do NOT trigger `emitReferralUpdatedEvent()`
* [ ] Signup completes successfully even with invalid referral codes (non-blocking)
* [ ] Campaign ID is stored alongside referral code when available (enhanced implementation)

### Phase 2 - Enhanced Logging (Optional but Recommended)

* [ ] Token request logs include full URL and response details
* [ ] Event emission logs include payload structure
* [ ] Environment variables validated on startup
* [ ] Failed API calls show detailed error context

***

## Step 5: Stripe Integration

<Note>
  **Test profile data fetch in create-checkout:** Verify the edge function logs show the actual referral\_code value (not "none" or empty) for a user who has a referral code in the database.

  Check logs: `[CREATE-CHECKOUT] User: <id> Referral code: <actual_code>`

  If logs show "none" but database has a value → RLS is blocking the read
</Note>

### Acceptance Criteria

* [ ] Stripe customers have `cello_ucc` and `new_user_id` in metadata
* [ ] Stripe webhook configured in Cello portal
* [ ] Test purchase shows in Cello dashboard with correct attribution
* [ ] Reading user data like `referral_code` from edge functions is working correctly

***

## Testing Notes

### Environment Checklist

* [ ] All required environment variables are set (see Integration Guide Prerequisites)
* [ ] Cello Portal is properly configured with product ID and API keys
* [ ] Testing in correct environment (sandbox vs production)

### Common Test Scenarios

#### 1. New User via Referral Link

1. Visit site with `?ucc=TEST123` parameter
2. Complete signup flow
3. Verify referral code is stored
4. Check Cello dashboard for signup event

#### 2. Authenticated User Referral Widget

1. Login as existing user
2. Click referral launcher button
3. Verify widget opens with user's referral link
4. Copy link and test in incognito mode

#### 3. Dynamic Labels on First Login (if using custom launcher)

<Warning>
  This is a critical test - labels must appear on first login, not just after page refresh.
</Warning>

1. Clear browser session/cookies (fresh state)
2. Login as existing user
3. **CRITICAL: Verify dynamic label appears within 1-2 seconds** (e.g., "Earn €1000")
4. Do NOT refresh the page - labels must appear on first render
5. Navigate to different pages within the app
6. Verify labels persist without requiring page refresh
7. Check browser console for successful `getLabels` call

#### 4. Invalid Referral Code (Phase 2 - if validation implemented)

1. Visit site with `?ucc=INVALID123` parameter
2. Complete signup flow
3. Verify user is created successfully
4. Verify invalid code is NOT stored in database
5. Verify no event sent to Cello dashboard

#### 5. Stripe Purchase Attribution

1. Complete purchase as referred user
2. Verify Stripe customer has correct metadata
3. Check Cello dashboard for commission tracking

### Troubleshooting

If any checklist item fails, refer to the "Troubleshooting" section in the [Integration Guide](/resources/react-nodejs-integration#troubleshooting) for detailed debugging steps.

***

## Sign-off

* [ ] All Phase 1 (Mandatory) items verified and passing
* [ ] Tested in sandbox environment
* [ ] Tested in production environment (when ready)
* [ ] All critical user flows tested end-to-end

| Field           | Value                   |
| --------------- | ----------------------- |
| **Tester Name** |                         |
| **Date**        |                         |
| **Environment** | ☐ Sandbox  ☐ Production |

**Notes:**

***
