{"id":318548,"date":"2026-07-14T11:19:47","date_gmt":"2026-07-14T11:19:47","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/customer-match-list-for-google-ads\/"},"modified":"2026-07-14T11:19:36","modified_gmt":"2026-07-14T11:19:36","slug":"customer-match-list-google-ads","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/customer-match-list-google-ads\/","author":9137856,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.1.1","stable_tag":"1.1.1","tested":"7.0.1","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"Customer Match List for Google Ads","header_author":"Uprise Team","header_description":"One Google Ads Customer Match CSV per billing country, built from WooCommerce orders.","assets_banners_color":"","last_updated":"2026-07-14 11:19:36","external_support_url":"","external_repository_url":"","donate_link":"https:\/\/www.paypal.me\/eduardvd","header_plugin_uri":"","header_author_uri":"https:\/\/uprise.ro","rating":0,"author_block_rating":0,"active_installs":0,"downloads":33,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.1.1":{"tag":"1.1.1","author":"rwky","date":"2026-07-14 11:19:36"}},"upgrade_notice":{"1.1.1":"<p>Naming and documentation release; no functional changes.<\/p>","1.1.0":"<p>Feed URLs changed to end in <code>.csv<\/code> and hashing normalization was corrected \u2014 run &quot;Delete all files &amp; reset dedup&quot;, then re-run the backfill.<\/p>"},"ratings":[],"assets_icons":[],"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.1.1"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3607354,"resolution":"1","location":"assets","locale":"","width":1878,"height":1726}},"screenshots":{"1":"The admin page under WooCommerce \u2192 Marketing, showing the schedule selector, per-country URL table, and backfill controls.","2":"Backfill in progress \u2014 live progress card with orders processed, rows written and order lock.","3":"WP-CLI: <code>wp cmls status<\/code> printing the per-country breakdown."}},"plugin_section":[],"plugin_tags":[567,271475,985,456,286],"plugin_category":[45,55],"plugin_contributors":[97974],"plugin_business_model":[],"class_list":["post-318548","plugin","type-plugin","status-publish","hentry","plugin_tags-csv","plugin_tags-customer-match","plugin_tags-google-ads","plugin_tags-marketing","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_category-seo-and-marketing","plugin_contributors-rwky","plugin_committers-rwky"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/s.w.org\/plugins\/geopattern-icon\/customer-match-list-google-ads.svg","icon_2x":false,"generated":true},"screenshots":[{"src":"https:\/\/ps.w.org\/customer-match-list-google-ads\/assets\/screenshot-1.png?rev=3607354","caption":"The admin page under WooCommerce \u2192 Marketing, showing the schedule selector, per-country URL table, and backfill controls."}],"raw_content":"<!--section=description-->\n<p>This plugin builds and maintains <strong>one CSV file per billing country<\/strong> in the <strong>Google Ads Customer Match Lists<\/strong> format from your WooCommerce orders billing data. Each country file is downloadable via a private and secure (tokenized) URL \u2014 ideal for marketing teams that run per-country campaigns and want clean, single-market audience lists.<\/p>\n\n<p>The values are hashed with the same SHA-256 normalization used by both Google Ads Customer Match and Meta Ads Custom Audiences, so the same file can also be uploaded manually to Meta Ads Manager (see FAQ).<\/p>\n\n<p><strong>Why this export?<\/strong>\nNot all purchases are captured by Google Ads tracking; periodic uploads of <strong>Customer Match Lists<\/strong> help targeting and campaign performance.<\/p>\n\n<p><strong>Why per-country files?<\/strong>\nMarketing teams optimize Google Ads campaigns per country. Mixing a German audience into a Romanian campaign's match list pollutes the targeting. This plugin keeps each market in its own file.<\/p>\n\n<h4>How it works<\/h4>\n\n<ol>\n<li>A <strong>one-time backfill<\/strong> walks every completed WooCommerce order, splits them by billing country, hashes the customer fields and writes one CSV per country.<\/li>\n<li>A <strong>scheduled job<\/strong> (1, 6, 12, or 24 hours) picks up new completed orders since the last run and appends them to the right country file.<\/li>\n<li>Each country file is downloadable from a <strong>secret URL<\/strong> that you hand to your marketing team. They can paste it into <strong>Google Ads Data Manager \u2192 HTTPS connector<\/strong> and Google fetches the latest list on its schedule OR do one-time manual upload.<\/li>\n<\/ol>\n\n<h4>Features<\/h4>\n\n<ul>\n<li><strong>Per-country splitting<\/strong> \u2014 one CSV per ISO billing country, never mixed.<\/li>\n<li><strong>Background backfill from the admin<\/strong> (no CLI needed) \u2014 runs via Action Scheduler.<\/li>\n<li><strong>One-time backfill via WP-CLI<\/strong> with status filter, date filter (<code>--days=N<\/code>, <code>--since<\/code>, <code>--until<\/code>), dry-run, and batch-size control.<\/li>\n<li><strong>Scheduled incremental appends<\/strong> every 1, 6, 12, or 24 hours.<\/li>\n<li><strong>Per-(email, country) deduplication<\/strong> via a dedicated indexed database table \u2014 no full-file scans, single indexed insert per row.<\/li>\n<li><strong>CSV exported columns headers<\/strong>: <code>Email, Phone, First Name, Last Name, Country, Zip<\/code>.<\/li>\n<li><strong>Hashed per Google spec<\/strong>: SHA-256 of trimmed\/lowercased values, phone normalized to E.164 with the leading <code>+<\/code> \u2014 the same hashing Meta Ads Custom Audiences accept.<\/li>\n<li><strong>Secret tokenized URLs<\/strong> \u2014 one per country, all resettable from the admin or via CLI.<\/li>\n<li><strong>Storage hardening<\/strong> \u2014 files live under <code>wp-content\/uploads\/customer-match-list-google-ads\/<\/code> with filenames containing a 64-bit hash derived from the token.<\/li>\n<li><strong>REST endpoint stream<\/strong> \u2014 the CSV is sent chunked with <code>nocache_headers()<\/code>.<\/li>\n<li><strong>HPOS-first SQL<\/strong> \u2014 direct <code>JOIN<\/code> on <code>wc_orders<\/code> + <code>wc_order_addresses<\/code> (or <code>posts<\/code>+<code>postmeta<\/code> on classic). <strong>Designed for stores with tens of millions of orders.<\/strong><\/li>\n<\/ul>\n\n<h4>Admin Dashboard Settings<\/h4>\n\n<p><strong>WooCommerce \u2192 Marketing \u2192 Customer Match List<\/strong>.<\/p>\n\n<p>From there you can:<\/p>\n\n<ul>\n<li>Pick the cron interval (1\/6\/12\/24 h).<\/li>\n<li>See the access token; reset it (regenerates every URL, renames every file).<\/li>\n<li>See per-country status: row count, file size, and the tokenized URL ready to copy.<\/li>\n<li>Start a background backfill with a date-range preset.<\/li>\n<li>Watch backfill progress live (orders processed, rows written, rows skipped, watermark).<\/li>\n<li>Delete every country file and reset the dedup table.<\/li>\n<li>Do an automated check that confirms the webserver does not expose the CSV directory via a public file listing.<\/li>\n<\/ul>\n\n<h4>WP-CLI<\/h4>\n\n<ul>\n<li><code>wp cmls backfill<\/code> \u2014 one-time backfill of historical orders, split by country. Flags: <code>--statuses=completed<\/code> (default), <code>--all-statuses<\/code>, <code>--days=N<\/code>, <code>--since=YYYY-MM-DD<\/code>, <code>--until=YYYY-MM-DD<\/code>, <code>--dry-run<\/code>, <code>--batch-size=5000<\/code>, <code>--force<\/code>.<\/li>\n<li><code>wp cmls run-now<\/code> \u2014 runs the incremental writer immediately (same code path as the scheduled cron).<\/li>\n<li><code>wp cmls status<\/code> \u2014 prints a table with one row per country: row count, file size, URL.<\/li>\n<li><code>wp cmls reset-token<\/code> \u2014 regenerates the token and renames every country file to match.<\/li>\n<li><code>wp cmls delete-file<\/code> \u2014 deletes every country CSV and truncates the dedup table.<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin folder to <code>wp-content\/plugins\/customer-match-list-google-ads<\/code> (or install from the WordPress.org repository).<\/li>\n<li>Activate <strong>Customer Match List for Google Ads<\/strong>. WooCommerce must already be active.<\/li>\n<li>Go to <strong>WooCommerce \u2192 Marketing \u2192 Customer Match List<\/strong>.<\/li>\n<li>Pick an update interval (1, 6, 12, or 24 hours).<\/li>\n<li>Run the backfill:\n\n<ul>\n<li><strong>From the admin<\/strong> \u2014 pick a date range under \"Backfill\", click \"Start backfill\", and watch the progress card. You can close the tab; it keeps running.<\/li>\n<li><strong>From the shell<\/strong> \u2014 <code>wp cmls backfill --days=540<\/code> (or any range that suits you).<\/li>\n<\/ul><\/li>\n<li>After the first backfill finishes, the \"Download URLs\" table shows one URL per country. Copy each URL and paste it into Google Ads Data Manager \u2192 HTTPS connector for the corresponding country's Customer Match list.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"why%20one%20file%20per%20country%3F\"><h3>Why one file per country?<\/h3><\/dt>\n<dd><p>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.<\/p><\/dd>\n<dt id=\"how%20do%20i%20plug%20a%20url%20into%20google%20ads%3F\"><h3>How do I plug a URL into Google Ads?<\/h3><\/dt>\n<dd><p>In Google Ads \u2192 <strong>Tools and Settings<\/strong> \u2192 <strong>Audience Manager<\/strong> \u2192 <strong>Your data sources<\/strong>, set up a <strong>Customer Match<\/strong> audience and choose the <strong>HTTPS<\/strong> data source. 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.<\/p><\/dd>\n<dt id=\"does%20the%20file%20work%20with%20meta%20%28facebook%29%20ads%3F\"><h3>Does the file work with Meta (Facebook) Ads?<\/h3><\/dt>\n<dd><p>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 \u2014 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.<\/p><\/dd>\n<dt id=\"how%20long%20does%20the%20backfill%20take%3F\"><h3>How long does the backfill take?<\/h3><\/dt>\n<dd><p>Roughly 10 seconds per 150,000\u2013200,000 orders on typical hardware. The query path is direct SQL against <code>wc_orders<\/code> + <code>wc_order_addresses<\/code> (HPOS).\nFor 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.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20orders%20with%20no%20billing%20country%3F\"><h3>What happens to orders with no billing country?<\/h3><\/dt>\n<dd><p>In theory it's impossible as billing and shipping is country based; but in case this ever happens they are 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.<\/p><\/dd>\n<dt id=\"what%20about%20orders%20with%20no%20email%3F\"><h3>What about orders with no email?<\/h3><\/dt>\n<dd><p>They get written. Google Customer Match accepts a row with <strong>any one<\/strong> 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.<\/p>\n\n<p>Google handles cross-identifier deduplication on its side after matching to a Google account \u2014 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.<\/p><\/dd>\n<dt id=\"will%20the%20same%20customer%20appear%20in%20multiple%20country%20files%3F\"><h3>Will the same customer appear in multiple country files?<\/h3><\/dt>\n<dd><p>Yes \u2014 but only if they actually ordered from multiple countries!<\/p><\/dd>\n<dt id=\"i%20ran%20the%20backfill%20twice%20%E2%80%94%20why%20didn%27t%20it%20write%20more%20rows%20the%20second%20time%3F\"><h3>I ran the backfill twice \u2014 why didn't it write more rows the second time?<\/h3><\/dt>\n<dd><p>This is by design, as every <code>(email, country)<\/code> pair is recorded the first time it's seen and never re-written.<\/p>\n\n<p>To regenerate from scratch (for example after toggling debug mode or changing normalization), use <strong>WooCommerce \u2192 Marketing \u2192 Customer Match List \u2192 Danger zone \u2192 Delete all files &amp; reset dedup<\/strong> or <code>wp cmls delete-file<\/code>, then run the backfill again.<\/p><\/dd>\n<dt id=\"i%20get%20a%20401%20%22rest%20api%20has%20been%20restricted%20to%20authenticated%20users%22%20when%20i%20open%20the%20url\"><h3>I get a 401 \"REST API has been restricted to authenticated users\" when I open the URL<\/h3><\/dt>\n<dd><p>Some security plugins (\"Admin and Site Enhancements\" \/ ASE has this option, Disable REST API, etc.) block all unauthenticated REST traffic. This plugin does <strong>not<\/strong> attempt to override those policies \u2014 that would be hostile to the security setting you deliberately chose.<\/p>\n\n<p>If you hit this error, whitelist the plugin's feed prefix in your security plugin's exclusion list: <code>\/wp-json\/cmls\/v1\/feed\/<\/code>. Google Ads (and any other configured consumer) needs unauthenticated GET access to that prefix \u2014 the tokenized URL is the sole authentication mechanism.<\/p><\/dd>\n<dt id=\"phone%20numbers%20%E2%80%94%20how%20reliable%20is%20the%20normalization%20without%20libphonenumber%3F\"><h3>Phone numbers \u2014 how reliable is the normalization without libphonenumber?<\/h3><\/dt>\n<dd><p>For most countries (RO, DE, UK, FR, ES, US, NL, BE, PT, IT mobile, \u2026) it's correct. The routine accepts <code>+<\/code>, <code>00<\/code>, the country's national trunk <code>0<\/code>, and bare national numbers (using the order's billing country to fill in the dialing code).<\/p>\n\n<p>There is a known limitation for <strong>Italian landlines<\/strong>: in Italy the leading <code>0<\/code> 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.<\/p>\n\n<p><strong>If you need strict accuracy across all locales, swap <code>CMLS_Writer::normalize_phone()<\/code> for a libphonenumber-based implementation.<\/strong><\/p><\/dd>\n<dt id=\"is%20wp-cron%20reliable%20enough%20for%20the%20incremental%20updates%3F\"><h3>Is WP-Cron reliable enough for the incremental updates?<\/h3><\/dt>\n<dd><p>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 <code>wp-cron.php<\/code> every minute \u2014 standard WordPress practice and recommendation.<\/p><\/dd>\n<dt id=\"can%20i%20disable%20hashing%20for%20debugging%3F\"><h3>Can I disable hashing for debugging?<\/h3><\/dt>\n<dd><p>Yes. use the integrated define <code>CMLS_DISABLE_HASHING<\/code> in <code>wp-config.php<\/code>:<\/p>\n\n<pre><code>define( 'CMLS_DISABLE_HASHING', true );\n<\/code><\/pre><\/dd>\n<dt id=\"does%20this%20support%20high-performance%20order%20storage%20%28hpos%29%20%2F%20legacy%20postmeta%3F\"><h3>Does this support High-Performance Order Storage (HPOS) \/ Legacy Postmeta?<\/h3><\/dt>\n<dd><p>Yes. The plugin declares <code>custom_order_tables<\/code> compatibility and queries <code>wc_orders<\/code> + <code>wc_order_addresses<\/code> directly when HPOS is enabled. On classic (postmeta) storage it falls back to <code>wp_posts<\/code> + <code>wp_postmeta<\/code> with a single conditional-aggregation query per batch.<\/p><\/dd>\n<dt id=\"does%20the%20plugin%20send%20any%20data%20outside%20my%20server%3F\"><h3>Does the plugin send any data outside my server?<\/h3><\/dt>\n<dd><p>The plugin itself makes <strong>no outbound HTTP calls<\/strong> \u2014 no analytics, no tracking pixels, no telemetry. All processing happens on your WordPress install.<\/p>\n\n<p>However, the whole point of the workflow is that <strong>Google Ads (or any other consumer you configure) will pull the CSV from your site<\/strong> at the tokenized URL. Anyone in possession of that URL can retrieve a file containing:<\/p>\n\n<ul>\n<li>SHA-256 hashes of the customer's email, phone, first name, and last name;<\/li>\n<li>the customer's billing country and postal code in plaintext.<\/li>\n<\/ul>\n\n<p>Treat the tokenized URL as a secret. If it leaks, use <strong>Reset Token<\/strong> in the admin (or <code>wp cmls reset-token<\/code>) to invalidate all existing URLs and rename the files on disk. See the site's Privacy Policy page \u2014 this plugin registers suggested policy text via WordPress's Privacy tool.<\/p><\/dd>\n<dt id=\"where%20are%20the%20files%20stored%3F\"><h3>Where are the files stored?<\/h3><\/dt>\n<dd><p>wp-content\/uploads\/customer-match-list-google-ads\/customer-match-{hash}-{country}.csv. The <code>{hash}<\/code> is a 16-character hex derived from the secret token, so filenames are not guessable. An <code>index.php<\/code> placeholder in the directory prevents listing if your host happens to have it enabled and then it notifies the shop owner (when visiting the dashboard).<\/p><\/dd>\n<dt id=\"what%20about%20directory%20listing%3F\"><h3>What about directory listing?<\/h3><\/dt>\n<dd><p>The settings page does a one-second loopback HTTP request to the uploads directory URL (<code>\/wp-content\/uploads\/customer-match-list-google-ads\/<\/code>) when you open it, caches the result for an hour, and shows one of three banners:<\/p>\n\n<ul>\n<li><strong>Green \u2014 safe.<\/strong> The server returned 200\/401\/403\/404 with no listing markers (typically because the bundled <code>index.php<\/code> silence file is served, or because the webserver explicitly blocks directory listings).<\/li>\n<li><strong>Red \u2014 exposed.<\/strong> The server returned 200 with <code>Index of \u2026<\/code> or with our CSV filename prefix in the body. Anyone who guesses the directory URL can enumerate your country files. Fix it: Apache \u2192 <code>Options -Indexes<\/code> (or rely on the WordPress-shipped <code>.htaccess<\/code>); nginx \u2192 <code>autoindex off;<\/code> in the relevant <code>location<\/code> block.<\/li>\n<li><strong>Yellow \u2014 could not verify.<\/strong> The loopback request failed within the one-second budget (NAT \/ split-DNS \/ firewall blocking PHP self-calls). Open the URL shown in the notice in a private\/incognito browser window \u2014 if you see a listing, restrict it; otherwise you're fine.<\/li>\n<\/ul>\n\n<p>The check is cached for an hour and re-runs immediately if you click <strong>Re-check now<\/strong>.<\/p><\/dd>\n<dt id=\"what%20about%20google%27s%20540-day%20lookback%20window%3F\"><h3>What about Google's 540-day lookback window?<\/h3><\/dt>\n<dd><p>Google Ads Customer Match uses data uploaded within the last 540 days. The plugin doesn't enforce this so you can decide how much history to include. The \"Last 540 days\" preset in the backfill range dropdown matches that window. Older data is still appended if you ask for it, but Google won't actively use it.<\/p><\/dd>\n<dt id=\"can%20i%20include%20orders%20that%20aren%27t%20%60completed%60%3F\"><h3>Can I include orders that aren't `completed`?<\/h3><\/dt>\n<dd><p>Yes. <code>wp cmls backfill --statuses=processing,completed,on-hold<\/code> for an explicit list, or <code>--all-statuses<\/code> for everything. The scheduled (incremental) writer is <code>wc-completed<\/code> only by design \u2014 Customer Match doesn't benefit from including pending or cancelled orders.<\/p><\/dd>\n<dt id=\"how%20is%20the%20deduplication%20table%20sized%3F\"><h3>How is the deduplication table sized?<\/h3><\/dt>\n<dd><p>One row per unique <code>(email_hash, country)<\/code>. At ~110 bytes per row, 1M unique customers across all countries is roughly 100 MB.<\/p><\/dd>\n<dt id=\"will%20deactivating%20woocommerce%20break%20it%3F\"><h3>Will deactivating WooCommerce break it?<\/h3><\/dt>\n<dd><p>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.<\/p>\n\n<p>If you uninstall the plugin then the <code>uninstall.php<\/code> routine cleans up the option keys, database tables, and any generated files.<\/p><\/dd>\n<dt id=\"gdpr%20%2F%20privacy\"><h3>GDPR \/ privacy<\/h3><\/dt>\n<dd><p>The files contain hashed personal information (email, phone, name) and plaintext country + ZIP. Treat the directory and its access URLs as sensitive data! If a customer requests deletion under GDPR \/ similar:<\/p>\n\n<ol>\n<li>Delete or anonymize the WooCommerce order(s).<\/li>\n<li>Run <strong>Danger zone \u2192 Delete all files &amp; reset dedup<\/strong> (or <code>wp cmls delete-file<\/code>).<\/li>\n<li>Re-run the backfill \u2014 the deleted customer is gone from the files.<\/li>\n<\/ol>\n\n<p>Targeted per-row deletion isn't supported on purpose: the SHA-256 hashing is one-way and rebuilding from source is fast.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.1.1<\/h4>\n\n<ul>\n<li>Consistent plugin name: \"Customer Match List for Google Ads\". The exported files also work for Meta Ads Custom Audiences (see FAQ) \u2014 same hashing.<\/li>\n<li>Confirmed compatibility with WooCommerce 10.9.<\/li>\n<li>Readme and documentation cleanup. No functional changes.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Feed URLs now end in <code>.csv<\/code> so Google Ads' HTTPS connector accepts them.<\/li>\n<li>Hashing normalization aligned with the Google Customer Match spec (Unicode-aware lowercase, name punctuation stripping, US ZIP truncation, double-hash guard).<\/li>\n<li>Fresh activations no longer sweep historical orders \u2014 backfill is explicit (admin button or WP-CLI).<\/li>\n<li>Admin JS moved into enqueued, page-scoped files.<\/li>\n<li>Added suggested privacy-policy text, sub-100-row serving warning, CSV-injection hardening on zip values, and removed the REST authentication override.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release: per-country CSVs with <code>(identity, country)<\/code> dedup, WP-CLI and Action Scheduler backfills, tokenized REST download endpoint, HPOS-first SQL.<\/li>\n<\/ul>","raw_excerpt":"WooCommerce to Google Ads Customer Match CSV exporter. Per-country lists, scheduled\/WP-CLI backfills, secure URLs. Files also work for Meta Ads.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/318548","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=318548"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/rwky"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=318548"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=318548"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=318548"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=318548"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=318548"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=318548"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}