# Default channel rules and when to reclassify

Use this to test a source and medium pair, not to design a convention. Rules below are the manual-traffic conditions from Google's default channel group page, read on 2026-10-17. Google can change them; re-read the page before quoting a rule to a stakeholder.

## Rule cues for manual traffic

Channel definitions are not case sensitive and cannot be edited. "Source list" means Google's downloadable list of sites by category, linked from the same page.

- Direct: source exactly `(direct)` and medium `(not set)` or `(none)`.
- Cross-network: campaign name contains `cross-network`.
- Paid Shopping: (source on the shopping list, or campaign name matches the shop pattern below) and medium matches the paid pattern.
- Paid Search: source on the search list and medium matches the paid pattern.
- Paid Social: source on the social list and medium matches the paid pattern.
- Paid Video: source on the video list and medium matches the paid pattern.
- Display: medium is `display`, `banner`, `expandable`, `interstitial` or `cpm`.
- Paid Other: medium matches the paid pattern (no source condition).
- Organic Shopping: source on the shopping list, or campaign name matches the shop pattern.
- Organic Social: source on the social list, or medium is `social`, `social-network`, `social-media`, `sm`, `social network` or `social media`.
- Organic Video: source on the video list, or medium matches `^(.*video.*)$`.
- Organic Search: source on the search list, or medium exactly `organic`.
- Referral: medium is `referral`, `app` or `link`.
- Email: source or medium is `email`, `e-mail`, `e_mail` or `e mail`.
- Affiliates: medium `affiliate`.
- Audio: medium exactly `audio`.
- SMS: source or medium exactly `sms`.
- Mobile Push Notifications: medium ends with `push`, or contains `mobile` or `notification`, or source exactly `firebase`.
- AI Assistant: medium exactly `ai-assistant`. GA4 also sets medium `ai-assistant` and campaign `(ai-assistant)` itself when the referrer is on its list of AI assistants (since 13 May 2026). Google's AI Overviews and AI Mode count as Organic Search.
- Unassigned: no other rule matched.

Patterns:

```text
Paid medium:  ^(.*cp.*|ppc|retargeting|paid.*)$
Shop campaign: ^(.*(([^a-df-z]|^)shop|shopping).*)$
```

Google Ads traffic is classified differently: by ad network type for most traffic, by campaign type for Shopping, and by campaign type when GBRAID is present or the network type is absent. Do not test Google Ads rows with the manual cues.

The help page does not publish an evaluation order. When a pair could match two rules, read the processed report for a controlled test click rather than predicting the winner.

## Pairs that commonly land in Unassigned

Each of these matches no medium cue, so it is Unassigned unless the source is on one of Google's lists or the campaign name trips another rule:

- `newsletter`, `edm`, `mailer`, `crm` used as medium (Email needs `email` in source or medium).
- `qr`, `qrcode`, `print`, `offline`, `event`, `ooh`.
- `partner`, `influencer`, `creator`, `sponsorship`, `podcast` (Audio needs exactly `audio`).
- `organic_social`, `social_organic`, `post` with a source not on the social list.
- `ai`, `chatgpt`, `llm`, `genai`.
- A medium with a typo or an unresolved placeholder such as `{medium}`.
- `<any source> / (not set)` from links that carry only `utm_source`: partner links, social profile links and some assistant links. The landing URL still shows the partial UTM, so this is a tagging problem (cause A), not lost collection.

Two traps that do not show up as Unassigned:

- Any medium containing `cp` (`cpc`, `cpm`, `cpa`, `cpv`) or starting with `paid` matches the paid pattern, so mislabelled organic posts tagged `paid_social` land in a paid channel.
- A campaign name containing `shop` or `shopping` (for example `winter_shop_launch`) can match Organic Shopping or Paid Shopping whatever the medium says.

Quick pre-check in SQL, for the output of query Q7 in [bigquery-checks.md](bigquery-checks.md). It flags pairs whose medium and source match none of the manual cues above. It does not test Google's source lists (search, social, video, shopping), so a pair marked false still needs a source-list check before you call it Unassigned. A NULL medium is treated as no match.

```sql
SELECT
  source,
  medium,
  sessions,
  IFNULL(
    REGEXP_CONTAINS(medium, r'^(.*cp.*|ppc|retargeting|paid.*)$')
    OR medium IN ('display', 'banner', 'expandable', 'interstitial', 'cpm',
                  'social', 'social-network', 'social-media', 'sm',
                  'social network', 'social media', 'organic',
                  'referral', 'app', 'link', 'affiliate', 'audio', 'sms',
                  'ai-assistant', 'email', 'e-mail', 'e_mail', 'e mail')
    OR REGEXP_CONTAINS(medium, r'video|mobile|notification')
    OR ENDS_WITH(medium, 'push')
    OR source IN ('email', 'e-mail', 'e_mail', 'e mail', 'sms', 'firebase', '(direct)'),
    FALSE
  ) AS matches_a_cue,
  rows_cross_network_campaign + rows_shop_campaign > 0 AS campaign_may_match
FROM pairs  -- output of Q7
ORDER BY matches_a_cue, sessions DESC;
```

A pair with `campaign_may_match` true can land in Cross-network, Organic Shopping or Paid Shopping because of its campaign name, whatever `matches_a_cue` says. Confirm those with the processed report.

## Unassigned only in a custom group

Signal: Unassigned rose under a custom or primary channel group, but Session default channel group shows no matching rise for the same dates. This is a configuration problem; stop the collection cause tree.

Checks:

- Data API `run_report` with `sessionSourceMedium`, `sessionDefaultChannelGroup` and either `sessionPrimaryChannelGroup` (when the group is primary) or `sessionCustomChannelGroup:<channel group ID>`, metric `sessions`, filtered to Unassigned in the custom dimension. Pairs the default group classifies but the custom group leaves Unassigned are the group's defect. Check the dimension syntax against the live API schema before sending.
- Look for a channel that matches medium `ai-assistant`. Google's help page does not say whether channels it adds later reach existing custom groups, so check the group itself; a group created before 13 May 2026 is the first suspect.
- Read the rule order. Traffic goes to the first channel it matches, so a narrow channel below a broad one never matches, and a broad corrective channel placed high absorbs traffic meant for later channels.

Fix: a draft change to the group (add the missing channel, reorder, narrow a condition), approved by someone with Editor access and recorded in `martech-context/decisions.md`.

Confirm: rerun the comparison. No pair is classified in the default group and Unassigned in the custom group, other than documented exceptions.

## When a custom channel group is defensible

Facts checked on 2026-10-17: a standard property can have 2 custom channel groups and a 360 property 5, in addition to the default, with up to 50 channels each. Custom groups apply to reports retroactively. Changing the primary channel group populates the primary dimension from that point forward only. Traffic goes to the first channel it matches in the group's order. Creating or editing needs Editor or above, under Admin, Data display, Channel groups.

Reclassify history only when all of these hold:

- The original source and medium identify the practice unambiguously, and the registry or the campaign owner confirms it (for example `acme_news / newsletter` is the company newsletter).
- The rule matches that exact pair or a documented list, not a broad pattern that could capture other traffic.
- Collection for that traffic is otherwise healthy (causes B to H ruled out for it).

Never:

- Write a rule that matches `(not set)` source or medium. That invents a source.
- Put a broad rule high in the order. A catch-all early channel absorbs traffic meant for later ones.
- Replace the default group in dashboards without a note. Keep the default group available for comparison and name the custom group's purpose.

Layout for a corrective group:

- Start from the default group's channels, so everything not corrected keeps its default label.
- Write conditions on the unprefixed fields the help page lists for channel groups (Source, Medium, Campaign name, Campaign ID, Source platform, Manual ad content, Default channel group), not on Session-scoped dimension names.
- Add specific corrective channels above the channel they should beat. For AI assistants, use the rule in the next section, not Google's example regex.
- Keep an explicit unknown channel at the bottom so Unassigned stays visible.
- Record the group, rule order, regexes and the date in `martech-context/decisions.md`.

## AI assistant channel in a custom group

Use this when the property's own Referral rows show assistant hosts that GA4 does not label `ai-assistant`. Checked on 2026-10-17.

Google's custom channel group page gives an "AI assistants" example: a source-only regex in a channel placed above Referral, with a note to update the regex as assistants change. Do not copy it. Its alternatives include `^.*ai`, `.*gpt.*`, `.*gemini.*` and `.*bard.*`, which match unrelated sources such as `unrelated.ai`, `gemini.com` and `bombardier.com`. With no medium condition, it also pulls tagged email, paid or partner links whose source names an assistant into the AI channel.

The rule, as one channel with two condition groups joined by OR, placed above Referral:

```text
Channel: AI assistants - verified

Condition group 1:
  Medium exactly matches ai-assistant
OR
Condition group 2:
  Source matches regex
    ^(www\.)?(chatgpt\.com|chat\.openai\.com|gemini\.google\.com|grok\.com|perplexity\.ai|claude\.ai|copilot\.microsoft\.com|chat\.deepseek\.com)$
  AND Medium exactly matches referral
```

- Condition group 1 keeps everything GA4 already labels `ai-assistant`, including assistants not in the host list. If the copied group already has an AI Assistant channel, extend its conditions instead of adding a second channel.
- The host list is a starting candidate, not a verified list. Keep a dated list in `decisions.md`: each host, the product surface, the evidence (a Referral row with that source in this property, with dates) and an owner. Add a host only when the property's own data shows it. Do not add a company's other subdomains: `platform.openai.com` and `community.openai.com` are developer and forum sites, not assistant referrals.
- Case: Google's regex page says Analytics regex is full match and case sensitive by default, while the channel group page says the default channel definitions are not case sensitive. Check how the property treats case in a custom condition with the test list before publishing.

Pre-publish test list (synthetic source / medium pairs and the expected result for the AI channel). Run it in a regex tester with full-match semantics before publishing, and again in the comparison view afterwards:

- `chatgpt.com / referral`: in.
- `www.perplexity.ai / referral`: in.
- `newassistant.example / ai-assistant`: in, through condition group 1.
- `claude.ai / email`: out. A tagged medium keeps its channel.
- `chatgpt / ai`, `chatgpt / referral`, `chatgpt_digest / email`: out. Tagged sources are not hosts.
- `chatgpt.com.evil.com / referral`: out.
- `gemini.com / referral`, `bombardier.com / referral`, `unrelated.ai / referral`: out.
- `platform.openai.com / referral`, `community.openai.com / referral`: out.
- `CHATGPT.COM / referral`: record what the property does, and write the case decision into `decisions.md`.

Confirm after publishing: the AI channel equals the default AI Assistant sessions plus the Referral sessions from the listed hosts, and Referral falls by that second number in the comparison view.
