Scheduling Syncs
Set up automated syncs so your search performance data stays fresh without manual intervention.
Recommended frequency
A daily sync is ideal. Google Search Console data has a 2-3 day delay, so running once daily ensures you always have the most recent available data. Running more frequently provides no additional data.
Using cron
Add a cron job to run the sync daily at 2 AM:
# Edit crontab
crontab -e
# Add this line (runs daily at 2:00 AM)
0 2 * * * cd /path/to/your/project && pnpm pagebridge sync --site sc-domain:example.com >> /var/log/pagebridge-sync.log 2>&1Using GitHub Actions
Create a workflow file for automated syncs:
.github/workflows/pagebridge-sync.yml
name: PageBridge Daily Sync
on:
schedule:
- cron: '0 2 * * *' # Daily at 2:00 AM UTC
workflow_dispatch: # Allow manual triggers
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- name: Run PageBridge sync
run: pnpm pagebridge sync --site sc-domain:example.com --check-index
env:
GOOGLE_SERVICE_ACCOUNT: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
SANITY_PROJECT_ID: ${{ secrets.SANITY_PROJECT_ID }}
SANITY_DATASET: ${{ secrets.SANITY_DATASET }}
SANITY_TOKEN: ${{ secrets.SANITY_TOKEN }}
SITE_URL: ${{ secrets.SITE_URL }}Setting up GitHub Secrets
In your GitHub repository, go to Settings > Secrets and variables > Actions and add each environment variable as a secret.
Using Vercel Cron
If your site is deployed on Vercel, you can create an API route that triggers the sync and schedule it with Vercel Cron:
app/api/cron/pagebridge-sync/route.ts
import { SyncEngine, GSCClient, DecayDetector, URLMatcher, TaskGenerator } from '@pagebridge/core'
import { createDb } from '@pagebridge/db'
import { createClient } from '@sanity/client'
export async function GET(request: Request) {
// Verify the request is from Vercel Cron
const authHeader = request.headers.get('authorization')
if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
return new Response('Unauthorized', { status: 401 })
}
// Run sync...
const gsc = new GSCClient({
credentials: JSON.parse(process.env.GOOGLE_SERVICE_ACCOUNT!)
})
const db = createDb(process.env.DATABASE_URL!)
const sanity = createClient({
projectId: process.env.SANITY_PROJECT_ID!,
dataset: process.env.SANITY_DATASET!,
token: process.env.SANITY_TOKEN!,
apiVersion: '2024-01-01',
useCdn: false
})
const engine = new SyncEngine({ gsc, db, sanity })
const result = await engine.sync({ siteUrl: 'sc-domain:example.com' })
return Response.json({ success: true, pages: result.pages.length })
}vercel.json
{
"crons": [
{
"path": "/api/cron/pagebridge-sync",
"schedule": "0 2 * * *"
}
]
}Multiple sites
If you manage multiple GSC properties, run separate sync commands for each:
pagebridge sync --site sc-domain:example.com
pagebridge sync --site sc-domain:other-site.comSee Multi-site setup for more details.