| 开发者 | rwky |
|---|---|
| 更新时间 | 2026年10月21日 03:48 |
| 捐献地址: | 去捐款 |
| PHP版本: | 7.4 及以上 |
| WordPress版本: | 7.1 |
| 版权: | GPLv2 or later |
| 版权网址: | 版权信息 |
--days=N, --since, --until), dry-run, and batch-size control.Email, Phone, First Name, Last Name, Country, Zip.+ — the same hashing Meta Ads Custom Audiences accept.wp-content/uploads/customer-match-list-google-ads/ with filenames containing a 64-bit hash derived from the token, behind a deny-all .htaccess on Apache.nocache_headers().JOIN on wc_orders + wc_order_addresses (or posts+postmeta on classic). Designed for stores with tens of millions of orders.wp cmls rebuild (or wp cmls rebuild-now) — rebuilds every file from the orders inside the audience window and swaps them in, in the same process (no PHP time limit). Same result as the nightly rebuild and Tools → Rebuild now.wp cmls backfill — one-time backfill of historical orders, split by country. Flags: --statuses=processing,completed (defaults to the statuses saved in the settings), --all-statuses, --days=N, --since=YYYY-MM-DD, --until=YYYY-MM-DD, --dry-run, --batch-size=5000, --force. The next rebuild goes back to the saved window and statuses.wp cmls update-now (or wp cmls run-now) — appends orders placed since the last run, right away. Same code path as the scheduled cron and Tools → Update now.wp cmls status — prints a table with one row per country (row count, file size, URL) and the all-countries URL when it's on, then the audience window, statuses and rebuild times.wp cmls reset-token — regenerates the token and renames every file to match. If a file can't be renamed, nothing changes and the command fails.wp cmls delete-file — deletes every country CSV and truncates the dedup table.wp-content/plugins/customer-match-list-google-ads (or install from the WordPress.org repository).wp cmls rebuild.Marketing teams optimize Google Ads campaigns per country. Mixing audiences degrades match-rate signals and wastes budget on irrelevant impressions. Each country file is independent and can be wired into its own Customer Match list. Google's Data Manager pulls each URL on its own schedule, so you can refresh some markets without affecting others.
Yes. On the Settings tab, tick Also offer one file with every country. The Feeds tab then lists an extra URL ending in /all.csv, after the country URLs. It holds the rows of every country file together, under one header, so it's always in step with them. A customer who ordered from two countries appears once per country, as in the country files.
In Google Ads → Tools → Shared library → Audience manager, click + Create remarketing list → + Customer list and connect the HTTPS data source (step by step under "How do I add value segment URLs in Google Ads?" below; country URLs work the same way). Paste the country-specific URL from the plugin's admin page. Google Ads fetches the file on its own cadence; our plugin keeps the file fresh per the schedule you picked.
Yes — they complement each other. In 2026 Google began automatically enrolling accounts that use both Enhanced Conversions and Customer Match into conversion-based customer lists (enrollment emails went out from June 2026; data processing starts August 18, 2026). Those lists are built solely from what the Google Ads tag captures on your site from that point on: customers using ad blockers or declining your consent banner never enter them, and neither do phone, imported, or historical orders. This plugin builds Customer Match lists from the WooCommerce order database instead — every completed order, including full order history via backfill, split into one file per country, with a mailing-address fallback when an order has no email or phone. Keep both: attach the automatic conversion-based lists and the per-country lists this plugin feeds, and Google deduplicates matched customers on its side.
Yes. Meta Ads Custom Audiences use the same SHA-256 hashing of normalized (trimmed, lowercased) values, so a country CSV can be uploaded to Meta Ads Manager as a customer list — map the columns in Meta's upload screen. Note that Meta does not pull files from URLs; the pull-from-URL workflow is Google-specific, so on Meta use manual upload.
Roughly 10 seconds per 150,000–200,000 orders on typical hardware. The query path is direct SQL against wc_orders + wc_order_addresses (HPOS).
For 1M+ orders the CLI is still the most reliable option because no PHP/web timeout applies; the admin Action-Scheduler-backed runner also handles 1M+ but each batch must complete within the host's PHP limit and if it does not then it won't finish.
It shouldn't happen, since WooCommerce billing and shipping addresses are country-based, but if it does, the order is skipped. There is no correct file to route them to, and Google's per-country Customer Match campaigns can't use them anyway. The same applies to orders with an invalid country code.
They get written. Google Customer Match accepts a row with any one of: email, phone, or full mailing address (first name + last name + zip). The plugin includes a row as long as one of those identifiers is present alongside a valid country. Deduplication is still single-column: it uses email when available, otherwise phone, otherwise the mailing address. Google handles cross-identifier deduplication on its side after matching to a Google account — so a customer who orders once with email + phone and again with only their phone will appear as two rows in the CSV but as one user in your Customer Match audience.
Yes — but only if they actually ordered from multiple countries!
This is by design, as every (email, country) pair is recorded the first time it's seen and never re-written.
To regenerate everything from scratch (for example after toggling debug mode), click Tools → Rebuild now or run wp cmls rebuild. The rebuild starts from empty files and swaps them in when it's done; the URLs stay the same.
Your site uses plain permalinks (Settings → Permalinks → Plain), so WordPress builds REST URLs with a query string. Google Ads rejects feed URLs with a query string, and the plugin shows a warning at the top of its page and on the Health tab. Pick any other permalink structure; the URLs then end in .csv. Update the URLs in Google Ads afterwards.
Some security plugins ("Admin and Site Enhancements" / ASE has this option, Disable REST API, etc.) block all unauthenticated REST traffic. This plugin does not attempt to override those policies — that would be hostile to the security setting you deliberately chose.
If you hit this error, whitelist the plugin's feed prefix in your security plugin's exclusion list: /wp-json/cmls/v1/feed/. Google Ads (and any other configured consumer) needs unauthenticated GET access to that prefix — the tokenized URL is the sole authentication mechanism.
For most countries (RO, DE, UK, FR, ES, US, NL, BE, PT, IT mobile, …) it's correct. The routine accepts +, 00, the country's national trunk 0, and bare national numbers (using the order's billing country to fill in the dialing code).
A number typed without + or 00 but starting with the dialing code's digits is read as already international. For countries whose numbers have a fixed length (India, Brazil, Norway, Poland, Singapore, Kazakhstan and 29 more) the plugin checks the length first, so an Indian mobile like 9123456789 becomes +919123456789, not +9123456789. Countries with variable-length numbers (Germany, Austria, Italy, Finland, …) keep the simpler rule.
There is a known limitation for Italian landlines: in Italy the leading 0 is part of the national number, not a trunk prefix, so the routine may strip a digit it shouldn't. Italian mobile numbers (3xx) are fine.
If you need strict accuracy across all locales, swap CMLS_Writer::normalize_phone() for a libphonenumber-based implementation.
WordPress's built-in cron is request-triggered: it only fires if someone hits the site. On low-traffic stores it may drift. For predictable runs, configure a real system cron that calls wp-cron.php every minute — standard WordPress practice and recommendation.
Yes. Add the CMLS_DISABLE_HASHING define to wp-config.php:
define( 'CMLS_DISABLE_HASHING', true );
Yes. The plugin declares custom_order_tables compatibility and queries wc_orders + wc_order_addresses directly when HPOS is enabled. On classic (postmeta) storage it falls back to wp_posts + wp_postmeta with a single conditional-aggregation query per batch.
The plugin makes no requests to third-party services — no analytics, no tracking pixels, no telemetry. All processing happens on your WordPress install. (The directory-listing safety check is a one-second request from your server to its own uploads URL — see the directory-listing FAQ.) However, the whole point of the workflow is that Google Ads (or any other consumer you configure) will pull the CSV from your site at the tokenized URL. Anyone in possession of that URL can retrieve a file containing:
wp cmls reset-token) to invalidate all existing URLs and rename the files on disk. See the site's Privacy Policy page — this plugin registers suggested policy text via WordPress's Privacy tool.
wp-content/uploads/customer-match-list-google-ads/customer-match-{hash}-{country}.csv, and customer-match-{hash}-seg-{id}.csv for value segments. During a rebuild the new files are written next to them with a .build suffix. The {hash} is a 16-character hex derived from the secret token, so filenames are not guessable. An index.php placeholder prevents listing if your host happens to have it enabled, and a deny-all .htaccess stops Apache from serving the files directly: the tokenized URLs read them through WordPress instead. nginx ignores .htaccess; there the unguessable names protect the files, or add location ^~ /wp-content/uploads/customer-match-list-google-ads/ { deny all; } to your server block. The all-countries file isn't stored: it's put together from the country files when Google fetches it.
The settings page does a one-second loopback HTTP request to the uploads directory URL (/wp-content/uploads/customer-match-list-google-ads/) when you open it, caches the result for an hour, and shows one of three banners:
.htaccess denies access, the bundled index.php silence file is served, or the webserver explicitly blocks directory listings).Index of … or with our CSV filename prefix in the body. Anyone who guesses the directory URL can enumerate your country files. Fix it: Apache → Options -Indexes (or rely on the WordPress-shipped .htaccess); nginx → autoindex off; in the relevant location block.Google Ads keeps a Customer Match member for up to 540 days after that member was last uploaded or refreshed. Every time Google fetches your file, everyone in it is uploaded again, so a customer stays in the audience for as long as they are in the file, however old their orders are. That's what the audience window (Settings tab) is for. Every night the files are rebuilt from the orders inside the window, so a customer whose last order is older drops out of the file. Google then stops refreshing them, and they leave the audience at the latest 540 days after the last fetch that included them. New installs start at 540 days; pick "All orders" to keep everyone. The backfill date range only limits the initial history import; the audience window is what keeps the list trimmed afterwards. Sites upgraded from 1.x keep their current files, which only ever grow, until the settings are saved once. Saving turns on the nightly rebuild with the window you chose.
completed?Yes. On the Settings tab, Order statuses lists every status, including custom ones added by other plugins (for example "Shipped"). Shortcuts pick Completed only, every paid status, or everything. The scheduled writer, the late-status hook, the admin backfill and the nightly rebuild all use your selection.
The page warns you when you select a status where the customer hasn't paid (pending payment, on hold, failed, cancelled, refunded): those customers didn't buy, and failed orders often come from bots testing stolen cards.
When an order leaves your selection (for example Completed → Refunded), the customer is removed at the next nightly rebuild, unless another of their orders still qualifies.
For a one-off run with other statuses, use wp cmls backfill --statuses=processing,completed,on-hold or --all-statuses.
Extra files that hold only some of your customers, each with its own URL to add in Google Ads as a separate Customer Match list. Turn them on under Value segments, then add up to 5 segments from a template or your own rules:
Each segment URL is its own Customer Match list in Google Ads. Segment files are created at the nightly rebuild; click Tools → Rebuild now after adding a segment if you don't want to wait. The URLs are on the Feeds tab under Value segment URLs: one per segment, or one per segment and country if you split them by country. For each URL:
One row per unique (email_hash, country). At ~110 bytes per row, 1M unique customers across all countries is roughly 100 MB. While a rebuild runs, a second copy is filled next to it (plus a per-customer totals table when value segments are on), so plan for about twice that during the rebuild. The spare copies are emptied when it finishes.
Yes, activated per site: each site gets its own token, files, tables and schedule. Activate it from each site's Plugins screen; network activation is refused, because the setup has to run on every site. If an older version was network-activated, network-deactivate it and activate it per site. Uninstalling cleans up every site.
The plugin's admin page shows a notice and stops scheduling cron, but data isn't lost. Re-activate WC and the plugin resumes from the noted order.
If you uninstall the plugin then the uninstall.php routine cleans up the option keys, database tables, and any generated files.
The files contain hashed personal information (email, phone, name) and plaintext country + ZIP. Treat the directory and its access URLs as sensitive data! The plugin only creates files on your own server and does not read consent-management records: every order in the selected range is exported as-is. Whether a given customer may be included in an advertising audience — and whether Google or Meta may receive the file — depends on your store's consent setup and local legal requirements; applying them is your responsibility as the data controller. If a customer requests deletion under GDPR / similar:
wp cmls rebuild) — the deleted customer is gone from every file, value segments included./all.csv with every country together (Settings tab).wp cmls update-now and wp cmls rebuild-now, matching the admin buttons.wp cmls run-now, reset-token and delete-file now work under the names the readme documents; the underscore names keep working.wp plugin activate no longer fails with WP_DEBUG display on..htaccess in the storage folder, a download name that doesn't reveal the file name on disk, and the feed routes are no longer listed in the REST API index.wp cmls rebuild.wp cmls rebuild; wp cmls backfill now defaults to the statuses saved in the settings; wp cmls status also shows the audience window, statuses and rebuild times..csv so Google Ads' HTTPS connector accepts them.(identity, country) dedup, WP-CLI and Action Scheduler backfills, tokenized REST download endpoint, HPOS-first SQL.