$npx -y skills add 40RTY-ai/shopify-admin-skills --skill shopify-admin-traffic-by-page-reportReport sessions, conversion rate, and bounce rate for every product and collection page using Shopify's analytics API — surfaces which pages earn eyeballs and which convert them.
| 1 | ## Purpose |
| 2 | Queries Shopify's built-in analytics engine (ShopifyQL) to surface session-level traffic data scoped to product and collection pages. Shows which pages are attracting the most traffic, how many sessions convert to orders, and where visitors are bouncing — ready input for SEO prioritisation, merchandising focus, and A/B test targeting. Read-only — no mutations are executed. |
| 3 | |
| 4 | ## Prerequisites |
| 5 | - Authenticated Shopify CLI session: `shopify auth login --store <domain>` |
| 6 | - API scopes: `read_reports` |
| 7 | - Shopify plan: ShopifyQL analytics is available on Basic and above; availability of `sessions` as a data source requires Shopify plan or higher |
| 8 | |
| 9 | ## Parameters |
| 10 | |
| 11 | | Parameter | Type | Required | Default | Description | |
| 12 | |-----------|------|----------|---------|-------------| |
| 13 | | store | string | yes | — | Store domain (e.g., mystore.myshopify.com) | |
| 14 | | format | string | no | human | Output format: `human` or `json` | |
| 15 | | dry_run | bool | no | false | Preview operations without executing mutations | |
| 16 | | days_back | integer | no | 30 | Lookback window in days (e.g., `30` = last 30 days) | |
| 17 | | page_type | string | no | both | Filter to: `products`, `collections`, or `both` | |
| 18 | | top_n | integer | no | 25 | Number of pages to show in the ranked output | |
| 19 | | sort_by | string | no | sessions | Ranking metric: `sessions`, `conversion_rate`, or `bounce_rate` | |
| 20 | |
| 21 | ## Workflow Steps |
| 22 | |
| 23 | 1. **OPERATION:** `shopifyqlQuery` — query (all landing pages) |
| 24 | **Inputs:** ShopifyQL string `FROM sessions SHOW sessions, conversion_rate GROUP BY landing_page_path SINCE -<days_back>d UNTIL today ORDER BY sessions DESC LIMIT 250`; `sessions` and `conversion_rate` are the confirmed available metrics for this data source |
| 25 | **Expected output:** All landing pages with session counts and conversion rates; paginate via `OFFSET` if result count equals 250 |
| 26 | |
| 27 | 2. **In-memory filtering:** Filter rows where `landing_page_path` starts with `/products/` (product pages) or `/collections/` (collection pages); apply `page_type` parameter; sort by `sort_by`; truncate to `top_n`; flag pages with sessions above median and `conversion_rate < 0.02` as `high_traffic_low_conversion` |
| 28 | |
| 29 | > **Note:** ShopifyQL does not support `LIKE`, `WHERE` string prefix filters, or aggregate aliases that shadow reserved column names (`sessions`, `conversion_rate`). All page-type filtering must be done in-memory after fetching all rows. |
| 30 | |
| 31 | ## GraphQL Operations |
| 32 | |
| 33 | ```graphql |
| 34 | # shopifyqlQuery:query (page traffic) — validated against api_version 2025-01 |
| 35 | query TrafficByPage($query: String!) { |
| 36 | shopifyqlQuery(query: $query) { |
| 37 | parseErrors |
| 38 | tableData { |
| 39 | columns { |
| 40 | name |
| 41 | dataType |
| 42 | displayName |
| 43 | } |
| 44 | rows |
| 45 | } |
| 46 | } |
| 47 | } |
| 48 | ``` |
| 49 | |
| 50 | The `$query` variable (single call — all landing pages, filtered in-memory): |
| 51 | ``` |
| 52 | FROM sessions |
| 53 | SHOW sessions, conversion_rate |
| 54 | GROUP BY landing_page_path |
| 55 | SINCE -<days_back>d |
| 56 | UNTIL today |
| 57 | ORDER BY sessions DESC |
| 58 | LIMIT 250 |
| 59 | ``` |
| 60 | |
| 61 | Then filter rows in-memory: |
| 62 | - Product pages: `landing_page_path.startsWith('/products/')` |
| 63 | - Collection pages: `landing_page_path.startsWith('/collections/')` |
| 64 | - `conversion_rate` is returned as a decimal (e.g. `0.016` = 1.6%) — multiply by 100 for display |
| 65 | |
| 66 | > **Confirmed live against 2025-01:** `sessions` (INTEGER) and `conversion_rate` (PERCENT) are the available metrics. `WHERE … LIKE`, `bounce_rate`, `converted_sessions`, and aggregate aliases that shadow reserved names are not supported in ShopifyQL `FROM sessions`. |
| 67 | |
| 68 | ## Session Tracking |
| 69 | |
| 70 | **Claude MUST emit the following output at each stage. This is mandatory.** |
| 71 | |
| 72 | **On start**, emit: |
| 73 | ``` |
| 74 | ╔══════════════════════════════════════════════╗ |
| 75 | ║ SKILL: traffic-by-page-report ║ |
| 76 | ║ Store: <store domain> ║ |
| 77 | ║ Started: <YYYY-MM-DD HH:MM UTC> ║ |
| 78 | ╚══════════════════════════════════════════════╝ |
| 79 | ``` |
| 80 | |
| 81 | **After each step**, emit: |
| 82 | ``` |
| 83 | [N/TOTAL] <QUERY|MUTATION> <OperationName> |
| 84 | → Params: <brief summary of key inputs> |
| 85 | → Result: <count or outcome> |
| 86 | ``` |
| 87 | |
| 88 | **On completion**, emit: |
| 89 | |
| 90 | For `format: human` (default): |
| 91 | ``` |
| 92 | ══════════════════════════════════════════════ |
| 93 | OUTCOME SUMMARY |
| 94 | Lookback window: <days_back> days |
| 95 | Page type: <products|collections|both> |
| 96 | Pages analysed: <n> |
| 97 | Top session page: <path> (<n> sessions) |
| 98 | Top converting page: <path> (<pct>%) |
| 99 | Errors: 0 |
| 100 | Output: traffic_by_page_<date>.csv |
| 101 | ══════════════════════════════════════════════ |
| 102 | ``` |
| 103 | |
| 104 | For `format: json`, emit: |
| 105 | ```json |
| 106 | { |
| 107 | "skill": "traffic-by-page-report", |
| 108 | "sto |