{"id":370553,"date":"2026-09-20T07:55:17","date_gmt":"2026-09-20T07:55:17","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/changetrace\/"},"modified":"2026-10-01T07:39:25","modified_gmt":"2026-10-01T07:39:25","slug":"changetrace","status":"publish","type":"plugin","link":"https:\/\/zgh.wordpress.org\/plugins\/changetrace\/","author":23567970,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.4.0","stable_tag":"0.4.0","tested":"7.1.2","requires":"6.2","requires_php":"8.1","requires_plugins":null,"header_name":"ChangeTrace","header_author":"ChangeTrace","header_description":"Connects your WordPress\/WooCommerce site to ChangeTrace: baseline snapshot, hourly heartbeat, a bounded event queue, change detection, and error capture (PHP fatals, JS errors, HTTP 5xx\/timeouts) with PII stripping.","assets_banners_color":"71292c","last_updated":"2026-10-01 07:39:25","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/change-trace.com","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":137,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.3.0":{"tag":"0.3.0","author":"changetrace","date":"2026-09-20 07:54:42","revision":3703996},"0.3.1":{"tag":"0.3.1","author":"changetrace","date":"2026-09-21 15:23:49","revision":3705858},"0.4.0":{"tag":"0.4.0","author":"changetrace","date":"2026-10-01 07:39:25","revision":3722588}},"upgrade_notice":{"0.4.0":"<p>Adds plugin-install, theme-update and watched-option change detection, and corrects the\ndata-collection disclosure to list WooCommerce\/EDD commerce data. Option values are never\ntransmitted. Recommended for all sites.<\/p>","0.3.1":"<p>Fixes WooCommerce\/EDD order, refund, and failed-payment tracking, which never registered\non the usual plugin load order. Recommended for all WooCommerce and EDD sites.<\/p>","0.3.0":"<p>Adds error capture (PHP, JS, HTTP) with PII stripping. No action required after upgrading.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3705858,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3705858,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon-512x512.png":{"filename":"icon-512x512.png","revision":3705858,"resolution":"512x512","location":"assets","locale":"","width":384,"height":384}},"assets_banners":{"banner-1544x500.jpg":{"filename":"banner-1544x500.jpg","revision":3705858,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-2316x750.jpg":{"filename":"banner-2316x750.jpg","revision":3705858,"resolution":"2316x750","location":"assets","locale":"","width":2316,"height":750},"banner-772x250.jpg":{"filename":"banner-772x250.jpg","revision":3705858,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.3.0","0.3.1","0.4.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3705858,"resolution":"1","location":"assets","locale":"","width":2858,"height":2404},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3705858,"resolution":"2","location":"assets","locale":"","width":2858,"height":5208},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3705858,"resolution":"3","location":"assets","locale":"","width":2858,"height":1966},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3705858,"resolution":"4","location":"assets","locale":"","width":2880,"height":1800},"screenshot-5.gif":{"filename":"screenshot-5.gif","revision":3705858,"resolution":"5","location":"assets","locale":"","width":760,"height":475},"screenshot-6.gif":{"filename":"screenshot-6.gif","revision":3705858,"resolution":"6","location":"assets","locale":"","width":900,"height":563},"screenshot-7.gif":{"filename":"screenshot-7.gif","revision":3705858,"resolution":"7","location":"assets","locale":"","width":900,"height":563}},"screenshots":[]},"plugin_section":[],"plugin_tags":[281664,29196,5603,248562,286],"plugin_category":[45,54],"plugin_contributors":[281665],"plugin_business_model":[],"class_list":["post-370553","plugin","type-plugin","status-publish","hentry","plugin_tags-change-detection","plugin_tags-error-tracking","plugin_tags-monitoring","plugin_tags-observability","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_category-security-and-spam-protection","plugin_contributors-changetrace","plugin_committers-changetrace"],"banners":{"banner":"https:\/\/ps.w.org\/changetrace\/assets\/banner-772x250.jpg?rev=3705858","banner_2x":"https:\/\/ps.w.org\/changetrace\/assets\/banner-1544x500.jpg?rev=3705858","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/changetrace\/assets\/icon-128x128.png?rev=3705858","icon_2x":"https:\/\/ps.w.org\/changetrace\/assets\/icon-256x256.png?rev=3705858","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/changetrace\/assets\/screenshot-1.png?rev=3705858","caption":""},{"src":"https:\/\/ps.w.org\/changetrace\/assets\/screenshot-2.png?rev=3705858","caption":""},{"src":"https:\/\/ps.w.org\/changetrace\/assets\/screenshot-3.png?rev=3705858","caption":""},{"src":"https:\/\/ps.w.org\/changetrace\/assets\/screenshot-4.png?rev=3705858","caption":""},{"src":"https:\/\/ps.w.org\/changetrace\/assets\/screenshot-5.gif?rev=3705858","caption":""},{"src":"https:\/\/ps.w.org\/changetrace\/assets\/screenshot-6.gif?rev=3705858","caption":""},{"src":"https:\/\/ps.w.org\/changetrace\/assets\/screenshot-7.gif?rev=3705858","caption":""}],"raw_content":"<!--section=description-->\n<p>ChangeTrace watches your WordPress and WooCommerce site for meaningful changes and\nerrors and sends them to the ChangeTrace service (a cloud dashboard at\nhttps:\/\/app.change-trace.com), where they are correlated against metrics to surface\nthe most likely cause of a movement, with evidence.<\/p>\n\n<p>This plugin is the on-site agent. It does nothing until you connect it: you paste a\nsite token generated in the ChangeTrace dashboard, and only then does the plugin begin\nsending data to the ChangeTrace API.<\/p>\n\n<p><strong>What it collects (once connected):<\/strong><\/p>\n\n<ul>\n<li>A one-time <strong>baseline snapshot<\/strong> on connect: your active plugins and theme and their\nversions, plus WordPress, PHP, and WooCommerce versions.<\/li>\n<li>An hourly <strong>heartbeat<\/strong> so the dashboard knows the site is alive.<\/li>\n<li><strong>Change detection<\/strong> \u2014 plugins installed, activated, deactivated, updated or removed;\ntheme changed or updated; WordPress core updated; PHP version changed.<\/li>\n<li><strong>Watched site options<\/strong> \u2014 a short, fixed allowlist (permalink structure, siteurl, home,\nactive plugins, template, stylesheet, blog_public, core auto-update policy, and\nWooCommerce payment gateway settings). Only the option NAME and a summary of its shape\n(type, size\/length, and a short one-way hash) are sent \u2014 never the option's value.<\/li>\n<li><strong>Error capture<\/strong> \u2014 PHP fatals\/errors (shutdown + error handler, fails silently),\nfrontend JS errors (window.onerror, unhandled rejections, failed\/5xx fetch &amp; XHR;\nsampled), and 5xx\/timeouts on WordPress's outbound HTTP and its own REST API.<\/li>\n<li><strong>Commerce activity<\/strong> \u2014 if WooCommerce or Easy Digital Downloads is active: orders,\nfailed orders, failed payments, refunds, and checkouts started\/failed. Each carries the\norder id, the amount, the store currency, the payment method and the order status. No\ncustomer names, addresses, emails or line items are collected.<\/li>\n<\/ul>\n\n<p>All error payloads are <strong>PII-stripped<\/strong> (emails, credentials, form values, card numbers)\nand size-capped before they are queued and sent. Events are held in a bounded local queue\nand sent in batches (roughly every 5 minutes) with retry\/backoff.<\/p>\n\n<p><strong>Performance:<\/strong> collection is event-driven and adds no scheduled work beyond two WP-Cron\njobs (an hourly heartbeat and a 5-minute queue flush). The queue is a single non-autoloaded\noption capped at 500 events. The plugin does not measure page speed on your server \u2014 page\nperformance is measured by ChangeTrace from outside, so nothing runs in your visitors'\nbrowsers except the small sampled JavaScript error handler.<\/p>\n\n<p><strong>A ChangeTrace account is required.<\/strong> ChangeTrace is a third-party SaaS. See the\n\"External services\" section below for exactly what is sent and where.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This plugin connects to the ChangeTrace service to send monitoring data. This connection\nis required for the plugin to do anything, and only starts after you connect the plugin\nwith a site token from the ChangeTrace dashboard.<\/p>\n\n<p><strong>Services used<\/strong><\/p>\n\n<ul>\n<li><strong>ChangeTrace API<\/strong> \u2014 https:\/\/api.change-trace.com<\/li>\n<li><strong>ChangeTrace dashboard (web app)<\/strong> \u2014 https:\/\/app.change-trace.com<\/li>\n<\/ul>\n\n<p><strong>What data is sent, and when<\/strong><\/p>\n\n<ul>\n<li>On connect (once): a baseline snapshot \u2014 your active plugins and theme with versions,\nand your WordPress, PHP, and WooCommerce versions.<\/li>\n<li>Every hour: a heartbeat (site is alive) plus your site token in the request header.<\/li>\n<li>Roughly every 5 minutes (when there is activity): a batch of events \u2014 detected changes\n(plugin\/theme\/core\/PHP\/watched options), captured errors (PHP\/JS\/HTTP), and, when\nWooCommerce or Easy Digital Downloads is active, commerce events carrying the order id,\namount, store currency, payment method and status. Error payloads are PII-stripped and\nsize-capped. Watched-option values are never sent \u2014 only the option name and a summary\nof its shape.<\/li>\n<li>On connect, your browser is sent to https:\/\/app.change-trace.com to sign in and approve\nconnecting this site.<\/li>\n<\/ul>\n\n<p>Your site token is stored on your site and only ever sent to the API as an Authorization\nheader; the API stores only a hash of it. No data is sent before you connect.<\/p>\n\n<p>This service is provided by ChangeTrace. By connecting your site you agree to their terms\nand privacy policy:<\/p>\n\n<ul>\n<li>Terms of Service: https:\/\/change-trace.com\/terms-of-service<\/li>\n<li>Privacy Policy: https:\/\/change-trace.com\/privacy-policy<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate the plugin from the Plugins screen (or upload the folder to\n   wp-content\/plugins\/).<\/li>\n<li>Open <strong>ChangeTrace<\/strong> in the admin menu.<\/li>\n<li>Create an account at https:\/\/app.change-trace.com, generate a site token (it starts\nwith <code>site_tok_<\/code>), and paste it into the connect screen.<\/li>\n<\/ol>\n\n<p>Advanced: the API, dashboard, privacy, and terms URLs can be overridden in <code>wp-config.php<\/code>\nvia <code>CHANGETRACE_API_BASE_URL<\/code>, <code>CHANGETRACE_APP_URL<\/code>, <code>CHANGETRACE_PRIVACY_URL<\/code>, and\n    CHANGETRACE_TERMS_URL, or via the matching <code>changetrace_*<\/code> filters.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20a%20changetrace%20account%3F\"><h3>Do I need a ChangeTrace account?<\/h3><\/dt>\n<dd><p>Yes. ChangeTrace is a hosted service. The plugin is the on-site agent and needs a site\ntoken from https:\/\/app.change-trace.com to do anything.<\/p><\/dd>\n<dt id=\"does%20the%20plugin%20send%20any%20data%20before%20i%20connect%20it%3F\"><h3>Does the plugin send any data before I connect it?<\/h3><\/dt>\n<dd><p>No. Nothing leaves your site until you paste a valid site token and connect. See the\n\"External services\" section for what is sent afterward.<\/p><\/dd>\n<dt id=\"is%20personal%20data%20sent%20to%20changetrace%3F\"><h3>Is personal data sent to ChangeTrace?<\/h3><\/dt>\n<dd><p>Error payloads are PII-stripped (emails, credentials, form values, card numbers) and\nsize-capped before being queued and sent. The baseline snapshot contains software\nversions and plugin\/theme names, not visitor data.<\/p>\n\n<p>Commerce events carry order totals, currency, payment method and order status, plus the\norder id \u2014 never customer names, addresses, emails, phone numbers or line items. Fields a\ncustomer typed into checkout are discarded outright rather than filtered.<\/p>\n\n<p>Watched-option values are never transmitted; only the option name and a shape summary.<\/p><\/dd>\n<dt id=\"does%20the%20plugin%20slow%20my%20site%20down%3F\"><h3>Does the plugin slow my site down?<\/h3><\/dt>\n<dd><p>Collection is event-driven and the handlers are wrapped so a collector error can never\nbreak a page, a checkout or a purchase. Work on the request path is limited to appending\nto a bounded local queue. Sending happens on WP-Cron, not during a page view. Frontend\nJavaScript error capture is sampled (about 25% of page loads, capped at 5 errors per load).<\/p>\n\n<p>The plugin does not measure page speed on your server; page performance is measured by\nChangeTrace from outside your hosting.<\/p><\/dd>\n<dt id=\"how%20do%20i%20stop%20sending%20data%3F\"><h3>How do I stop sending data?<\/h3><\/dt>\n<dd><p>Deactivate the plugin, or disconnect the site from the ChangeTrace connect screen. You\ncan also delete the plugin; it cleans up its stored token and options on uninstall.<\/p><\/dd>\n<dt id=\"can%20i%20point%20the%20plugin%20at%20a%20self-hosted%20or%20staging%20environment%3F\"><h3>Can I point the plugin at a self-hosted or staging environment?<\/h3><\/dt>\n<dd><p>Yes. Define <code>CHANGETRACE_API_BASE_URL<\/code> (and optionally <code>CHANGETRACE_APP_URL<\/code>) in\n    wp-config.php.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.4.0<\/h4>\n\n<ul>\n<li>New: plugin installs are reported as their own <code>plugin_installed<\/code> event. Previously a\nplugin that appeared on disk without being activated was absorbed silently into the\nbaseline and could never be offered as a possible cause.<\/li>\n<li>New: theme updates are detected. Only a switch to a <em>different<\/em> theme was reported\nbefore, so updating the active theme \u2014 one of the most common ways to break a site \u2014\nproduced no event at all.<\/li>\n<li>New: changes to a short, fixed allowlist of high-signal site options are reported\n(<code>option_changed<\/code>): permalink structure, siteurl, home, active plugins, template,\nstylesheet, blog_public, core auto-update policy, and WooCommerce payment gateway\nsettings. Only the option NAME and a summary of its shape (type, size\/length and a\nshort one-way hash) are sent \u2014 never the option's value, because several of these hold\nlive API keys. No other option is monitored.<\/li>\n<li>New: event types are declared in one place (<code>includes\/Support\/Event_Types.php<\/code>) and\ncompared against the ChangeTrace API's own registry by an automated check, so the\nplugin cannot ship a type the service does not understand.<\/li>\n<li>Change: readme and the connect screen now disclose WooCommerce\/EDD commerce data\n(order id, total, currency, payment method, status, refunds, checkout events), which\nthe plugin has sent since 0.2.0 but did not list. No collection behaviour changed.<\/li>\n<li>Fix: the connect screen and the suggested privacy-policy text claimed the plugin\ncollects performance metrics. It does not and never has \u2014 page performance is measured\nby ChangeTrace from outside your hosting, with nothing running in visitors' browsers.<\/li>\n<\/ul>\n\n<h4>0.3.1<\/h4>\n\n<ul>\n<li>Fix: WooCommerce and EDD event collectors did not register their hooks when the\nplugin loaded before WooCommerce\/EDD (the usual load order), so orders, refunds, and\nfailed payments were never captured. Hook registration is now deferred until\nWooCommerce\/EDD is available.<\/li>\n<li>Fix: capture WooCommerce orders at checkout placement via\n  woocommerce_checkout_order_processed and the block\/Store-API\n  woocommerce_store_api_checkout_order_processed, instead of <code>woocommerce_new_order<\/code>,\nwhich fired at draft creation on block checkout and recorded phantom orders.<\/li>\n<\/ul>\n\n<h4>0.3.0<\/h4>\n\n<ul>\n<li>Error capture: PHP fatals\/errors (shutdown + error handler, fails silently),\nfrontend JS errors (window.onerror, unhandled rejections, failed\/5xx fetch &amp; XHR;\nsampled), and 5xx\/timeouts on WordPress's outbound HTTP + own REST API.<\/li>\n<li>All error payloads are PII-stripped (emails, credentials, form values, card numbers)\nand size-capped before queuing.<\/li>\n<\/ul>\n\n<h4>0.2.0<\/h4>\n\n<ul>\n<li>Baseline snapshot (plugins, theme, WP\/PHP\/WooCommerce versions) sent once on connect.<\/li>\n<li>Bounded local event queue (drops oldest when full) with a scheduled batch sender\n(every 5 minutes) that retries with exponential backoff on failure.<\/li>\n<li>Remote config fetch (enabled modules, sampling, heartbeat interval).<\/li>\n<\/ul>\n\n<h4>0.1.0<\/h4>\n\n<ul>\n<li>Connection layer: connect screen, secure token storage, hourly heartbeat.<\/li>\n<\/ul>\n\n<h4>0.0.0<\/h4>\n\n<ul>\n<li>Initial skeleton. Boots and activates; no detectors wired up yet.<\/li>\n<\/ul>","raw_excerpt":"Detects changes and errors on your WordPress\/WooCommerce site and sends them to ChangeTrace to surface the likely cause of issues, with evidence.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/zgh.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/370553","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zgh.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/zgh.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/zgh.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=370553"}],"author":[{"embeddable":true,"href":"https:\/\/zgh.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/changetrace"}],"wp:attachment":[{"href":"https:\/\/zgh.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=370553"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/zgh.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=370553"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/zgh.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=370553"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/zgh.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=370553"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/zgh.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=370553"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/zgh.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=370553"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}