# GA4 hostname decision and validation workbook

Prepared and sources reviewed: 2026-10-08. Companion files: `ga4-hostnames-blank.csv` and `ga4-hostnames-worked.csv`.

This workbook separates intended collection, a candidate hostname set and actual GA4 Testing observations. It does not connect to an account, scan websites or change a filter. The worked inputs are synthetic. A local exact-string exercise was run on 2026-10-08; no live GA4 filter test or activation was performed.

## Start with the business decision

Use one row per important hostname, collection route and event. Keep the event's purpose beside it. A hostname decision cannot establish a completed enquiry, qualification or sale.

| Decision | Meaning in this workbook |
| --- | --- |
| Allow | The business intends to retain this collection. It is not evidence that Google will retain it. |
| Suppress | Evidence establishes that the collection is unwanted for this property. |
| Hold | Something material is unresolved. Do not activate the proposed filter while necessary collection remains at risk. |

These are review labels, not Google filter states. Google's states are Testing, Active and Inactive. Do not translate a workbook Hold into a supposed third Include operation.

The blank CSV provides Main site, Campaign and Booking rows. Duplicate them for additional host/event combinations. Empty hostnames on blank templates mean not entered. In the worked example H06 and H07, empty strings are intentional synthetic inputs and the corresponding notes explain them.

## Property and change record

| Field | Your evidence |
| --- | --- |
| Property identifier and responsible owner | Unknown |
| Stream identifiers and collection routes | Unknown |
| Inventory period, timezone and export time | Unknown |
| Main-site, campaign and booking systems checked | Unknown |
| Existing filters: name, operation, condition, state | Unknown |
| Proposed exact hosts or other documented conditions | Unknown |
| Capacity within the ten-filter property limit | Unknown |
| Other Include rules that widen the candidate set | Unknown |
| Exclude rules that may remove intended data | Unknown |
| Test plan, consent conditions and expected event triggers | Unknown |
| Testing start and planned observation window | Not started |
| Actual named-filter observations and export references | Not observed |
| Independent form or booking receipt check | Not observed |
| Unresolved Hold rows | Unknown |
| Activation decision and approving owner | Hold; owner unassigned |
| Previous configuration, change time and correction plan | Not recorded |
| Subsequent collection review | Pending |

Retain private exports in controlled records. Do not put client contact details in this public teaching template. Record references instead.

## Set up the two views

1. Inventory: Free form exploration with Hostname, Event name and Event count. Record the period and scope; compare with the actual systems that should send events.
2. Validation: add Test data filter name, Hostname and Event name to Rows, and Event count to Values. Use Google's named-filter condition for the proposed filter while keeping the unfiltered inventory available beside it.
3. Wait the documented 24 to 36 hours after selecting Testing before reading validation results. Cover essential low-frequency activity as well; elapsed time alone is not acceptance.
4. Record a known-match and known-nonmatch observation and the configured operation. Google describes Testing as labelling matching data. A matching Include condition and matching Exclude condition have different consequences. Do not assume every labelled row would be removed.
5. Investigate a missing or unexpected row. Check collection, scope, timing, existing filters and route. DebugView alone cannot establish ordinary-report treatment, especially when developer exclusions exist.

Current primary setup: [Hostname filtering](https://support.google.com/analytics/answer/16608575?hl=en). Navigation and behavior were read from documentation, not verified in a particular account.

## Blank event record

| Field | Your value |
| --- | --- |
| Row ID / surface | Unknown |
| Exact hostname, or reason it is missing | Unknown |
| Collection route | Unknown |
| Intended event and business action | Unknown |
| Allow / Suppress / Hold and reason | Hold |
| Condition and expected candidate membership | Unknown |
| Expected Testing observation | Define after recording the operation and test plan |
| Actual filter name, hostname, event and count | Not observed |
| Actual time, timezone and source reference | Not observed |
| Event triggers and duplicate check | Not observed |
| Independent receipt, if relevant | Not observed |
| Other filter/route explanation | Unknown |
| Owner and next action | Unassigned |
| Final decision | Hold |

No observation is not zero events, an excluded event or a successful pass. Record each of those only when the evidence supports it.

## Fictional worked matrix

**All hostnames, event choices and collection decisions below are invented. They describe no customer account or real event traffic.** The reserved `.example` domains are teaching strings. No counts represent visits, enquiries or removed spam.

Candidate exact set: `www.advisory.example` and `go.advisory.example`.

| Row and surface | Decision / local selection | Actual GA4 Testing evidence |
| --- | --- | --- |
| H01 Main-site page_view | Allow; in candidate set | Not observed |
| H02 Campaign generate_lead | Allow; in candidate set | Not observed |
| H03 Booking generate_lead | Hold; outside candidate set | Not observed; collection route unresolved |
| H04 Staging page_view | Suppress; outside candidate set | Not observed |
| H05 Misleading suffix page_view | Suppress; outside candidate set | Not observed |
| H06 Empty browser hostname | Hold; outside candidate set | Not observed; missing-host reason unresolved |
| H07 Measurement Protocol qualify_lead | Allow; not evaluated by local selection | Not observed; documented Include exemption is separate |
| H08 Data Manager API lead update | Hold; not evaluated by local selection | Not observed; behavior not established here |

The worked CSV retains the full strings, routes, decisions, proposed next actions and local results. Its evidence references explicitly say synthetic inputs. The main and campaign Allow choices are intentions, not passed account tests. The staging and misleading-host Suppress decisions are invented case assumptions, not diagnoses of a real business.

The booking row prevents activation. The candidate list does not contain its hostname, and the route remains unknown. Establish whether the booking system sends browser events, another integration sends the event, or the event is not sent to this property. Then revise the proposal and test the resulting collection.

For H06, inspect any `page_location` override on the affected event. Google's dimension guidance requires a full URL when overriding the automatic value; a path such as `/book/` contains no hostname. This is a possible cause to check, not the established cause of the synthetic row. Keep its actual GA4 observation Not observed.

The local output is **2 in candidate, 4 outside candidate, 2 not evaluated**. These are counts of example strings, not event volumes. Six strings were compared for exact membership; the two other routes were excluded from that exercise. This does not emulate Google's hostname normalization, filtering implementation, precedence, labels, integrations or processing time.

## Reproduce the local string exercise

Save the worked CSV and the following code as `selection_check.py` in the same folder, then run `python3 selection_check.py`. It uses Python's standard library, reads the local worked CSV and prints results. It makes no network or account calls and changes no file. The assertions check only the supplied synthetic exercise; do not reuse its result as evidence of an Analytics filter test.

```python
from pathlib import Path
import csv

# SYNTHETIC exact-string selection exercise. No network or Analytics API calls.
# This does not emulate Google normalization, processing, labels or precedence.
path = Path("ga4-hostnames-worked.csv")
candidate = {"www.advisory.example", "go.advisory.example"}
with path.open(newline="", encoding="utf-8") as handle:
    rows = list(csv.DictReader(handle))
counts = {"in_candidate": 0, "outside_candidate": 0, "not_evaluated": 0}
for row in rows:
    if row["record_kind"] != "synthetic_example":
        raise ValueError("This exercise accepts the supplied synthetic rows only")
    route = row["collection_route"]
    if route in {"MeasurementProtocol", "DataManagerAPI"}:
        result = "not_evaluated"
    else:
        result = "in_candidate" if row["hostname"] in candidate else "outside_candidate"
    assert result == row["candidate_membership_expected"], row["sample_id"]
    assert row["ga4_testing_observed"] == "Not observed"
    counts[result] += 1
    print(row["sample_id"], row["decision"], result, "GA4: Not observed")
print(counts)
print("Local string selection only. Activation remains Hold; no GA4 validation.")
```

Expected final output:

```text
{'in_candidate': 2, 'outside_candidate': 4, 'not_evaluated': 2}
Local string selection only. Activation remains Hold; no GA4 validation.
```

## Before and after a real activation

Resolve every material Hold. Obtain the property owner's review of all intended event origins and the actual Testing observations. Retain previous settings and an agreed correction plan. Record the Active change time; Google documents a 24-to-36-hour start window, not instant enforcement. Inspect subsequent essential events and independent receipt again.

Setting a filter back to Inactive is a prospective correction, not a way to recover excluded history. Google says excluded data is unavailable in Analytics and BigQuery. A saved report filter is the appropriate alternative when the goal is merely to hide data in a view.

## Source register

Reviewed 2026-10-08. Sources explain the method and product behavior; they do not substantiate the fictional records.

- [September21 Include release and route exceptions](https://support.google.com/analytics/answer/9164320?hl=en): Measurement Protocol exempt; empty hostnames blocked. Do not infer that every server-side route is exempt or every blank hostname proves spam.
- [Hostname setup and Testing](https://support.google.com/analytics/answer/16608575?hl=en): Editor role, operations, four match types, filter states and timing.
- [Data-filter behavior and precedence](https://support.google.com/analytics/answer/13296761?hl=en): prospective/permanent effect; Include union before Excludes.
- [Internal traffic](https://support.google.com/analytics/answer/10104470?hl=en): ten data filters per property and separate IP-related controls.
- [Developer traffic](https://support.google.com/analytics/answer/13296662?hl=en): debug collection and report exclusion are different checks.
- [Hostname dimension](https://support.google.com/analytics/table/13948007?hl=en-GB): hostname describes a visited URL, not its referral source.
- [Cross-domain measurement](https://support.google.com/analytics/answer/10071811?hl=en): separate continuity setup.

No account observation or filter activation is claimed by this workbook. Retain local string results and actual GA4 validation as separate evidence.
