Title: VizProof Timeline
Author: Tommy Bordas
Published: <strong>Juni 29, 2026</strong>
Last modified: Agustus 27, 2026

---

Search plugins

![](https://ps.w.org/vizproof-timeline/assets/banner-772x250.png?rev=3609315)

![](https://ps.w.org/vizproof-timeline/assets/icon-256x256.png?rev=3609315)

# VizProof Timeline

 By [Tommy Bordas](https://profiles.wordpress.org/tommybordas/)

[Download](https://downloads.wordpress.org/plugin/vizproof-timeline.1.3.5.zip)

 * [Details](https://su.wordpress.org/plugins/vizproof-timeline/#description)
 * [Reviews](https://su.wordpress.org/plugins/vizproof-timeline/#reviews)
 *  [Installation](https://su.wordpress.org/plugins/vizproof-timeline/#installation)
 * [Development](https://su.wordpress.org/plugins/vizproof-timeline/#developers)

 [Support](https://wordpress.org/support/plugin/vizproof-timeline/)

## Description

VizProof Timeline connects WordPress to [VizProof](https://vizproof.com), a visual
regression testing service, so every WordPress update can be followed by an automated
visual check of your key pages.

#### Why

Plugin, theme, and core updates rarely throw PHP errors when they break something
visual: a shifted button, a collapsed layout, a missing hero image. Your monitoring
stays green while your pages degrade. VizProof Timeline catches those regressions
right from wp-admin, before your visitors do.

#### How it works

 1. Click “Connecter à VizProof”: authorize the site from your VizProof account and
    the API token and project are configured automatically (a manual API token also
    works).
 2. Select the pages to monitor: each one is auto-classified as Single, Listing, or
    Static.
 3. Run updates as usual: a modal captures the “before” reference with live progress,
    the update then applies on its own, and a visual scan runs right after.
 4. Read the verdict first (OK / anomalies to review); pipeline and per-site details
    stay folded unless something is wrong.

#### Key features

 * One-click connect to VizProof, without any API token copy/paste (manual token
   still supported)
 * Settings profiles: “Simple (recommandé)” and “Prudent” presets configure the 
   whole automation in one click; fine-grained settings live under “Réglages avancés”
 * Guaranteed before/after ordering: the “before” reference is captured and promoted
   before the update starts, from a progress modal, including for WordPress core
   updates
 * Optional strict mode: cancel the WordPress update if the baseline could not be
   captured in time
 * Post-update scans after plugin, theme, or core updates, including background 
   automatic updates
 * Content-aware reference: publishing or editing content refreshes the baseline
   of the affected pages (partial re-capture on supporting servers), so editorial
   changes never show up as regressions
 * Verdict-first update panel and quiet, dismissible admin notices
 * Run history and visual diff summaries in wp-admin
 * Scheduled checks with WP-Cron (Action Scheduler fallback)
 * Plugin rollback with local backups when an update causes regressions
 * Multisite support in per-site and network-wide modes
 * WP-CLI commands (`wp vizproof status|baseline|scan`) with JSON output and CI-
   friendly exit codes, plus scans hooked into CLI-triggered updates

#### Requirements

A VizProof account and API token are required. The free plan is enough to get started:
sign up at [vizproof.com/register](https://vizproof.com/register). See the Installation
section for the step-by-step setup.

### External services

This plugin connects to VizProof APIs hosted at `https://vizproof.com` (or a custom
VizProof API URL configured by the site administrator).

It sends requests only when plugin features are used (project/page loading, scan
launches, run history refresh, post-update workflows, scheduled scans).

Data that may be sent includes:

 * API token entered by an administrator
 * Linked VizProof site/project ID
 * Page IDs or URLs used for scans
 * Run trigger metadata required by update workflows

Service documentation and policies:

 * Privacy Policy: https://vizproof.com/privacy
 * Terms of Service: https://vizproof.com/terms

## Installation

 1. Upload the `vizproof-timeline` folder to `/wp-content/plugins/`.
 2. Activate **VizProof Timeline**.
 3. Click **VizProof** in the top admin bar, then **Configuration**.
 4. Click **Connecter à VizProof**: sign in (or create a free account), authorize the
    site, and you are redirected back with the API token and project configured automatically.
 5. Select the pages to monitor and save.

Manual alternative (self-hosted servers or if you prefer explicit tokens):

 1. Create a free account at [vizproof.com](https://vizproof.com/register).
 2. Create a project and add at least one page (use your WordPress site URL).
 3. Go to **Account  API Tokens** and generate a token (starts with `vrt_`).
 4. Paste the token in the plugin Configuration page and select the project.

Multisite:

 1. Open `Network Admin -> Settings -> VizProof Timeline`.
 2. Choose `Per-site` or `Network-wide` mode.

## FAQ

### Does this plugin require a VizProof account?

Yes. The free plan is enough to get started. The easiest path is the “Connecter 
à VizProof” button on the plugin Configuration page: it signs you in on vizproof.
com and configures the token and project automatically. A manual API token (Account
API Tokens) also works; see the Installation section.

### Do I have to copy an API token?

Not anymore: one-click connect creates and configures a dedicated, revocable token
for the site. Manual tokens remain supported (useful for self-hosted VizProof servers).

### What happens after a plugin/theme/core update?

If post-update scan is enabled, VizProof Timeline queues a scan after the update
completes and exposes status/results in wp-admin.

### Does WP-CLI trigger the same scan logic?

Yes, in two ways. WP-CLI update commands run through the same updater hooks as an
update started from wp-admin. And three dedicated commands are available once the
site is connected:

 * `wp vizproof status` reports the connection, the selected project and the last
   scan.
 * `wp vizproof baseline --wait` captures a reference and promotes it, to run before
   a deployment.
 * `wp vizproof scan --wait` runs a scan and returns the visual verdict. Exit code
   2 means anomalies were found, which lets a pipeline stop on a visual regression.

Add `--format=json` to any of them for a parsable output. The token and the project
are read from the site configuration, so connect the site from wp-admin first.

### Is multisite supported?

Yes.

 * `Per-site`: each subsite keeps its own configuration.
 * `Network-wide`: one shared network-level configuration.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“VizProof Timeline” is open source software. The following people have contributed
to this plugin.

Contributors

 *   [ Tommy Bordas ](https://profiles.wordpress.org/tommybordas/)

[Translate “VizProof Timeline” into your language.](https://translate.wordpress.org/projects/wp-plugins/vizproof-timeline)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/vizproof-timeline/),
check out the [SVN repository](https://plugins.svn.wordpress.org/vizproof-timeline/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/vizproof-timeline/)
by [RSS](https://plugins.trac.wordpress.org/log/vizproof-timeline/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.3.5

 * Fixed: nothing appeared below the update log to say the post-update scan had 
   started. The result block was created by JavaScript on a page that writes itself
   progressively, so both its presence and its position depended on when the script
   happened to run. It is now rendered by PHP in the page footer, which is the one
   place guaranteed to come after the update log, and it says what it is waiting
   for even if the script never takes over.
 * Fixed: the admin bar spinner never started on the page running an update, which
   is exactly where you watch it. The scan is queued while that page is streaming,
   so the admin bar had already been rendered with an empty state and the script
   had nothing to poll. It now polls on that page regardless of the state it was
   handed.
 * Fixed: the running-scan line in the admin bar menu was not clickable. It now 
   opens the results page.

#### 1.3.4

 * New: the VizProof entry in the admin bar shows when a scan is running, on every
   admin screen. Its eye icon pulses, and the menu carries a live line with the 
   current stage and how long it has been going. Until now a scan was only visible
   on the update screens and on the results page: anywhere else, nothing said one
   was in progress. The initial state is rendered with the page, so no request is
   made while nothing is running, and polling stops on its own after twenty minutes.

#### 1.3.3

 * New: a post-update scan that finds nothing is promoted as the new baseline, on
   by default and switchable in the settings. Without it the reference ages at every
   accepted update, so differences already reviewed come back on the next scan. 
   Promotion only happens on a completed scan with no failed run and no anomaly,
   so a regression is never frozen in as the new normal.
 * The scan card now says what was updated, with names and versions, instead of 
   only “post-update scan”. The plugin already stored the detail and even had a 
   function to format it, which was never called.
 * The history maintenance actions (clean up identical scans, mark as favourite,
   delete this batch) sit in a folded block. Given the same visual weight as “Accept
   and set as baseline”, they competed with it for attention without serving any
   daily purpose.
 * Fixed: a post-update scan took minutes to start, whatever the configured settle
   delay. That delay was applied by scheduling the job in the future, which is the
   one place it cannot work: nothing wakes a job dated later, so Action Scheduler’s
   async queue was bypassed and `spawn_cron()` had no event to trigger. The job 
   waited for a cron pass instead. It is now queued immediately and the settle delay
   is held by the worker, between the cache purge and the capture, capped at 60 
   seconds so a sleeping process is never cut off. Retries keep their exponential
   backoff.
 * Fixed: the VizProof result appeared above the update log, so it read as if the
   scan had run before the update it comments on. The block is meant to sit below
   the update flow, but it was appended while the page was still streaming, which
   put it at the end of whatever had been written so far. It is now pushed back 
   to the end on every render and once more when the page finishes loading.
 * Fixed: on the update execution page, the panel showed the result of a previous
   update under the “VizProof result after the update” heading whenever the current
   scan had not produced a run yet. The scan looked like it had run before the update.
   The listing page already guarded against stale results; the execution page now
   does too and shows the waiting state instead.
 * Fixed: the scan step list announced “all steps completed” while three steps were
   still pending. The summary only looked at running and failed steps, so a pipeline
   made entirely of pending steps read as finished.
 * The results screen shows when a post-update scan is queued or running, with how
   long ago it was requested and a link to the step-by-step view. Progress was only
   visible on the WordPress update screens, so the results page looked as if nothing
   had been started.

#### 1.3.2

 * Cache purging before an update scan now covers WP Fastest Cache, Autoptimize,
   WP-Optimize, Cache Enabler, Hummingbird and Nginx Helper, on top of WP Rocket,
   LiteSpeed, W3 Total Cache, WP Super Cache, Breeze and SiteGround Optimizer. Plugins
   that combine and minify CSS into files whose URL changes on every purge were 
   the ones missing: a page could be served pointing at a stylesheet that no longer
   existed, and the capture then showed the raw document, default list bullets included,
   which reads as a full-page regression.
 * Fixed: a run marked as favourite was displayed as the site baseline. The favourite
   badge reused the baseline badge’s CSS class, and the panel decided “this run 
   is the baseline” by looking for that class in the page, so a favourited run had
   its verdict forced to green and was described as the site’s reference, hiding
   a failure. The two badges are now distinct, and the check reads the card’s actual
   state.
 * Fixed: the verdict opened with “No flow diffs detected” on scans that had found
   visual anomalies. That sentence is what the server returns when no flow ran at
   all, and the panel used it as a fallback when a run had no AI summary, so a message
   about flows announced a visual verdict. The flow summary now stays in the details,
   where its subject is clear.
 * Fixed: the post-update panel repeated itself. On a single site, the same sentence
   was rendered three times over, by the headline banner, the detail box and the
   per-site list. The banner keeps the verdict, the box keeps only what the banner
   has not already said, and the list is reduced to its status and its link. The“
   Results per site” heading no longer appears above a list of one.
 * The baseline bar says which scan is the reference, and takes you to it. When 
   the reference is not among the loaded scans it said “Baseline active”, asserting
   that a reference exists without naming it, while no card below carried a badge.
   It now names the scan and its date, offers a “View this scan” button that selects
   and scrolls to its card, and says plainly when the reference sits outside the
   list.
 * The “Post-update scan” and “Baseline first” checkboxes no longer appear on the
   update execution page, where the choice has already been made and applied, and
   read as settings for what just happened. They stay in the page so the panel keeps
   polling for the scan result, but they are no longer presented as controls.
 * Fixed: “Baseline status unavailable.” was the last English string left in the
   French interface.

#### 1.3.1

 * Fixed: page titles containing an apostrophe showed up as “Page d'accueil” across
   the results screen. A WordPress title can be stored with HTML entities depending
   on the editor that created it; sent as-is when the page was registered, the entity
   was frozen into the VizProof record and escaped a second time on display. Titles
   are now normalized before they leave WordPress, and what comes back from the 
   API is cleaned too, so records created before this release also display correctly.
 * The results screen had accumulated around thirty tinted surfaces, including six
   different pale blues for plain containers, which left no visual hierarchy at 
   all. Colour is now reserved for what carries meaning: the scan verdict, and the
   active baseline. Everything structural sits on two neutral surfaces and two neutral
   borders, driven by a small set of CSS variables. The palette went from 180 hard-
   coded colours to 144.
 * The category chips (SEO, structure, tone) no longer each carry their own colour,
   and the “Action” text is no longer green: their label already says what they 
   are.
 * The results screen is split in two titled sections. Scan results used to render
   under the “Historique des scans” heading, with no section or title of their own:
   the capture summary landed at the very top of the page, far from what it summarised,
   and the simple/expert switch floated between the scan list and the verdict, anchored
   to neither. Results now have their own section, whose header groups the title,
   the summary and the switch. The page navigation no longer sits between the two.

#### 1.3.0

 * New: three WP-CLI commands, `wp vizproof status`, `wp vizproof baseline` and `
   wp vizproof scan`. They drive the same pipeline as the admin screens, take `--
   wait`, `--timeout` and `--format=json`, and return an exit code a build can act
   on: 0 when clean, 2 when the scan found visual anomalies, 1 on a technical failure.
   The site still has to be connected from wp-admin first, as the commands read 
   the stored token and project.
 * Fixed: the reference capture taken before an update failed with “Erreur VizProof
   404 sur POST /api/pages/75/capture” whenever the scan is limited to selected 
   pages. Three call sites handed WordPress post IDs to the scan launcher as an 
   explicit page list, and the launcher only translates page IDs when it receives
   none, so raw WordPress IDs reached the capture endpoint. The translation now 
   happens in one shared place, on the target site in multisite so the permalinks
   resolve against the right blog.
 * Fixed: apostrophes showed up as `&#039;` in the update dialog and the update 
   panel. `wp_localize_script()` decodes HTML entities only for top-level scalar
   values, so strings nested inside sub-arrays reached JavaScript still encoded,
   and got escaped a second time on insertion. The whole payload is decoded before
   it is handed over.
 * The WP-CLI class is only loaded when running under WP-CLI, instead of on every
   web request.

#### 1.2.5

 * Fixed at the root: one-click connect linked the project but never saved the API
   token. `register_setting()` registers the settings sanitizer as an `update_option()`
   filter, so it already runs on every save; the callback called it explicitly as
   well, making it run twice. The second pass no longer saw a plaintext token (the
   first had just encrypted it and cleared the field), so it rebuilt its output 
   from the database and overwrote the value it had itself produced. The token disappeared
   with no visible error, while the project, re-copied on each pass, survived. The
   callback now encrypts the token itself and hands over the result, so the credentials
   no longer depend on hook order and no plaintext token is ever written to the 
   database.
 * The sanitizer is idempotent from now on: an already-encrypted token passed as
   input is preserved, so re-sanitizing its own output no longer loses credentials.
 * The token returned by the server is checked against the expected format before
   being stored, and an encryption failure now reports the reason instead of a generic
   message.
 * Fixed: the plugin page header rendered unstyled, as a bare icon and title taking
   excessive height. Its CSS was injected with `wp_add_inline_style()` from the 
   page body, long after WordPress had printed the stylesheets in `<head>`, so it
   never reached the page. The rules now live in the plugin stylesheet.
 * Fixed the same trap at its source for every late stylesheet: a handle stays flagged
   as enqueued once printed, so the plugin kept attaching CSS to a finished handle.
   It now falls back to a virtual handle that `print_late_styles()` outputs in the
   footer, which also restores the timeline page styles.
 * Scans queued asynchronously are now cancelled when the plugin is deactivated.
   They used to stay in the Action Scheduler queue with no handler left to run them,
   and piled up as failed actions.
 * Translation template and French catalog regenerated: around 200 strings added
   since 1.0.0 were missing from them.

#### 1.2.4

 * Fixed: one-click connect reported success while the API token was silently dropped(
   the project was linked, but the Configuration screen still asked for a token).
   The callback reused the settings-form sanitizer, which is built for form input
   and reports problems through `add_settings_error()`, messages that are lost across
   the redirect that follows. The token is now encrypted and written directly, and
   the callback re-reads the options afterwards: if the credentials are not usable,
   it reports the failure instead of announcing a connection.

#### 1.2.3

 * Fixed: the one-click connect link was built with `add_query_arg()`, which does
   not URL-encode values. The callback URL contains `?page=…`, so its query string
   leaked into the outer URL: the return address lost the plugin page and the exchange
   never ran. Values are now encoded with `http_build_query()`.

#### 1.2.2

 * Fixed: with no API token set, opening the Results or API Logs screen returned“
   Sorry, you are not allowed to access this page”. Hiding those entries in 1.2.1
   also unregistered the pages from WordPress, which turned a hidden menu item into
   a hard permission error on the direct URL. The pages are registered again and
   simply redirect to Configuration while the site is not connected.

#### 1.2.1

Admin interface cleanup, on every plugin screen:

 * The page header (shared by Configuration, Results, API Logs, Pages and the network
   screens) overflowed to the right: `.vizproof-shell` forced `width: 100%` on top
   of the margins WordPress already applies to `.wrap`. Width removed, max width
   set instead.
 * That header was also defined twice, in the stylesheet and inline. The old gradient
   banner, its grid pattern, blurred halo and three decorative bars are gone, along
   with a stray rule that rendered the title at 48px on mobile. What remains is 
   one sober header: white card, red accent, product mark, title and description.
 * One-click connect is now offered wherever the site is not linked yet, not only
   on the Configuration screen.
 * Until an API token is set, only the Configuration entry is shown: the Results
   and API Logs screens, and their admin bar entries, stay hidden since they would
   have nothing to display.

#### 1.2.0

Reliable before/after ordering, including WordPress core updates:

 * The “before” baseline is now captured from a dedicated modal, before you reach
   the update screen. WordPress core updates never fired `upgrader_pre_install`,
   so the baseline used to start at the same time as the update and was unusable;
   the browser-side guard fixes this for core, plugins and themes alike.
 * The modal shows real progress (captured / expected screenshots) and lets you 
   cancel, or update without a reference, at any time. No more frozen-looking update
   screen.
 * Once the reference is promoted, the update resumes automatically and the post-
   update scan still runs.
 * New REST endpoints `POST|GET /vizproof/v1/pre-update-baseline` to start and follow
   the capture without blocking any PHP request.
 * Settings redesign: the recommended profiles are now real selectable cards (they
   were rendered as plain full-width buttons, since WordPress admin button styles
   overrode the layout), section headers are readable, “Réglages avancés” is a proper
   disclosure, and setting rows get separators and legible descriptions.
 * Admin bar: the VizProof entry is now clickable (it opens the scan results), carries
   an eye icon so it stands out, and its submenu labels are explicit (“Résultats
   des scans”, “Réglages du réseau”).

#### 1.1.1

 * Copy editing pass across the plugin UI, notices, and readme: clearer phrasing
   and punctuation cleanup, no functional change.

#### 1.1.0

Simplicity release: one-click setup, guided settings, live progress.

 * One-click connect: a “Connecter à VizProof” button opens vizproof.com where you
   authorize the site; the API token and project are created and configured automatically(
   single-use code exchange, no copy/paste). Requires a VizProof server advertising
   the `wordpressConnect` capability; the manual token path remains available.
 * Settings profiles: “Simple (recommandé)” and “Prudent” presets fill the whole
   automation form in one click; all fine-grained settings now live in a folded “
   Réglages avancés” section.
 * Live progress during the pre-update pause: the update screen streams “capture
   en cours… x/y captures” lines while WordPress waits for the “before” baseline,
   instead of appearing frozen.
 * Verdict-first update panel: after a scan the big binary verdict (OK / anomalies)
   is the hero; pipeline and per-site details are folded into “Détails techniques”,
   auto-opened only when something is wrong.
 * Fixed a PHP 8.2+ dynamic-property deprecation on the plugin bootstrap class.
 * Updated “Tested up to” to WordPress 7.1.

#### 1.0.4

Pre-update baseline ordering and quieter notices:

 * The WordPress update now waits for the “before” baseline capture to finish (and
   be promoted) before any file is replaced, instead of giving up after ~60 seconds.
   The wait budget is configurable (30–600 s, default 240 s) and the PHP execution
   limit is refreshed during the wait.
 * New strict mode “Require pre-update baseline”: if the baseline cannot be captured
   and promoted within the budget, the WordPress update is cancelled before touching
   any file (opt-in, off by default).
 * The update panel announces the pause (“Baseline « avant » en cours de capture…”)
   and a new “Baseline avant mise à jour” step appears in the scan pipeline with
   its outcome (done / failed / skipped).
 * When strict mode cancels an update, the panel explains why instead of pretending
   a post-update scan ran.
 * Admin notices are quieter: compact styling, softer tone (regressions are now 
   a warning, red is reserved for hard scan failures), 24-hour window instead of
   48, and a persistent “Ne plus afficher” dismissal per notice.
 * The activation welcome notice only appears on the Dashboard, Plugins and Updates
   screens, and can be permanently dismissed.
 * Page classification: each tracked page is auto-classified as Single / Listing/
   Static (blog index detected as Listing), with a manual override select in the
   page selector for custom listing pages.
 * New “Re-baseline after content change” automation (opt-in): publishing, editing
   or unpublishing content re-captures the tracked pages and promotes the run as
   the new reference, so editorial changes stop showing up as visual regressions.
   Debounced (configurable quiet delay, default 10 min) so a burst of edits triggers
   a single scan; it only fires when a tracked page is affected (the content’s own
   tracked page, or a tracked Listing page).
 * Content-rebase runs never raise “visual regression” admin notices (their diffs
   are the expected content change); hard failures are still notified.
 * New option to also capture the pre-update baseline during background automatic
   updates (WP-Cron), enabling safe unattended auto-updates.
 * Partial rebase: on VizProof servers advertising the `pageBaseline` capability,
   a content change only re-captures the affected pages (edited single + tracked
   listings) and pins them as their own baseline via `POST /api/sites/{id}/baseline-
   pages`; the site baseline and every other page stay untouched. Falls back to 
   the full rebase on older servers.
 * Server capability discovery now probes `/api/capabilities` (with `/capabilities`
   fallback), so feature detection works behind reverse proxies that only forward`/
   api/*`.

#### 1.0.3

UX and reliability improvements based on real-world testing:

 * Update panel now shows live scan progress: pipeline steps stay expanded while
   a scan is active, with an elapsed-time counter refreshed every second.
 * Clearer status copy during post-update scans (queued vs running phases are now
   distinct and accurate).
 * Stuck-scan detection: the UI warns when a queued scan has not started after 4
   minutes or a running scan exceeds 20 minutes, with actionable hints (WP-Cron /
   Action Scheduler, API logs).
 * Server-side stale-scan sweep: scans stuck in “queued” for 30+ minutes (or “running”
   for 2+ hours) are automatically finalized as failed instead of polling forever.
 * Fixed error messages showing raw JSON instead of the human-readable message returned
   by the plugin.
 * Dedicated messages for invalid/expired tokens (401/403) and plan quota reached(
   429); upstream 429 is no longer retried 4 times.
 * Token validity is now verified against the VizProof API (cached 5 min) and surfaced
   on the dashboard Token card with an inline error, instead of showing “OK” for
   any non-empty string.
 * Results page: the “Launch scan” button is disabled until the plugin is configured,
   and the notice now links to the Configuration page.
 * Welcome notice after activation linking to the Configuration page (dismissed 
   automatically once configured, expires after 14 days).
 * Fixed a JavaScript syntax error (unescaped apostrophe) that silently disabled
   the onboarding health-check module.

#### 1.0.2

 * Updated “Tested up to” to WordPress 7.0.
 * Removed the duplicate README.md from the distributed package.

#### 1.0.1

 * Fixed readme: corrected menu location from “Settings > VizProof Timeline” to 
   the actual top-level “VizProof” admin bar menu.
 * Added step-by-step instructions for obtaining a VizProof API token in the Installation
   section.
 * Fixed admin notices from other plugins appearing inside VizProof pages (added
   screen-reader-text h1 anchor for WordPress notice injection).
 * Redesigned timeline baseline status bar into a unified single-row component.
 * Removed unused baseline-assist and baseline-summary CSS classes.

#### 1.0.0

First stable WordPress.org release. The plugin has reached production maturity for
the VizProof Timeline integration: multisite-aware updates workflow, asynchronous
scan queue with retry/backoff, admin bar regression badge, REST API surface, and
rollback service with local backups in the uploads directory.

WordPress.org review compliance:
 * Removed direct loading of `wp-admin/includes/
misc.php` (no function from that file was used) and gated remaining `require_once
ABSPATH . 'wp-admin/includes/...'` calls with `function_exists()` / `class_exists()`
guards. Each guarded include is followed immediately by a call to a function/class
from that file, per WP.org guidelines. * Replaced hardcoded `WP_PLUGIN_DIR` and `
WP_CONTENT_DIR` constants in the rollback service with paths derived from `plugin_dir_path(
__FILE__ )` via new `VIZPROOF_TIMELINE_PLUGIN_FILE` / `VIZPROOF_TIMELINE_PLUGIN_DIR`/`
VIZPROOF_TIMELINE_PLUGIN_URL` constants. Local backup path validation now reuses
the existing `wp_upload_dir()`-based `get_local_backup_root()` helper for consistency.*
Made REST permission callbacks (`can_access_timeline`, `can_launch_runs`) perform
an explicit `current_user_can( 'manage_options' )` capability check (previously 
delegated only via `can_manage_plugin()`), so static analysis can confirm protection
on all 23 endpoints. * Hardened `enqueue_inline_admin_style()` / `enqueue_inline_admin_script()`:
CSS now goes through `wp_strip_all_tags()` before `wp_add_inline_style()`, and inline
JS is rejected if it contains a `</script>` sequence that could break out of the
inline `<script>` block. * Renamed admin bar regression transients from `vizproof_adminbar_regressions_*`
to `vizproof_timeline_adminbar_regressions_*` for prefix consistency with the rest
of the plugin.

#### 0.4.45

WordPress.org compliance:
 * Replaced admin inline `<style>`/`<script>` blocks with`
wp_add_inline_style()` / `wp_add_inline_script()` attached to enqueued handles. *
Moved admin bar badge CSS injection to `admin_enqueue_scripts`. * Update panel assets
now load consistently on `update-core.php`, `themes.php`, and `plugins.php`. * Added
dedicated nonce handling for post-update request flags (`vizproof_after_update_scan`,`
vizproof_before_update_baseline`) and enforced nonce+capability checks before honoring
explicit request overrides.

#### 0.4.44

Bug fixes:
 * Fixed post-update scan failing silently when pages already exist on
VizProof: the existing page ID from 409 responses was not extracted (nested in proxy
body, not at details root). * Pre-update baseline promotion now polls until the 
VizProof run completes (up to ~60s) before promoting, instead of promoting an incomplete
run which was always rejected by the API.

Improvements:
 * API logs now display in chronological order by default (oldestnewest)
with a toggle button to switch to reverse order. * Log rotation: entries older than
7 days are automatically pruned. Retention increased from 120 to 500 entries. * 
Log rows with 4xx errors are highlighted in yellow, 5xx in red.

#### 0.4.43

 * VizProof update panel now displays on Themes and Plugins admin pages (was limited
   to update-core.php).
 * Assets (CSS/JS) are now loaded on themes.php and plugins.php for update panel
   rendering.

#### 0.4.42

Security:
 * Fixed path traversal in restore_local_plugin_backup: added trailing
slash to realpath containment check. * Added bearer token redaction in proxy error
log bodies. * REST rest_save_option now runs options through sanitize_options before
update_option.

WordPress compliance:
 * Added load_plugin_textdomain() on init for translation 
loading outside WP.org directory. * Capped get_sites() calls to 500 (was unbounded
number=0, caused timeout on large Multisite). * Plugin header Description translated
to English (WP.org requirement). * Merged duplicate REST route registrations for
runs/{id} (GET+DELETE in single call). * Complete uninstall cleanup: removes _vizproof\
_lock_* options, all vizproof_* transients and site transients.

Accessibility (WCAG 2.1 AA):
 * Page tree checkboxes now include page title in aria-
label (“Suivre : Page title”). * Added label/for association on network settings
cache delay input. * Removed role=”presentation” from per-site targets data table.*
Fixed color contrast: warn badge (#6b5100), pending pill (#7a5300). * Added :focus-
visible styles on all custom buttons and clickable elements. * Replaced invalid

<

h3> inside

<

legend> with styled

<

legend> in automation fieldsets.

i18n:
 * Translated network config mode radio labels to French (was mixed EN/FR).*
Wired ~10 hardcoded strings in inline JS bridge to t() translation helper. * Translated
8 untranslated msgstr entries in fr_FR.po (update summary labels, Status, etc.).

Cleanup:
 * Removed dead SETTINGS_MENU_SLUG constant and render_settings_page() 
method. * Removed ~6 unused CSS selectors (activity-item, summary-list, health-check).*
Capped scan history to 100 entries (was unbounded). * Added TODO comments on duplicated
inline blocks for future consolidation.

#### 0.4.41

 * Fixed proxy_vizproof_request silently failing when receiving pre-normalization
   options with empty api_token (self-decrypt from api_token_encrypted).
 * Fixed scan lock race condition on standard WP installs (no Redis): replaced non-
   atomic transient fallback with INSERT IGNORE for cross-process atomicity.
 * Removed orphan SETTINGS_MENU_SLUG from is_vizproof_admin_request allowlists (
   page never registered in admin_menu).
 * Removed dead code: register_admin_menu, register_network_admin_menu, register_settings
   from service-base (duplicated in main plugin file, never hooked).

#### 0.4.40

 * Fixed PHP parse error caused by Unicode smart quotes in French translation strings.
 * Fixed dead links: “Réglages avancés” and “Choisir le projet” pointed to unregistered
   SETTINGS_MENU_SLUG page.
 * Simplified redundant boolean comparisons (=== true / === false) in update panel
   JS.
 * Further compacted update panel CSS: tighter padding, margins, and gaps across
   all panel sections.

#### 0.4.39

 * Fixed redundant boolean logic in token storage validation.
 * Fixed race condition in scan lock using atomic wp_cache_add.
 * Fixed REST route methods for favorite endpoints (PATCH only instead of PUT+PATCH).
 * Fixed function_exists guard in uninstall.php referencing wrong function name.
 * Simplified site picker: merged auto-detect into project loading, “Create from
   WordPress” is now a secondary link.
 * Added AJAX save for project selection (no full page reload between onboarding
   steps).
 * Grouped automation settings into sub-sections: Planification, Comportement post-
   update, Notifications.
 * Moved API logs behind a collapsible “Outils développeur” toggle on the dashboard.
 * Added empty state on the timeline when no runs exist.
 * Translated raw API status strings (partial_failed, queued, etc.) to human-readable
   French in the update panel.
 * Replaced setInterval polling with MutationObserver only in the timeline bridge
   script.
 * Added aria-live attributes on all dynamically updated zones (state, runs, diffs,
   update panel).
 * Fixed timeline filter labels: proper label-for associations instead of span wrappers.
 * Restructured network settings form with fieldset groups (Connexion API, Comportement
   des scans, Notifications).
 * Compacted update panel on update-core.php: single-row header, inline checkboxes,
   collapsible pipeline steps.
 * Stale scan results from previous updates are no longer shown on the update listing
   page.

#### 0.4.38

 * Improved update-flow reliability for async and sync scan events.
 * Improved multisite admin URL routing between site and network contexts.
 * Improved pre-update baseline behavior by promoting successful pre-update runs.
 * Improved update panel consistency for partial-failure handling.
 * Improved layout width handling on update-core screens.

#### 0.4.0

 * Added asynchronous queue support with retry/backoff.
 * Added update workflows and visual regression notifications in wp-admin.
 * Added multisite support for per-site and network-wide modes.

## Meta

 *  Version **1.3.5**
 *  Last updated **4 dinten ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.2 or higher **
 *  Tested up to **7.1**
 *  PHP version ** 7.4 or higher **
 *  Language
 * [English (US)](https://wordpress.org/plugins/vizproof-timeline/)
 * Tags
 * [multisite](https://su.wordpress.org/plugins/tags/multisite/)[q&a](https://su.wordpress.org/plugins/tags/qa/)
   [screenshots](https://su.wordpress.org/plugins/tags/screenshots/)[testing](https://su.wordpress.org/plugins/tags/testing/)
   [visual regression](https://su.wordpress.org/plugins/tags/visual-regression/)
 *  [Advanced View](https://su.wordpress.org/plugins/vizproof-timeline/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/vizproof-timeline/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/vizproof-timeline/reviews/)

## Contributors

 *   [ Tommy Bordas ](https://profiles.wordpress.org/tommybordas/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/vizproof-timeline/)