{"id":9401,"date":"2026-08-12T18:00:00","date_gmt":"2026-08-12T16:00:00","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/?p=9401"},"modified":"2026-10-09T22:41:27","modified_gmt":"2026-10-09T20:41:27","slug":"bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4","status":"publish","type":"post","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/","title":{"rendered":"BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Two changes in the Google analytics stack became effective in June 2026. Both are documented, both are in force as of 10 August 2026, and neither announces itself while a pipeline runs. The first narrows what the BigQuery Data Transfer Service will fetch during a backfill. The second narrows what the Google Signals setting in the Analytics admin actually controls. What links them is not the subject matter but the mode of arrival: no failed job, no exception in a log, no line in a monitoring dashboard. The first surfaces when someone starts a backfill. The second surfaces when someone notices that a switch no longer produces the effect it produced before.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Two changes that took effect in June without an error message<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Most changes in a data stack announce themselves. A schema shifts and a query fails. An endpoint is retired and a client returns a status code. A quota tightens and a job stops. Those changes are noisy, and the noise is what makes them cheap to handle: the monitoring that already exists catches them, and someone reads the message.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The two June changes belong to a different category. In both cases the system keeps working. Jobs complete, settings can still be toggled, dashboards still render. The change shows up only in the content of the data or in the meaning of a configuration value, and neither of those is covered by the usual alerting.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>BigQuery Data Transfer Service:<\/strong> since 1 June 2026 the connectors for Google Ads, Search Ads 360 and Google Analytics 4 no longer populate backfill runs with data older than 37 months. The documentation states that such runs return incomplete or empty results and can overwrite existing complete history.<\/li>\n<li><strong>Google Signals:<\/strong> from 15 June 2026 the Google Signals setting in the Analytics admin and the Google Signals API control only the association of Analytics data with information from signed-in users for behavioural reporting. Control over the data itself sits with Consent Mode, specifically with the <code>ad_storage<\/code> parameter.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The rest of this article treats them as two instances of the same operational problem: a documented change whose effect becomes visible only through a deliberate check. Section 2 to 4 cover the transfer limit and a guard that can be placed in front of a backfill. Sections 5 and 6 cover the Signals change and an inventory that records the current state before it is needed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. The 37-month boundary in the BigQuery Data Transfer Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The entry appeared in the BigQuery release notes on 6 May 2026 and took effect on 1 June 2026. It applies to three connectors of the BigQuery Data Transfer Service: Google Ads, Search Ads 360 and Google Analytics 4. Backfill runs on these connectors are no longer populated with data older than 37 months. The stated reason is a change to the retention rules on the Google Ads side.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Two boundaries of the change matter for anyone maintaining a warehouse built on these transfers. Data already transferred remains untouched \u2014 as long as no backfill runs over it. The 37 months are a rolling window, not a fixed cut-off date, so a range that was still inside the boundary in June moves outside it as the months pass. A backfill definition stored in a runbook a year ago and left unchanged will therefore cross the boundary at some point without anything in the definition itself changing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The documentation leaves several details open: whether a run returns an error code or message, whether the Cloud console warns about a range beyond the boundary, and whether the operation can be reversed afterwards. None of these behaviors should be assumed. The guard therefore needs to check the requested range and the resulting rows rather than rely on an undocumented signal from the service.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Why a backfill can replace complete history<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The core of this change is not the boundary. A limit on how far back a connector reaches would be an inconvenience with an obvious workaround: keep the archive that already exists. The core is the second half of the documented behaviour \u2014 a run that returns incomplete or empty results can overwrite history that was complete.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The sequence that leads there is an ordinary one. A warehouse holds four years of transfer data. A late correction, a schema adjustment or a suspected gap prompts a re-run for an older window. The backfill is scheduled with a date range that reaches back beyond 37 months, entirely or in part. The run completes. The partitions inside the window are rewritten with what the connector delivered, and what the connector delivered for the portion beyond the boundary is incomplete or empty. Nothing in that chain requires a mistake in the request itself; the same request would have worked in May.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is what makes a re-run different from a first load. A first load into an empty range can only add. A re-run over an existing range replaces, and replacement is only safe when the source is at least as complete as the target. Since 1 June that assumption no longer holds for the affected connectors beyond the 37-month mark, which turns a routine operation into one that needs a precondition attached to it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Because the documentation does not describe a reversal path, the practical consequence is that the check has to happen before the run, and a copy has to exist before the run. Recovery after the fact depends entirely on whatever the warehouse itself preserved.<\/p>\n\n\n\n<figure class=\"lw-diagram\">\n<img decoding=\"async\" src=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/diagrams\/hand-backfill-en.png\" width=\"1120\" height=\"700\" loading=\"lazy\" alt=\"The same BigQuery target table shown before and after a backfill that reaches past the 37-month boundary, with the older segment turning from complete to empty\">\n<figcaption>The boundary does not block the run; it changes what the run writes. Everything to the left of it comes back incomplete or empty, and it lands in the same rows that previously held the full history.<\/figcaption>\n<\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">4. A guard before the run: check the boundary, count the rows, keep a copy<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The guard has three parts, and each one is small enough to sit in front of an existing backfill step. All identifiers written in capitals below are placeholders for the project, dataset, table and date column of the warehouse the run touches; the column names are not prescribed by the service and follow whatever the target table already uses.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The first part compares the requested range against the rolling boundary. It answers a single question \u2014 does any part of this window fall beyond 37 months \u2014 and it answers it from the calendar, not from a response the service may or may not send.<\/p>\n\n\n<figure style=\"--cbb-digits:2\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"sql\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">SQL<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-sql\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\"><span class=\"cbb-comment\">-- PROJECT, DATASET, TARGET_TABLE and PARTITION_DATE are placeholders.<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">DECLARE<\/span> backfill_start <span class=\"cbb-type\">DATE<\/span> <span class=\"cbb-keyword\">DEFAULT<\/span> <span class=\"cbb-type\">DATE<\/span> <span class=\"cbb-string\">'2022-01-01'<\/span>;\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">DECLARE<\/span> backfill_end   <span class=\"cbb-type\">DATE<\/span> <span class=\"cbb-keyword\">DEFAULT<\/span> <span class=\"cbb-type\">DATE<\/span> <span class=\"cbb-string\">'2022-06-30'<\/span>;\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">DECLARE<\/span> earliest_supported <span class=\"cbb-type\">DATE<\/span> <span class=\"cbb-keyword\">DEFAULT<\/span> <span class=\"cbb-function\">DATE_SUB<\/span>(<span class=\"cbb-function\">CURRENT_DATE<\/span>(), <span class=\"cbb-keyword\">INTERVAL<\/span> <span class=\"cbb-number\">37<\/span> MONTH);\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">SELECT<\/span>\n<\/span><span class=\"cbb-line\">  backfill_start,\n<\/span><span class=\"cbb-line\">  backfill_end,\n<\/span><span class=\"cbb-line\">  earliest_supported,\n<\/span><span class=\"cbb-line\">  backfill_start &lt; earliest_supported <span class=\"cbb-keyword\">AS<\/span> starts_before_boundary,\n<\/span><span class=\"cbb-line\">  backfill_end   &lt; earliest_supported <span class=\"cbb-keyword\">AS<\/span> ends_before_boundary,\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-function\">DATE_DIFF<\/span>(earliest_supported, backfill_start, DAY) <span class=\"cbb-keyword\">AS<\/span> days_outside;<\/span><\/code><\/pre><\/figure>\n\n\n<p class=\"wp-block-paragraph\">The same comparison belongs in the wrapper that triggers the run, so that an out-of-range window stops the job instead of merely producing a row in a result set. A shell gate keeps the decision next to the scheduler rather than inside the warehouse.<\/p>\n\n\n<figure style=\"--cbb-digits:2\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"bash\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">Shell<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-bash\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\"><span class=\"cbb-comment\">#!\/usr\/bin\/env bash<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">set<\/span> <span class=\"cbb-attr\">-euo<\/span> pipefail\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">START=<span class=\"cbb-string\">\"2022-01-01\"<\/span>\n<\/span><span class=\"cbb-line\">END=<span class=\"cbb-string\">\"2022-06-30\"<\/span>\n<\/span><span class=\"cbb-line\">BOUNDARY=<span class=\"cbb-string\">\"$(date -u -d '37 months ago' +%F)\"<\/span>\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">if<\/span> &#91;&#91; <span class=\"cbb-string\">\"<\/span><span class=\"cbb-variable\">$START<\/span><span class=\"cbb-string\">\"<\/span> &lt; <span class=\"cbb-string\">\"<\/span><span class=\"cbb-variable\">$BOUNDARY<\/span><span class=\"cbb-string\">\"<\/span> &#93;&#93;<span class=\"cbb-operator\">;<\/span> <span class=\"cbb-keyword\">then<\/span>\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-function\">echo<\/span> <span class=\"cbb-string\">\"range starts <\/span><span class=\"cbb-variable\">$START<\/span><span class=\"cbb-string\">, boundary is <\/span><span class=\"cbb-variable\">$BOUNDARY<\/span><span class=\"cbb-string\"> - backfill not started\"<\/span> <span class=\"cbb-operator\">&gt;<\/span>&amp;<span class=\"cbb-number\">2<\/span>\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-keyword\">exit<\/span> <span class=\"cbb-number\">1<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">fi<\/span>\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-comment\"># only reached when the whole window sits inside the boundary<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-comment\"># .\/run_backfill.sh \"$START\" \"$END\"<\/span><\/span><\/code><\/pre><\/figure>\n\n\n<p class=\"wp-block-paragraph\">The second part is a row census per day, taken before the run and again afterwards. It does not depend on any message from the service and it makes a replacement with empty results visible as a number rather than as a suspicion. Storing both phases in the same audit table keeps the comparison to a single query.<\/p>\n\n\n<figure style=\"--cbb-digits:2\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"sql\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">SQL<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-sql\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\"><span class=\"cbb-keyword\">CREATE<\/span> <span class=\"cbb-keyword\">TABLE<\/span> <span class=\"cbb-keyword\">IF<\/span> <span class=\"cbb-keyword\">NOT<\/span> <span class=\"cbb-keyword\">EXISTS<\/span> <span class=\"cbb-variable\">`PROJECT.audit.transfer_row_census`<\/span> (\n<\/span><span class=\"cbb-line\">  captured_at <span class=\"cbb-type\">TIMESTAMP<\/span>,\n<\/span><span class=\"cbb-line\">  phase <span class=\"cbb-type\">STRING<\/span>,\n<\/span><span class=\"cbb-line\">  day <span class=\"cbb-type\">DATE<\/span>,\n<\/span><span class=\"cbb-line\">  row_count <span class=\"cbb-type\">INT64<\/span>\n<\/span><span class=\"cbb-line\">);\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">INSERT<\/span> <span class=\"cbb-keyword\">INTO<\/span> <span class=\"cbb-variable\">`PROJECT.audit.transfer_row_census`<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">SELECT<\/span> <span class=\"cbb-function\">CURRENT_TIMESTAMP<\/span>(), <span class=\"cbb-string\">'before'<\/span>, PARTITION_DATE, <span class=\"cbb-function\">COUNT<\/span>(*)\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">FROM<\/span> <span class=\"cbb-variable\">`PROJECT.DATASET.TARGET_TABLE`<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">WHERE<\/span> PARTITION_DATE <span class=\"cbb-keyword\">BETWEEN<\/span> <span class=\"cbb-type\">DATE<\/span> <span class=\"cbb-string\">'2022-01-01'<\/span> <span class=\"cbb-keyword\">AND<\/span> <span class=\"cbb-type\">DATE<\/span> <span class=\"cbb-string\">'2022-06-30'<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">GROUP<\/span> <span class=\"cbb-keyword\">BY<\/span> PARTITION_DATE;\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-comment\">-- after the run, the same statement with phase = 'after', then:<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">SELECT<\/span>\n<\/span><span class=\"cbb-line\">  b.day,\n<\/span><span class=\"cbb-line\">  b.row_count <span class=\"cbb-keyword\">AS<\/span> rows_before,\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-function\">IFNULL<\/span>(a.row_count, <span class=\"cbb-number\">0<\/span>) <span class=\"cbb-keyword\">AS<\/span> rows_after,\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-function\">IFNULL<\/span>(a.row_count, <span class=\"cbb-number\">0<\/span>) - b.row_count <span class=\"cbb-keyword\">AS<\/span> delta\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">FROM<\/span> <span class=\"cbb-variable\">`PROJECT.audit.transfer_row_census`<\/span> b\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">LEFT<\/span> <span class=\"cbb-keyword\">JOIN<\/span> <span class=\"cbb-variable\">`PROJECT.audit.transfer_row_census`<\/span> a\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-keyword\">ON<\/span> a.day = b.day <span class=\"cbb-keyword\">AND<\/span> a.phase = <span class=\"cbb-string\">'after'<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">WHERE<\/span> b.phase = <span class=\"cbb-string\">'before'<\/span>\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-keyword\">AND<\/span> <span class=\"cbb-function\">IFNULL<\/span>(a.row_count, <span class=\"cbb-number\">0<\/span>) &lt; b.row_count\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">ORDER<\/span> <span class=\"cbb-keyword\">BY<\/span> delta;<\/span><\/code><\/pre><\/figure>\n\n\n<p class=\"wp-block-paragraph\">The third part is the copy. Since the documentation says nothing about reversing such a run, the only reliable route back is a copy of the affected range made while it was still complete. A snapshot table named after the run and the date of the run is enough, and it can be dropped once the census shows no negative delta.<\/p>\n\n\n<figure style=\"--cbb-digits:1\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"sql\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">SQL<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-sql\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\"><span class=\"cbb-keyword\">CREATE<\/span> <span class=\"cbb-keyword\">TABLE<\/span> <span class=\"cbb-variable\">`PROJECT.DATASET.TARGET_TABLE__pre_backfill_20260810`<\/span> <span class=\"cbb-keyword\">AS<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">SELECT<\/span> *\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">FROM<\/span> <span class=\"cbb-variable\">`PROJECT.DATASET.TARGET_TABLE`<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">WHERE<\/span> PARTITION_DATE <span class=\"cbb-keyword\">BETWEEN<\/span> <span class=\"cbb-type\">DATE<\/span> <span class=\"cbb-string\">'2022-01-01'<\/span> <span class=\"cbb-keyword\">AND<\/span> <span class=\"cbb-type\">DATE<\/span> <span class=\"cbb-string\">'2022-06-30'<\/span>;<\/span><\/code><\/pre><\/figure>\n\n\n<p class=\"wp-block-paragraph\">Three steps, all on the warehouse side, none of them dependent on a signal the service is not documented to send. The order is what carries the value: boundary check, census, copy, then the run.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Google Signals has controlled less since 15 June<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The second change is smaller in code and larger in interpretation. From 15 June 2026, the Google Signals setting in the Analytics admin and the Google Signals API govern only one thing: whether Analytics data is associated with information from signed-in users for behavioural reporting. Control over the data itself now sits with Consent Mode, specifically with the <code>ad_storage<\/code> parameter. The description is on Google Analytics help page 17016975, retrieved on 10 August 2026.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The operational consequence is a shift in which surface answers a given question. A question about signed-in association in behavioural reporting is answered by the Signals setting. A question about the underlying data is answered by the consent configuration on the collection side. A configuration document, an internal wiki page or a client-facing description written before 15 June may still describe the Signals switch as governing the second question, and nothing in the interface marks that description as out of date.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Several things about this change are not documented and are worth naming as open rather than estimating. The help page carries no publication date, so the exact point at which the description was revised cannot be read from the page itself. It names no volume effects, so any statement about how reporting figures move is not supported by the source. And it says nothing about existing audiences, so the status of audiences built while the setting had a wider scope is not addressed there either. Each of these is a question for the properties in question, not one the documentation answers.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. An inventory per property, and what stays open<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">What can be done without leaving the documented ground is an inventory: record the current Signals state per property, keep the record, and check the <code>ad_storage<\/code> consent rates separately in reporting. That produces a dated baseline, which is what any later question about a difference will need.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Google Signals API is named in the documentation as one of the two control surfaces, but no endpoint names, request fields or response schemas are established here. The script below therefore keeps the API call itself behind a placeholder function, to be filled in against the API reference for the client library in use; the part that is written out is the persistence and the diff, which is where the value of the inventory sits.<\/p>\n\n\n<figure style=\"--cbb-digits:2\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"python\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">Python<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-python\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\"><span class=\"cbb-keyword\">import<\/span> csv\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">import<\/span> datetime\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-comment\"># Placeholder: implemented against the Google Signals API with the<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-comment\"># client library in use. Returns whatever state field that API exposes.<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">def<\/span> <span class=\"cbb-function\">fetch_signals_state<\/span>(property_id: str):\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">raise<\/span> <span class=\"cbb-function\">NotImplementedError<\/span>(<span class=\"cbb-string\">\"fill in against the API reference\"<\/span>)\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">PROPERTIES = &#91;<span class=\"cbb-string\">\"PROPERTY_ID_1\"<\/span>, <span class=\"cbb-string\">\"PROPERTY_ID_2\"<\/span>&#93;   <span class=\"cbb-comment\"># placeholders<\/span>\n<\/span><span class=\"cbb-line\">OUT = <span class=\"cbb-string\">\"signals_inventory.csv\"<\/span>\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">captured_at = datetime.datetime.<span class=\"cbb-function\">now<\/span>(datetime.timezone.utc).<span class=\"cbb-function\">isoformat<\/span>()\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">with<\/span> <span class=\"cbb-function\">open<\/span>(OUT, <span class=\"cbb-string\">\"a\"<\/span>, newline=<span class=\"cbb-string\">\"\"<\/span>, encoding=<span class=\"cbb-string\">\"utf-8\"<\/span>) <span class=\"cbb-keyword\">as<\/span> fh:\n<\/span><span class=\"cbb-line\">    writer = csv.<span class=\"cbb-function\">writer<\/span>(fh)\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">for<\/span> property_id <span class=\"cbb-keyword\">in<\/span> PROPERTIES:\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-keyword\">try<\/span>:\n<\/span><span class=\"cbb-line\">            state = <span class=\"cbb-function\">fetch_signals_state<\/span>(property_id)\n<\/span><span class=\"cbb-line\">            writer.<span class=\"cbb-function\">writerow<\/span>(&#91;captured_at, property_id, state, <span class=\"cbb-string\">\"\"<\/span>&#93;)\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-keyword\">except<\/span> Exception <span class=\"cbb-keyword\">as<\/span> exc:                  <span class=\"cbb-comment\"># recorded, not swallowed<\/span>\n<\/span><span class=\"cbb-line\">            writer.<span class=\"cbb-function\">writerow<\/span>(&#91;captured_at, property_id, <span class=\"cbb-string\">\"\"<\/span>, <span class=\"cbb-function\">repr<\/span>(exc)&#93;)<\/span><\/code><\/pre><\/figure>\n\n\n<p class=\"wp-block-paragraph\">The second half of the inventory is the consent side. How <code>ad_storage<\/code> state is stored differs per setup \u2014 it may sit in an export table, in a collection-side log, or in a table maintained by the consent platform \u2014 so the table and column names below are placeholders for whatever the warehouse already holds. The query produces a daily rate, which is the form in which a shift over the June boundary would be readable at all.<\/p>\n\n\n<figure style=\"--cbb-digits:2\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"sql\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">SQL<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-sql\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\"><span class=\"cbb-comment\">-- CONSENT_TABLE, DAY_COLUMN and AD_STORAGE_COLUMN are placeholders<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-comment\">-- for the columns in which the warehouse records consent state.<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">SELECT<\/span>\n<\/span><span class=\"cbb-line\">  DAY_COLUMN <span class=\"cbb-keyword\">AS<\/span> day,\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-function\">COUNTIF<\/span>(AD_STORAGE_COLUMN = <span class=\"cbb-string\">'granted'<\/span>) <span class=\"cbb-keyword\">AS<\/span> granted,\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-function\">COUNT<\/span>(*) <span class=\"cbb-keyword\">AS<\/span> total,\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-function\">SAFE_DIVIDE<\/span>(<span class=\"cbb-function\">COUNTIF<\/span>(AD_STORAGE_COLUMN = <span class=\"cbb-string\">'granted'<\/span>), <span class=\"cbb-function\">COUNT<\/span>(*)) <span class=\"cbb-keyword\">AS<\/span> granted_rate\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">FROM<\/span> <span class=\"cbb-variable\">`PROJECT.DATASET.CONSENT_TABLE`<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">WHERE<\/span> DAY_COLUMN <span class=\"cbb-keyword\">BETWEEN<\/span> <span class=\"cbb-type\">DATE<\/span> <span class=\"cbb-string\">'2026-05-01'<\/span> <span class=\"cbb-keyword\">AND<\/span> <span class=\"cbb-function\">CURRENT_DATE<\/span>()\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">GROUP<\/span> <span class=\"cbb-keyword\">BY<\/span> day\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">ORDER<\/span> <span class=\"cbb-keyword\">BY<\/span> day;<\/span><\/code><\/pre><\/figure>\n\n\n<p class=\"wp-block-paragraph\">The inventory records the state, but it does not explain changes in the figures. A rate that changes across June may reflect the consent configuration, seasonality, traffic mix or a site release. Because the documentation describes no volume effects, attributing that change to Google Signals would go beyond the source. The dated record lets you compare each property later while keeping two questions separate: what the setting controls and what the data shows.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Transfer boundary:<\/strong> since 1 June 2026 the BigQuery Data Transfer Service connectors for Google Ads, Search Ads 360 and Google Analytics 4 no longer populate backfill runs with data older than 37 months. The stated reason is a change to Google Ads retention rules.<\/li>\n<li><strong>The consequential part:<\/strong> the documentation states that such runs return incomplete or empty results and can overwrite existing complete history. Data already transferred stays untouched as long as no backfill runs over it.<\/li>\n<li><strong>Not documented:<\/strong> which error code or message appears, whether the interface warns, and whether the operation can be reversed. A guard therefore relies on the requested range, a row census before and after, and a copy taken beforehand.<\/li>\n<li><strong>Signals scope:<\/strong> from 15 June 2026 the Signals setting and the Google Signals API control only the association of Analytics data with signed-in user information for behavioural reporting; control over the data itself sits with Consent Mode and <code>ad_storage<\/code>.<\/li>\n<li><strong>Open on that side:<\/strong> the help page carries no publication date, names no volume effects, and says nothing about existing audiences. A dated per-property inventory records the state; it does not explain movements in the numbers.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Both changes were documented before they took effect, and both remain invisible in day-to-day operation until a specific action or a specific question brings them to the surface. The practical difference between the two is the point at which a check pays for itself: for the transfer boundary it is the moment before a backfill starts, for Google Signals it is the moment a configuration description is written down and dated.<\/p>\n\n\n<div class=\"lw-faq\">\n<h2>Questions and answers<\/h2>\n\n<h3>The shell gate compares dates as strings. Is that deliberate, given that the comparison fails silently for anything but ISO dates?<\/h3>\n<p>Deliberate, and the reason is worth stating out loud: ISO 8601 dates sort lexicographically, which is what makes a string comparison exact rather than merely convenient. The moment someone writes a date in a different format, the comparison stops meaning anything, and it stops silently, which is the same failure mode the whole article is about.<\/p>\n<p>There is a second dependency in that gate that deserves more attention than the string comparison. The boundary comes from <code>date -u -d '37 months ago'<\/code>, so it depends on the clock of whichever host runs the job and is computed in UTC, while the account or the warehouse may count days in another time zone. Near midnight the two can disagree by a day, and a day is enough at the edge of the window.<\/p>\n<p>Both are cheap to make visible instead of assumed: the boundary is computed once and logged beside the requested range, so the log records what the run actually compared. When the census later shows a negative delta, that line is what separates a wrong range from a wrong clock.<\/p>\n\n<h3>What does the documentation say about audiences built while the Google Signals setting still had the wider scope?<\/h3>\n<p>Nothing, as of the retrieval date given in the article: the help page does not mention audiences that already exist. The honest reading is that the source does not cover the case, not that the case is harmless.<\/p>\n<p>What can be done without leaving documented ground is narrow but useful: a dated record of the current state per property, together with the audience definitions as they stand. That turns a later question about a difference into a comparison instead of a reconstruction from memory, which is the whole value of the inventory.<\/p>\n<p>The temptation in this situation is to fill the gap with a plausible answer, because a plausible answer is what a stakeholder actually asks for. It is also how a number with no source ends up in a planning document and gets quoted back a year later. An open question, written down as open and dated, ages better than a confident guess.<\/p>\n<\/div>\n\n<div class=\"lw-quellen\">\n<h2>Sources<\/h2>\n<ul>\n<li><a href=\"https:\/\/docs.cloud.google.com\/bigquery\/docs\" target=\"_blank\" rel=\"noopener noreferrer\">BigQuery documentation<\/a><\/li>\n<li><a href=\"https:\/\/support.google.com\/analytics\/answer\/7029846\" target=\"_blank\" rel=\"noopener noreferrer\">BigQuery Export schema reference<\/a><\/li>\n<\/ul>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>Since June 2026 a BigQuery Data Transfer Service backfill can overwrite complete history with empty results, and the Google Signals setting governs less than it once did.<\/p>\n","protected":false},"author":1,"featured_media":15128,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[91333,91297,91258,91407],"class_list":["post-9401","post","type-post","status-publish","format-standard","hentry","category-digital-analytics","tag-bigquery","tag-data-quality","tag-google-analytics-4","tag-google-cloud"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026 | Lukas Wojcik<\/title>\n<meta name=\"description\" content=\"BigQuery backfills and Google Signals: date boundaries, empty import results and checks before overwriting existing history.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026 | Lukas Wojcik\" \/>\n<meta property=\"og:description\" content=\"BigQuery backfills and Google Signals: date boundaries, empty import results and checks before overwriting existing history.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-12T16:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-09T20:41:27+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-9401-bigquery-backfill-limit-google-signa-n.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Lukas Wojcik\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Lukas Wojcik\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/\"},\"author\":{\"name\":\"Lukas Wojcik\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"headline\":\"BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026\",\"datePublished\":\"2026-08-12T16:00:00+00:00\",\"dateModified\":\"2026-10-09T20:41:27+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/\"},\"wordCount\":2414,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/hero-9401-bigquery-backfill-limit-google-signa-n.png\",\"keywords\":[\"BigQuery\",\"Data Quality\",\"Google Analytics 4\",\"Google Cloud\"],\"articleSection\":[\"Digital Analytics\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/\",\"name\":\"BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026 | Lukas Wojcik\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/hero-9401-bigquery-backfill-limit-google-signa-n.png\",\"datePublished\":\"2026-08-12T16:00:00+00:00\",\"dateModified\":\"2026-10-09T20:41:27+00:00\",\"description\":\"BigQuery backfills and Google Signals: date boundaries, empty import results and checks before overwriting existing history.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/hero-9401-bigquery-backfill-limit-google-signa-n.png\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/hero-9401-bigquery-backfill-limit-google-signa-n.png\",\"width\":1200,\"height\":630,\"caption\":\"BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"Lukas Wojcik\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"Lukas Wojcik\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026 | Lukas Wojcik","description":"BigQuery backfills and Google Signals: date boundaries, empty import results and checks before overwriting existing history.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/","og_locale":"en_US","og_type":"article","og_title":"BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026 | Lukas Wojcik","og_description":"BigQuery backfills and Google Signals: date boundaries, empty import results and checks before overwriting existing history.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/","og_site_name":"Lukas Wojcik - Blog","article_published_time":"2026-08-12T16:00:00+00:00","article_modified_time":"2026-10-09T20:41:27+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-9401-bigquery-backfill-limit-google-signa-n.png","type":"image\/png"}],"author":"Lukas Wojcik","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Lukas Wojcik","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/#article","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/"},"author":{"name":"Lukas Wojcik","@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"headline":"BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026","datePublished":"2026-08-12T16:00:00+00:00","dateModified":"2026-10-09T20:41:27+00:00","mainEntityOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/"},"wordCount":2414,"commentCount":0,"publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-9401-bigquery-backfill-limit-google-signa-n.png","keywords":["BigQuery","Data Quality","Google Analytics 4","Google Cloud"],"articleSection":["Digital Analytics"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/","name":"BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026 | Lukas Wojcik","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/#primaryimage"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-9401-bigquery-backfill-limit-google-signa-n.png","datePublished":"2026-08-12T16:00:00+00:00","dateModified":"2026-10-09T20:41:27+00:00","description":"BigQuery backfills and Google Signals: date boundaries, empty import results and checks before overwriting existing history.","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/#primaryimage","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-9401-bigquery-backfill-limit-google-signa-n.png","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-9401-bigquery-backfill-limit-google-signa-n.png","width":1200,"height":630,"caption":"BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026"},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/bigquery-data-transfer-backfill-limit-and-google-signals-scope-two-ga4\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"BigQuery Data Transfer Backfill Limit and Google Signals Scope: Two GA4 Changes From June 2026"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"Lukas Wojcik","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"Lukas Wojcik"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/9401","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=9401"}],"version-history":[{"count":4,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/9401\/revisions"}],"predecessor-version":[{"id":21797,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/9401\/revisions\/21797"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media\/15128"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=9401"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/categories?post=9401"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=9401"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}