# Canada web-test worksheets

These worksheets help choose a Canadian endpoint requirement and diagnose a configured Shopify Online Store. They contain **no executed Shopify or proxy results**. The Python checker only checks a record's completeness and declared controls; it makes no network requests. Python 3.10 or later and its standard library are sufficient.

## Choose a worksheet

| Your decision | Download | Result to prepare |
| --- | --- | --- |
| Does the job need a Canadian country exit, a province/city exit, or a delivery fixture? | [canada-exit-request.json](https://ipvolt.com/downloads/canada-exit-request.json) or [canada-exit-request.csv](https://ipvolt.com/downloads/canada-exit-request.csv) | A bounded supplier request and acceptance record. |
| Which input changes a configured Shopify Canada experience? | [shopify-canada-worksheet.json](https://ipvolt.com/downloads/canada-localization/shopify-canada-worksheet.json) | A store configuration snapshot and six paired comparisons. |
| Prefer a spreadsheet or printed review? | [shopify-canada-configuration.csv](https://ipvolt.com/downloads/canada-localization/shopify-canada-configuration.csv) **and** [shopify-canada-visits.csv](https://ipvolt.com/downloads/canada-localization/shopify-canada-visits.csv) | Keep both together: the visits sheet alone omits common configuration. The Python checker reads JSON, not edited CSV. |

Download the [Python checker](https://ipvolt.com/downloads/canada-localization/validate_shopify_canada.py) beside the JSON worksheet.

The country request and Shopify experiment have different jobs. A request for a country exit need not include every Shopify comparison. The full experiment is for a reader who controls the store and its test configuration. Headless storefronts, B2B, external localization apps and custom routing need their own documented rules; do not assume this Online Store protocol covers them.

## Decide what needs to change

```text
What is the failed assertion?
|
+-- Target identifies the visitor as outside Canada
|   -> Check target-facing egress and target's location decision.
|   -> Request country-level CA unless the rule actually uses province/city.
|
+-- Expected French/English storefront did not appear
|   -> Check published/assigned translations, language setting and saved choice.
|   -> A Montreal endpoint is not a browser language preference.
|
+-- Wrong market after landing
|   -> Check entry URL, domain strategy and first-visit versus saved state.
|   -> Use the matched IP-only pair before blaming the endpoint.
|
+-- Delivery option differs or is absent
    -> Check full approved address, delivery zone, cart/inventory and checkout path.
    -> A Toronto endpoint does not establish membership in an M5V* delivery zone.
```

Canada Post separates the three-character Forward Sortation Area from the finer Local Delivery Unit. Shopify's local-delivery documentation uses `M5V*` as a postal-zone example. To test such a configured rule, prepare approved full-address fixtures inside and outside that zone, hold egress/cart/stock/checkout conditions fixed and record the available delivery options. Do not invent an address from a plausible postal-code format. The example does not assert that any particular merchant serves M5V or that every address is eligible. [Canada Post postal structure](https://www.canadapost-postescanada.ca/cpc/en/support/articles/addressing-guidelines/postal-codes.page), [Shopify local delivery](https://help.shopify.com/en/manual/fulfillment/setup/delivery-methods/local-delivery).

## Prepare the Shopify record

1. Save a copy of the JSON. Fill `configuration` from the store you control. Record active markets/currencies, domain strategy, the actual country and language redirection toggles, published languages, selector behavior, third-party routing (or `none`) and shipping rules. Record the product/cart, signed-out browser version, viewport, timezone and test window. Keep location permission denied; granting browser coordinates would add another location input.
2. Use a `snapshot_id` and private evidence reference for the configuration. Capture any change as a new snapshot. Shopify documents gradual shipping-setting migration, and province sub-region markets are currently early access with shipping-only customization. Record the setup actually present; the worksheet does not require that feature. [Shipping setup](https://help.shopify.com/en/manual/fulfillment/setup/shipping-rates/setting-up-shipping-rates), [market types](https://help.shopify.com/en/manual/markets/getting-started/market-types).
3. Fill `exits.CA` and `exits.control` from an authorized observation. The control must be outside Canada. `egress_id` is a stable private reference or digest for the observed target-facing IP; reuse it only when the observed IP is unchanged. Record the checker/target and timestamp. A separate IP checker can disagree with Shopify: it is not proof of Shopify's location decision. Keep credentials out of entry URLs and evidence exports.
4. Map `neutral_entry_url`, `canada_entry_url` and `control_market_entry_url` to the actual store URLs. A neutral entry is the agreed first-visit entry for testing location selection, not a preselected Canada path. If there is no suitable common entry, mark the IP comparison inapplicable with the reason. If the neutral and Canada URLs are identical on a shared domain, the URL contrast is inapplicable; the IP comparison can still inspect content.
5. Point `address_fixtures` to approved complete test addresses kept privately. The ON/QC pair compares two delivery destinations. It does not by itself isolate province from street, postal or radius rules. The control-country fixture is separate. Use the same product/cart and reset checkout between visits; stop at the authorized observation point without placing an order.
6. For each pair, set `applicable` to `true` or `false`. Keep skipped pairs with an explanation. For active pairs, write `expected_rule`, its store/source evidence and each visit's `expected_outcome` **before** running it. A comparison need not produce a difference to be valid.

## Run the comparisons

| Pair | Change | Keep fixed | Interpret against the configured rule |
| --- | --- | --- | --- |
| `ip` | CA versus non-CA egress | Same neutral URL, language and separate fresh contexts | Look for the configured country selection; a shared domain might change content with no URL redirect. |
| `url` | Neutral versus explicit Canada entry | Same exit, language and fresh-context policy | Determine the URL/redirection interaction. Do not assume a universal precedence order. |
| `language` | `en-CA` versus `fr-CA` preference | Same Canada entry, exit and fresh context | French requires the store's translation/language configuration. For Shopify's documented `.ca` example, active language redirection and available French lead to `.ca/fr`. |
| `saved` | Fresh context versus deliberately retained selector choice | Same entry, exit, browser preference and product | For the retained visit, start clean, choose English/country manually, then revisit in that same context. Record exact steps. An unrelated old profile contains uncontrolled state. |
| `province` | Approved ON versus QC shipping destination | Same CA entry, exit, language and cart | Compare merchant-defined delivery outcomes. An early-access province market does not imply independent currency, catalog, theme or domain. |
| `cross_border` | Non-CA versus Canadian shipping destination | Same control-market entry, control exit, language and fresh cart | Inspect the final configured checkout experience. A shipping-address change can change the market after the storefront visit. |

Shopify describes IP location, browser language, market URLs, saved selector preferences and final shipping address as distinct inputs. Its documentation also limits automatic redirection to the first visited page and describes domain-dependent behavior. These are platform rules to check against your store, not measurements in this download. [Localization](https://help.shopify.com/en/manual/markets/getting-started/localization), [redirection and language conditions](https://help.shopify.com/en/manual/international/automatic-redirection).

Use a new, isolated browser context for every fresh visit. Do not reuse storage state, an authenticated account, cart or an old service-worker profile. Close the context after recording the result. The saved-choice pair is the deliberate exception. Record actual browser language settings; changing a locale in a tool is not evidence that the browser sent the intended preferences. Keep the run window short and record stock/configuration changes instead of counting those visits as clean comparisons.

For every run, fill the `observation` fields and `actual_inputs` from what happened, then set `status` to `observed`. Record final URL, selected country, market, market evidence, language, currency and relevant delivery options separately. Use a country/market selector or your authorized storefront diagnostic for market evidence; currency and HTTP status alone are insufficient. Shopify exposes selected country/language and applicable country-region market through its [Liquid localization object](https://shopify.dev/docs/api/liquid/objects/localization), but this download supplies no executed instrumentation.

Use `match`, `mismatch` or `inconclusive`. If one of `selected_country`, `market`, `market_evidence`, `language` or `currency` is unavailable, record `unavailable`, choose `inconclusive` and explain the gap. `final_url` still requires an observed HTTP(S) URL; without it the record remains incomplete. Keep failures in the record. A rotated egress ID or changed URL invalidates an unchanged-input comparison even if the page looks right; rerun it with the control restored. Preserve both records. If an exit rotates between different comparison pairs, start a new worksheet record with the new egress ID for that pair; do not reuse the earlier IP evidence.

## Check the file locally

Place the checker and JSON together, then run:

```sh
python3 validate_shopify_canada.py shopify-canada-worksheet.json
```

The untouched download returns `INCOMPLETE_RECORD` and exit code 2 because real store details are missing. A filled plan can return `PLAN_COMPLETE`, which means only that its declarations are complete and its paired inputs are consistent. It is not a Shopify pass.

After recording observations:

```sh
python3 validate_shopify_canada.py shopify-canada-worksheet.json --observations
```

`RECORD_COMPLETE` can include `mismatch` and `inconclusive` outcomes. It means the declared observation fields and controls pass the local checks, not that the store works or the observations are true. To export a visit view after editing JSON:

```sh
python3 validate_shopify_canada.py shopify-canada-worksheet.json --export-csv shopify-canada-visits.csv
```

Keep the configuration JSON with that export. The checker does not validate address existence, geolocation databases, hidden theme/app behavior, prices, tax rules or network quality. No customer addresses, credentials or real purchases are needed to use the empty templates.

Method: original worksheet and offline consistency checks by ipvolt, with Shopify/Canada Post documentation accessed 26 September 2026 UTC. No live Shopify/proxy experiment was performed. Use the country request brief's accepted/total fields only after your own authorized measurements; leave them blank before execution.
