# HubSpot Sync Cron Installation Guide

**Last Updated:** 2026-03-06

Step-by-step guide for installing the hourly HubSpot affiliate sync cron job in production.

> **💡 Don't have server access?** See [CRON_WITHOUT_SERVER_ACCESS.md](CRON_WITHOUT_SERVER_ACCESS.md) for the quickest solution (2 minutes, no server access required).

## Installation Methods

### Method 0: GitHub Actions Scheduled Workflow - **Easiest** ⭐ **RECOMMENDED**

**Time:** 2 minutes | **No server access required** | **No external services needed**

The workflow file is already created in the repository (`.github/workflows/hubspot-sync-cron.yml`). Just add the GitHub Secret:

#### Setup Steps

1. **Add GitHub Secret:**
   - Go to: **Settings** → **Secrets and variables** → **Actions**
   - Click **New repository secret**
   - Name: `CRON_WEBHOOK_SECRET`
   - Value: `cf5a877749d9c94e4d6c0bfee780d73b` (hardcoded token from config file)
   - Click **Add secret**

2. **Verify workflow is enabled:**
   - Go to **Actions** tab
   - Select **HubSpot Sync Cron** workflow
   - Click **Run workflow** → **Run workflow** (manual test)
   - Check logs to verify success

**Done!** The sync will run automatically every hour.

See [GITHUB_SECRETS_SETUP.md](GITHUB_SECRETS_SETUP.md) for detailed setup instructions.

### Method 1: External Cron Service (Webhook) - **No Server Access Required**

If you prefer using an external cron service instead of GitHub Actions:

**No server configuration needed!** The token is hardcoded in `v2/config/cron-webhook-config.php`.

#### Setup Steps

1. **Choose an external cron service** (free options):
   - **cron-job.org** (free, reliable): https://cron-job.org
   - **EasyCron** (free tier): https://www.easycron.com
   - **Cronitor** (free tier): https://cronitor.io

2. **Configure the cron job** in your chosen service:
   - **URL:** `https://www.ordio.com/v2/api/cron-webhook-sync.php?token=cf5a877749d9c94e4d6c0bfee780d73b`
   - **Schedule:** Every hour (`0 * * * *` or "Hourly")
   - **Method:** GET or POST
   - **Timeout:** 600 seconds (10 minutes)

3. **Test the webhook:**
   ```bash
   curl "https://www.ordio.com/v2/api/cron-webhook-sync.php?token=cf5a877749d9c94e4d6c0bfee780d73b"
   ```

   Expected response:
   ```json
   {
     "success": true,
     "message": "Sync completed successfully",
     "partners_processed": 15,
     "timestamp": "2026-03-06T12:00:00+00:00"
   }
   ```

#### Advantages

- ✅ No server access required
- ✅ Works with any hosting provider
- ✅ Easy to set up and test
- ✅ Can monitor webhook calls from external service
- ✅ Automatic retries if webhook fails

#### Security Notes

- The webhook endpoint requires a secret token to prevent unauthorized access
- Rate limiting: Max 1 call per 5 minutes (prevents abuse)
- Token is never logged or exposed in error messages

### Method 2: Hosting Control Panel (cPanel, Plesk, etc.) - **No Server Access Required**

If you don't have SSH/server access, use your hosting control panel:

#### cPanel

1. **Log into cPanel**
2. **Find "Cron Jobs"** (usually under "Advanced" or "Advanced Features")
3. **Click "Cron Jobs"**
4. **Add New Cron Job:**
   - **Common Settings:** Select "Once Per Hour (0 * * * *)"
   - **Command:** Copy and paste this command:
     ```bash
     cd /var/www/lexikon && /usr/bin/php v2/cron/sync-affiliate-hubspot.php >> /var/log/affiliate-sync.log 2>&1
     ```
   - **Note:** Update `/var/www/lexikon` to your actual production path if different
   - **Note:** Update `/usr/bin/php` to your PHP CLI path (cPanel usually shows this in the cron interface)
5. **Click "Add New Cron Job"**

#### Plesk

1. **Log into Plesk**
2. **Go to "Scheduled Tasks"** (under "Tools & Settings" or domain settings)
3. **Click "Add Task"**
4. **Configure:**
   - **Task name:** "HubSpot Affiliate Sync"
   - **Run:** "Hourly"
   - **Command:** 
     ```bash
     cd /var/www/lexikon && /usr/bin/php v2/cron/sync-affiliate-hubspot.php >> /var/log/affiliate-sync.log 2>&1
     ```
5. **Save**

#### Other Control Panels

Most hosting control panels have a "Cron Jobs" or "Scheduled Tasks" section. Look for:
- **Schedule:** Hourly (or `0 * * * *`)
- **Command:** The command above
- **Path:** Make sure to use the correct production directory path

### Method 4: Provide Instructions to Server Admin

If someone else manages the server, send them this:

**Subject: Install HubSpot Sync Cron Job**

Please install the hourly HubSpot sync cron job on the production server:

**File to use:** `v2/cron/crontab-production.txt` (in the repository)

**Quick install command:**
```bash
cd /var/www/lexikon
crontab v2/cron/crontab-production.txt
```

**Or manually add this line to crontab:**
```bash
crontab -e
# Add this line:
0 * * * * cd /var/www/lexikon && /usr/bin/php v2/cron/sync-affiliate-hubspot.php >> /var/log/affiliate-sync.log 2>&1
```

**Verification:**
After installation, run: `php v2/scripts/affiliate/verify-cron-installed.php`

**What it does:**
- Runs hourly at minute 0 (00:00, 01:00, 02:00, etc.)
- Syncs partner data from HubSpot
- Updates levels and MRR
- Logs to `/var/log/affiliate-sync.log`

### Method 3: Direct Server Access (SSH)

**On production server:**

```bash
cd /var/www/lexikon
crontab v2/cron/crontab-production.txt
```

This installs:
- **Hourly HubSpot sync** (runs at minute 0 of every hour)
- **Daily health check** (runs at 9:00 UTC)
- **Daily performance analysis** (runs at 2:00 AM)

## Verification

After installation, verify the cron is set up correctly:

```bash
# Check if cron is installed
php v2/scripts/affiliate/verify-cron-installed.php

# Or manually check crontab
crontab -l | grep sync-affiliate-hubspot
```

Expected output from verification script:
```
OK: Affiliate sync cron is installed
  Sync: 0 * * * * cd /var/www/lexikon && /usr/bin/php v2/cron/sync-affiliate-hubspot.php >> /var/log/affiliate-sync.log 2>&1
```

## Manual Installation (Alternative)

If you prefer to add manually or edit existing crontab:

```bash
# Edit crontab
crontab -e

# Add this line:
0 * * * * cd /var/www/lexikon && /usr/bin/php v2/cron/sync-affiliate-hubspot.php >> /var/log/affiliate-sync.log 2>&1
```

## Path Configuration

**Important:** Update the path in `v2/cron/crontab-production.txt` if your production directory is different from `/var/www/lexikon`:

1. Edit `v2/cron/crontab-production.txt`
2. Replace `/var/www/lexikon` with your actual production path
3. Replace `/usr/bin/php` with your PHP CLI path (find with: `which php`)

## Testing

Before relying on cron, test the sync manually:

```bash
cd /var/www/lexikon
php v2/cron/sync-affiliate-hubspot.php
```

Expected output:
```
[2026-03-06 12:00:00] [INFO] Starting HubSpot affiliate partner sync...
[2026-03-06 12:00:01] [INFO] Processing partner: AP-20260129-AD2F73
...
[2026-03-06 12:00:45] [INFO] Sync completed successfully
```

## Monitoring

### Log Files

- **Sync logs:** `/var/log/affiliate-sync.log` (stdout/stderr from hourly sync)
- **Health check logs:** `/var/log/affiliate-sync-health.log` (daily health check output)
- **PHP error log:** Check your server's PHP error log for `[Affiliate Sync]` entries

### Health Check

Run the health check script manually:

```bash
php v2/scripts/affiliate/monitor-sync-health.php
```

This checks:
- Cache file exists and is valid
- Last sync timestamp
- Sync age (should be < 2 hours for hourly cron)
- Data completeness

### Email Alerts

If the sync fails, an email alert is automatically sent to `hady@ordio.com` with:
- Error message
- Error code
- Last successful sync timestamp
- Remediation steps

## Troubleshooting

### Cron Not Running

1. **Check cron service is running:**
   ```bash
   systemctl status cron  # Debian/Ubuntu
   # or
   systemctl status crond  # CentOS/RHEL
   ```

2. **Check cron logs:**
   ```bash
   grep CRON /var/log/syslog  # Debian/Ubuntu
   # or
   grep CRON /var/log/cron    # CentOS/RHEL
   ```

3. **Verify PHP CLI path:**
   ```bash
   which php
   /usr/bin/php --version
   ```

### Sync Not Updating Cache

1. **Check file permissions:**
   ```bash
   ls -la /var/www/lexikon/v2/data/
   # Cache directory should be writable
   ```

2. **Check lock file:**
   ```bash
   ls -la /var/www/lexikon/v2/data/affiliate_hubspot_sync.lock
   # If lock file exists and is old, another sync may be stuck
   ```

3. **Run sync manually and check for errors:**
   ```bash
   php v2/cron/sync-affiliate-hubspot.php
   ```

### Sync Taking Too Long

The sync processes all active partners sequentially. With 50+ partners, it may take 1-2 minutes. The script includes rate limiting to stay under HubSpot API limits.

## Related Documentation

- [CRON_SYNC_RUNBOOK.md](CRON_SYNC_RUNBOOK.md) - Detailed operational runbook
- [CRON_ENTRY.txt](CRON_ENTRY.txt) - Single-line cron entry reference
- [DEPLOYMENT_CHECKLIST.md](DEPLOYMENT_CHECKLIST.md) - Full deployment checklist
