A Meta Conversions API payload can preserve the correct Unix-seconds format and still carry a bad event_time when the WordPress web node, database, queue, cron runner, or container clock drifts. Retries can hide the problem by replacing the original action time with the current worker time. A small NTP and timestamp monitor catches drift before future or stale events damage diagnostics, attribution, or browser-server deduplication.
Use this for WordPress and WooCommerce sites that send Meta CAPI events from web requests, Action Scheduler, cron, queues, server-side tag managers, CRMs, or custom worker containers.
Quick answer
Persist the original customer action time and event ID at the event boundary. On every worker, record UTC now, NTP synchronization state, offset, queue age, event age, attempt number, and payload units. Alert on unsynchronized clocks, offset beyond the platform budget, future event_time, implausible age, millisecond values, and retries that change the original timestamp or event ID.
What to check first
- Inventory every host, container, serverless runtime, database, queue, cron path, and external service that creates or transforms event timestamps.
- Record NTP source, synchronization state, measured offset, timezone, boot time, container host, and deployment version.
- Persist original event_time and event ID before enqueueing, then log enqueue, dequeue, attempt, response, and retry timestamps separately.
- Calculate future skew, event age, queue age, transport delay, and whether event_time has ten or thirteen digits.
- Test normal, delayed, retry, clock-ahead, clock-behind, unsynchronized, restart, daylight-saving, and milliseconds fixtures.
Diagnostic table
Use this table to connect the observed behavior to evidence and a verification step.
| Action | Evidence to collect | How to verify |
| Choose an approved NTP source and offset budget for every runtime class. | Inventory every host, container, serverless runtime, database, queue, cron path, and external service that creates or transforms event timestamps. | All event-producing and event-sending runtimes report current synchronization and offset. |
| Persist original event_time and event ID before any asynchronous handoff. | Record NTP source, synchronization state, measured offset, timezone, boot time, container host, and deployment version. | Normal and delayed events retain the original action time and stable event ID. |
| Add local guards for sync state, offset, units, future skew, age, and retry mutation. | Persist original event_time and event ID before enqueueing, then log enqueue, dequeue, attempt, response, and retry timestamps separately. | Future, unsynchronized, stale-by-policy, and millisecond fixtures fail before API upload. |
| Alert with worker, deployment, event ID, offset, queue age, and safe diagnostic context. | Calculate future skew, event age, queue age, transport delay, and whether event_time has ten or thirteen digits. | Meta diagnostics and browser-server deduplication join to the same controlled event. |
Why this usually happens
- Containers inherit host time but monitoring may inspect only the application node.
- Queue workers rebuild payloads and use their current clock instead of persisted action time.
- Readable local timestamps can look correct while the integer sent to the API uses the wrong unit or source.
Useful command or data shape
Adapt paths, IDs, and privacy handling to the site before running commands or storing data on production.
worker,ntp_sync,offset_ms,event_age_s,queue_age_s,attempt,action
web-1,true,18,4,0,1,send
cron-2,true,-42,3605,3600,2,retry-original
queue-3,false,721000,-715,0,1,block-alert
worker-4,true,11,huge,0,1,block-unit
Test scenarios to run
Run the same controlled fixture across these branches. Write down the expected result before testing so a surprising response is easy to identify.
| Scenario | Fixture | Expected result |
| Normal clock | Offset inside budget | Event sends with original Unix seconds |
| Worker ahead | Clock plus ten minutes | Local guard blocks and alerts |
| Delayed retry | Queue waits two hours | Original event_time and ID remain unchanged |
| Millisecond unit | Thirteen-digit value | Schema guard rejects before upload |
Safe fix order
Use a sequence that makes each result easy to prove. Stop when new evidence changes the scope or owner of the problem.
- Choose an approved NTP source and offset budget for every runtime class.
- Persist original event_time and event ID before any asynchronous handoff.
- Add local guards for sync state, offset, units, future skew, age, and retry mutation.
- Alert with worker, deployment, event ID, offset, queue age, and safe diagnostic context.
- Verify Meta acceptance and browser-server deduplication with controlled test events.
Decision rule
Send only when the worker clock is synchronized inside budget, event_time is plausible Unix seconds from the original action, and retries preserve both event_time and event ID. Block and alert when those conditions fail.
Production verification checklist
- All event-producing and event-sending runtimes report current synchronization and offset.
- Normal and delayed events retain the original action time and stable event ID.
- Future, unsynchronized, stale-by-policy, and millisecond fixtures fail before API upload.
- Meta diagnostics and browser-server deduplication join to the same controlled event.
Field notes
- Use UTC for stored evidence and render local time only for humans.
- Do not rewrite an old event to appear recent; alert and handle it under the event-age policy.
- Avoid logging raw user data beside infrastructure metrics. Event ID and hashed destination context are usually enough.
Questions teams ask during testing
Can this be tested on staging?
Start on staging with production-like versions, cache, data shape, roles, integrations, and server packages. Finish with one controlled production fixture when the result depends on real email routing, edge cache, crawler access, payment callbacks, or advertising diagnostics.
What evidence should be retained?
Keep the smallest useful evidence set: exact versions, stable IDs, UTC timestamps, sanitized request or log excerpts, expected result, actual result, decision, and final verification. Redact customer data, secrets, order keys, and full click identifiers.
When should the change be rolled back?
Roll back when a revenue, privacy, security, publishing, or lead path fails and the cause cannot be isolated inside the approved maintenance window. Preserve the failed fixture before rollback so the next attempt starts with facts.
Mistakes to avoid
- Do not change several production layers at once. Preserve the failing evidence and isolate one variable per test.
- Do not treat a green screen, successful request, or quiet log as proof that the customer outcome is correct.
- Do not leave debug logs, broad credentials, test orders, temporary roles, or firewall exceptions active after verification.
- Do not close the work without recording versions, fixture IDs, UTC timestamps, owner, result, and rollback point.
What to tell the client or owner
Give the owner the affected versions, exact fixture, stable IDs, UTC timeline, before and after evidence, decision, rollback point, unresolved risks, and next review date.
When HandL WP should help
Bring in help when this affects leads, checkout, search visibility, security, paid media reporting, or a client production site. HandL WP can trace the issue through WordPress, hosting, cache, tracking, and Search Console, then verify the workflow after the technical fix.
If this is active on a production site, audit Meta CAPI event timing.
Related HandL WP guides
Use these related guides when the same issue touches tracking, security, checkout, or crawler visibility.
Repair one Meta CAPI worker clock as a canary
Run the Meta CAPI WordPress worker NTP remediation canary to correct clock offset while keeping original event_time and stable event IDs through queues, retries, diagnostics, and browser-server deduplication tests.
Helpful references