How OpenSEO Implements Scheduled Rank Tracking with Cloudflare Workflows

OpenSEO performs automated rank tracking through a Cloudflare Workflow that executes on a Cron schedule, validating runs, checking billing credits, and queuing keyword checks via the DataForSEO API.

OpenSEO is an open-source SEO platform that leverages Cloudflare Workflows to automate keyword position monitoring without maintaining dedicated infrastructure. The system uses a cron-triggered workflow defined in src/server/workflows/RankCheckWorkflow.ts to orchestrate daily rank checks, handling everything from credit validation to incremental result persistence. This architecture separates scheduled batch processing from manual live checks to optimize API costs and execution reliability.

Cron Schedule Configuration in wrangler.jsonc

The workflow trigger is defined in the Cloudflare Workers configuration file at the repository root. The Cron trigger is declared under the triggers.crons array in wrangler.jsonc, specifying when Cloudflare should automatically invoke the workflow.

When the cron expression fires (for example, "0 0 * * *" for daily midnight UTC), Cloudflare creates a workflow invocation that resolves to the RankCheckWorkflow entry-point with the trigger parameter set to "scheduled".

{
  "name": "open-seo",
  "type": "javascript",
  "compatibility_date": "2024-09-01",
  "triggers": {
    "crons": [
      "0 0 * * *"
    ]
  },
  "vars": {
    "RANK_CHECK_TRIGGER": "scheduled"
  }
}

The RankCheckWorkflow Orchestration Logic

The core workflow implementation lives in src/server/workflows/RankCheckWorkflow.ts. At line 46, the workflow checks the trigger type to determine execution mode. For scheduled triggers, it routes to runQueuedCheck (line 56); for manual invocations, it uses runLiveCheck (line 58).

The workflow executes a six-step pipeline that ensures reliable, cost-effective rank tracking:

Step 1: Run Validation

Before processing keywords, the workflow validates that the associated RankTrackingRepository run is still active. It checks that run.status is neither failed nor completed, preventing duplicate or stale executions from consuming resources.

Step 2: Keyword Preparation and Cost Estimation

The workflow loads all keywords associated with the requested configuration, optionally filtering by supplied IDs. It then calls estimateRankCheckCredits (lines 88-94) to calculate the total credit cost based on keyword volume, device types, and SERP depth.

Step 3: Credit Validation via Autumn

For deployments running on hosted Cloudflare Access servers, the workflow queries the Autumn billing service (lines 101-124) to verify that the user’s balance covers the estimated cost. If credits are insufficient, the workflow terminates early to prevent API charges.

Step 4: Executing the Check

The workflow routes execution based on trigger type:

  • Scheduled runs: Calls runQueuedCheck (implemented in src/server/workflows/rankCheckPaths.ts), which submits keywords to DataForSEO's task queue. This asynchronous approach costs approximately 30% of a live check and is ideal for bulk monitoring.
  • Manual runs: Calls runLiveCheck for immediate synchronous results, useful for on-demand validation.
// Cloudflare invokes the workflow with trigger: "scheduled"
// The workflow routes to runQueuedCheck for cost-efficient batch processing
await runQueuedCheck(step, {
  client,
  keywords,
  devices,
  serpDepth,
  domain,
  locationCode,
  languageCode,
  locationName,
  runId,
});

Step 5: Result Collection

As the workflow progresses, it writes each batch of results to the rank_tracking_snapshots table. This incremental persistence strategy prevents data loss if the workflow encounters errors during long-running checks with thousands of keywords.

Step 6: Finalization and Event Tracking

Upon completion, the workflow updates the run status to completed, writes a summary line to the logs, and fires a PostHog analytics event via captureServerEvent (lines 104-126). This provides observability into execution success and credit consumption.

Error Handling and Reliability

If any step throws an exception, the workflow invokes markRankCheckRunFailed (lines 29-49) to update the database record with the specific failure reason. This ensures that stale or erroneous runs are clearly marked, preventing the cron schedule from attempting to reprocess corrupted configurations indefinitely.

Database Schema and Persistence

The RankTrackingRepository class in src/server/features/rank-tracking/repositories/RankTrackingRepository.ts handles all database operations. The schema is defined in src/types/schemas/rank-tracking.ts, which structures the rank_tracking_snapshots table for time-series ranking data and the configuration tables for keyword lists.

Summary

  • Cloudflare Workflows execute rank tracking via Cron triggers defined in wrangler.jsonc, automatically invoking the workflow at specified intervals.
  • RankCheckWorkflow.ts orchestrates the process through six distinct steps: validation, preparation, billing checks, execution, persistence, and finalization.
  • Cost optimization is achieved through runQueuedCheck, which uses DataForSEO's task queue at roughly 30% the cost of live checks for scheduled monitoring.
  • Billing validation occurs via the Autumn service before API calls are initiated, preventing overage charges for hosted deployments.
  • Data integrity is maintained by writing results incrementally to rank_tracking_snapshots and marking failed runs explicitly via markRankCheckRunFailed.

Frequently Asked Questions

How does OpenSEO schedule automated rank tracking checks?

OpenSEO uses Cloudflare's Cron triggers defined in the wrangler.jsonc configuration file. The triggers.crons array specifies the schedule (e.g., "0 0 * * *" for daily execution), and Cloudflare automatically invokes RankCheckWorkflow with the trigger parameter set to "scheduled" at those intervals.

What is the difference between runQueuedCheck and runLiveCheck?

runQueuedCheck submits keywords to DataForSEO's asynchronous task queue, making it cost-effective (approximately 30% of live-check pricing) and suitable for scheduled bulk monitoring. runLiveCheck performs synchronous API calls for immediate results, designed for manual, on-demand rank checks where latency is acceptable but cost is higher.

How does the workflow prevent excessive API charges?

Before executing checks, the workflow calls estimateRankCheckCredits to calculate the total cost, then queries the Autumn billing service to verify sufficient user balance. If credits are insufficient, the workflow terminates before invoking paid DataForSEO APIs, protecting users from accidental overages.

What happens if a scheduled rank tracking run fails?

The workflow catches exceptions and invokes markRankCheckRunFailed (lines 29-49) to update the run status to failed and record the specific error reason in the database. This prevents the cron schedule from attempting to reprocess the same corrupted configuration on the next execution cycle.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →