shopify-theme-devtools 2.2.1 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,13 +24,15 @@ A powerful in-browser developer tools panel for Shopify theme development. Inspe
24
24
 
25
25
  ### Core Panels
26
26
 
27
+ - **AI Assistant** — GPT-powered theme debugging with full context access (cart, metafields, analytics, accessibility, and more)
27
28
  - **Objects Inspector** — Browse `shop`, `product`, `collection`, `customer`, `cart` and more with deep search and collapsible tree view
28
29
  - **Metafields Viewer** — Explore metafields across all resources and namespaces with type labels
29
30
  - **Cart Panel** — Real-time cart state with add/remove/quantity controls, cart history with restore, and attribute editing
30
31
  - **Console** — Chrome DevTools-style console with Liquid expression evaluator, and autocomplete
31
32
  - **Localization** — Markets, currencies, languages, and country data with quick switcher
32
33
  - **SEO Inspector** — Meta tags, Open Graph, Twitter Cards, and structured data (JSON-LD) validation
33
- - **Analytics Viewer** — Detects Google Analytics, Facebook Pixel, and other tracking codes
34
+ - **Analytics Viewer** — Captures GA4, Facebook Pixel, TikTok, Pinterest, Snapchat, Klaviyo, Shopify Analytics, and dataLayer events
35
+ - **Accessibility Scanner** — WCAG compliance checker with issue severity, suggested fixes, and score
34
36
  - **Storage Inspector** — Browse and edit localStorage, sessionStorage, and cookies
35
37
  - **Apps Panel** — Lists installed Shopify apps detected on the page
36
38
  - **Info Panel** — Theme details, template info, and request metadata
@@ -96,6 +98,72 @@ The Console panel includes an interactive expression evaluator for testing Liqui
96
98
  - **Cart History** — View previous cart states with timestamps and restore any snapshot
97
99
  - **Attribute Editor** — Modify cart attributes and notes
98
100
  - **Diff View** — See what changed between cart states
101
+ - **Scenario Builder** — Create and save cart scenarios for quick testing
102
+ - **Cart Tests** — Write validation rules to automatically test cart items
103
+
104
+ ### Cart Tests
105
+
106
+ The Cart Tests feature lets you create custom validation rules to ensure cart items meet your business requirements. Tests can be run manually or automatically whenever the cart changes.
107
+
108
+ **Rule Types:**
109
+
110
+ | Type | Description | Example |
111
+ |------|-------------|---------|
112
+ | **Property Dependency** | If item has property X, must have properties Y, Z | GWP items require `_gwp_price` and `_gwp_source` |
113
+ | **Field Value** | If field equals X, another field must meet condition | Gift Cards must have quantity = 1 |
114
+ | **Cart Composition** | If item X exists, item Y must also exist | Electronics require warranty item |
115
+ | **Quantity** | Min/max/multiple constraints per-item or cart-total | Max 10 per item, cart total max 50 |
116
+
117
+ **Features:**
118
+
119
+ - **Pre-built Templates** — 16 ready-to-use templates for common scenarios
120
+ - **Auto-run** — Toggle to run all tests whenever cart changes
121
+ - **Import/Export** — Save and share test configurations as JSON
122
+ - **Inline Results** — Pass/fail badges show test status at a glance
123
+
124
+ ### AI Assistant
125
+
126
+ An intelligent GPT-powered assistant that understands your Shopify theme context. Ask questions, debug issues, and generate Liquid code with full access to your page data.
127
+
128
+ **Setup:**
129
+ 1. Open the AI panel
130
+ 2. Enter your OpenAI API key (stored locally, never sent anywhere except OpenAI)
131
+ 3. Start asking questions
132
+
133
+ **What AI Can Access:**
134
+ - Page/template info, shop details, current resource (product/collection/page)
135
+ - Customer data (if logged in)
136
+ - Cart state and cart history
137
+ - Metafields for all resources
138
+ - Section schemas (from theme editor data)
139
+ - HTML structure of the page
140
+ - Network requests and responses
141
+ - Cookies, localStorage, sessionStorage
142
+ - Liquid errors detected on the page
143
+ - Accessibility scan results
144
+ - Analytics events (GA4, Facebook Pixel, TikTok, Pinterest, Snapchat, Klaviyo, Shopify, dataLayer)
145
+
146
+ **Context Modes:**
147
+ | Mode | Description |
148
+ |------|-------------|
149
+ | **Auto** | Smart detection - includes relevant context based on your question |
150
+ | **Minimal** | Basic page info and cart only (faster responses) |
151
+ | **Full** | Everything including cookies, storage, analytics, accessibility |
152
+ | **Custom** | Pick exactly which context to include |
153
+
154
+ **Example Questions:**
155
+ - "What data is available on this page?"
156
+ - "Help me write Liquid to display the product price with compare at price"
157
+ - "Why isn't my add to cart button working?"
158
+ - "What analytics events are firing on this page?"
159
+ - "Are there any accessibility issues I should fix?"
160
+
161
+ **Features:**
162
+ - **Streaming responses** — See answers as they're generated
163
+ - **Syntax highlighting** — Code blocks with Liquid, JavaScript, and JSON highlighting
164
+ - **Conversation history** — Per-page conversations persist in session storage
165
+ - **Search** — Find text across your conversation history
166
+ - **Copy code** — One-click copy for any code block
99
167
 
100
168
  ### Liquid Error Detection
101
169
 
@@ -107,6 +175,33 @@ Automatically scans the page for common Liquid issues:
107
175
  - Schema validation errors
108
176
  - Deprecation warnings
109
177
 
178
+ ### Analytics Panel
179
+
180
+ Captures and inspects analytics events from multiple tracking providers in real-time.
181
+
182
+ **Supported Providers:**
183
+ | Provider | Detection |
184
+ |----------|-----------|
185
+ | **Google Analytics 4** | `gtag()` calls |
186
+ | **Google Analytics Universal** | `ga()` calls |
187
+ | **Facebook Pixel** | `fbq()` calls |
188
+ | **TikTok Pixel** | `ttq.track()` calls |
189
+ | **Pinterest Tag** | `pintrk()` calls |
190
+ | **Snapchat Pixel** | `snaptr()` calls |
191
+ | **Klaviyo** | `_learnq.push()` calls |
192
+ | **Shopify Analytics** | `Shopify.analytics.publish()` |
193
+ | **Shopify Web Pixels** | `analytics.subscribe()` |
194
+ | **DataLayer** | `dataLayer.push()` |
195
+
196
+ **Features:**
197
+ - **Live capture** — Events appear as they fire
198
+ - **Conversion tracking** — Highlights purchase, add_to_cart, and other conversion events
199
+ - **Filtering** — Filter by provider or search event names/data
200
+ - **Deduplication** — Groups duplicate events fired within 500ms
201
+ - **Export** — Download captured events as JSON
202
+ - **Pause/Resume** — Stop capturing to analyze current events
203
+ - **Persistence** — Events persist across page navigations (session storage)
204
+
110
205
  ### Network Panel
111
206
 
112
207
  Captures and inspects Shopify API requests with powerful debugging tools:
@@ -163,6 +258,16 @@ npx shopify-theme-devtools init --inject
163
258
  | `--inject` | Automatically add render tag to `layout/theme.liquid` |
164
259
  | `--force` | Overwrite existing files without prompting |
165
260
 
261
+ The CLI automatically detects and injects your `metafields.json` schema from `.shopify/metafields.json` (or theme root), enabling devtools to show all defined metafields.
262
+
263
+ #### Syncing Metafields
264
+
265
+ When your metafields change over time, run the sync command to update the schema without overwriting other customizations:
266
+
267
+ ```bash
268
+ npx shopify-theme-devtools sync
269
+ ```
270
+
166
271
  ```bash
167
272
  # Examples
168
273
  npx shopify-theme-devtools init # Uses CDN (recommended)
@@ -200,11 +305,13 @@ The devtools panel automatically appears on **unpublished/development themes onl
200
305
 
201
306
  | Panel | Description |
202
307
  |-------|-------------|
308
+ | **AI** | GPT-powered assistant with full theme context access |
203
309
  | **Objects** | Inspect all Liquid objects with search and tree navigation |
204
310
  | **Metafields** | Browse metafields by resource (product, collection, shop, etc.) |
205
- | **Cart** | Live cart state, history snapshots, and manipulation tools |
311
+ | **Cart** | Live cart state, history, scenarios, tests, and manipulation tools |
206
312
  | **Locale** | Markets, currencies, languages with locale switching |
207
- | **Analytics** | Detected tracking codes and analytics configuration |
313
+ | **Analytics** | Live event capture for GA4, FB Pixel, TikTok, Pinterest, Klaviyo, Shopify |
314
+ | **Accessibility** | WCAG compliance scanner with score and suggested fixes |
208
315
  | **SEO** | Meta tags, Open Graph, Twitter Cards, JSON-LD structured data |
209
316
  | **Apps** | Installed Shopify apps detected on the page |
210
317
  | **Network** | API request monitor with edit/replay, cart diffs, and error diagnosis |
@@ -284,11 +391,17 @@ src/
284
391
  │ ├── components/
285
392
  │ │ ├── theme-devtools.js # Main component with tab management
286
393
  │ │ ├── object-inspector.js # Tree view inspector
287
- │ │ └── panels/ # Panel components
394
+ │ │ └── panels/ # Panel components (ai, cart, analytics, etc.)
395
+ │ ├── lib/
396
+ │ │ └── cart-test-templates.js # Pre-built cart test templates
288
397
  │ ├── services/
398
+ │ │ ├── ai.js # OpenAI API integration
399
+ │ │ ├── analytics.js # Analytics event interceptor
400
+ │ │ ├── accessibility.js # Accessibility scanning service
289
401
  │ │ ├── cart.js # Cart API with history
290
402
  │ │ ├── product.js # Product API (variants/images)
291
403
  │ │ ├── context.js # Liquid context parser
404
+ │ │ ├── context-serializer.js # AI context serialization
292
405
  │ │ ├── expression-evaluator.js # Liquid expression engine
293
406
  │ │ ├── network-interceptor.js # Fetch/XHR interceptor with persistence
294
407
  │ │ └── settings.js # User preferences
package/bin/cli.js CHANGED
@@ -47,6 +47,7 @@ ${COLORS.bold}Usage:${COLORS.reset}
47
47
 
48
48
  ${COLORS.bold}Commands:${COLORS.reset}
49
49
  init Initialize devtools in your Shopify theme
50
+ sync Sync metafields schema from .shopify/metafields.json
50
51
 
51
52
  ${COLORS.bold}Options for init:${COLORS.reset}
52
53
  --local Copy JS/CSS to assets folder instead of using CDN
@@ -58,6 +59,7 @@ ${COLORS.bold}Examples:${COLORS.reset}
58
59
  npx shopify-theme-devtools init
59
60
  npx shopify-theme-devtools init --local
60
61
  npx shopify-theme-devtools init --local --inject
62
+ npx shopify-theme-devtools sync
61
63
  `);
62
64
  }
63
65
 
@@ -77,6 +79,57 @@ function copyFile(src, dest, force = false) {
77
79
  return true;
78
80
  }
79
81
 
82
+ function findMetafieldsSchema(themeRoot) {
83
+ // Look for metafields.json in common locations
84
+ const possiblePaths = [
85
+ join(themeRoot, '.shopify', 'metafields.json'),
86
+ join(themeRoot, 'metafields.json'),
87
+ join(themeRoot, 'config', 'metafields.json'),
88
+ ];
89
+
90
+ for (const schemaPath of possiblePaths) {
91
+ if (existsSync(schemaPath)) {
92
+ try {
93
+ const content = readFileSync(schemaPath, 'utf-8');
94
+ // Validate it's valid JSON
95
+ JSON.parse(content);
96
+ return { path: schemaPath, content };
97
+ } catch {
98
+ // Invalid JSON, skip
99
+ }
100
+ }
101
+ }
102
+
103
+ return null;
104
+ }
105
+
106
+ function injectMetafieldsSchema(liquidContent, schemaContent) {
107
+ // Replace the default empty schema with the actual schema
108
+ const defaultSchema = `{%- capture devtools_metafields_schema -%}
109
+ {
110
+ "article": [],
111
+ "blog": [],
112
+ "collection": [],
113
+ "company": [],
114
+ "company_location": [],
115
+ "location": [],
116
+ "market": [],
117
+ "order": [],
118
+ "page": [],
119
+ "product": [],
120
+ "variant": [],
121
+ "shop": [],
122
+ "customer": []
123
+ }
124
+ {%- endcapture -%}`;
125
+
126
+ const newSchema = `{%- capture devtools_metafields_schema -%}
127
+ ${schemaContent.trim()}
128
+ {%- endcapture -%}`;
129
+
130
+ return liquidContent.replace(defaultSchema, newSchema);
131
+ }
132
+
80
133
  function patchLiquidForLocal(content) {
81
134
  // Change CDN to asset_url
82
135
  let patched = content.replace(
@@ -198,6 +251,13 @@ async function init(args) {
198
251
  '{%- assign devtools_local = false -%}'
199
252
  );
200
253
 
254
+ // Auto-detect and inject metafields schema
255
+ const metafieldsSchema = findMetafieldsSchema(themeRoot);
256
+ if (metafieldsSchema) {
257
+ liquidContent = injectMetafieldsSchema(liquidContent, metafieldsSchema.content);
258
+ success(`Injected metafields schema from ${metafieldsSchema.path.replace(themeRoot + '/', '')}`);
259
+ }
260
+
201
261
  if (useLocal) {
202
262
  liquidContent = patchLiquidForLocal(liquidContent);
203
263
  }
@@ -255,6 +315,67 @@ async function init(args) {
255
315
  console.log();
256
316
  }
257
317
 
318
+ async function sync() {
319
+ const cwd = process.cwd();
320
+
321
+ console.log();
322
+ log('Shopify Theme Devtools', COLORS.bold);
323
+ console.log();
324
+
325
+ // Detect theme root
326
+ const themeRoot = detectThemeRoot(cwd);
327
+
328
+ if (!themeRoot) {
329
+ error('Could not detect Shopify theme directory');
330
+ info('Make sure you run this command from your theme root');
331
+ info('(should contain layout/, snippets/, templates/ folders)');
332
+ process.exit(1);
333
+ }
334
+
335
+ const snippetsDir = join(themeRoot, 'snippets');
336
+ const liquidDest = join(snippetsDir, 'theme-devtools-bridge.liquid');
337
+
338
+ // Check if snippet exists
339
+ if (!existsSync(liquidDest)) {
340
+ error('Devtools snippet not found');
341
+ info('Run "npx shopify-theme-devtools init" first');
342
+ process.exit(1);
343
+ }
344
+
345
+ // Find metafields schema
346
+ const metafieldsSchema = findMetafieldsSchema(themeRoot);
347
+
348
+ if (!metafieldsSchema) {
349
+ error('No metafields.json found');
350
+ info('Looked in: .shopify/metafields.json, metafields.json, config/metafields.json');
351
+ process.exit(1);
352
+ }
353
+
354
+ // Read current snippet
355
+ let liquidContent = readFileSync(liquidDest, 'utf-8');
356
+
357
+ // Replace the metafields schema using a regex that matches any JSON content
358
+ const schemaRegex = /\{%- capture devtools_metafields_schema -%\}[\s\S]*?\{%- endcapture -%\}/;
359
+
360
+ if (!schemaRegex.test(liquidContent)) {
361
+ error('Could not find metafields schema section in snippet');
362
+ info('The snippet may be corrupted. Run "npx shopify-theme-devtools init --force" to regenerate');
363
+ process.exit(1);
364
+ }
365
+
366
+ const newSchema = `{%- capture devtools_metafields_schema -%}
367
+ ${metafieldsSchema.content.trim()}
368
+ {%- endcapture -%}`;
369
+
370
+ liquidContent = liquidContent.replace(schemaRegex, newSchema);
371
+
372
+ // Write updated snippet
373
+ writeFileSync(liquidDest, liquidContent);
374
+ success(`Synced metafields schema from ${metafieldsSchema.path.replace(themeRoot + '/', '')}`);
375
+
376
+ console.log();
377
+ }
378
+
258
379
  // Parse arguments
259
380
  const args = process.argv.slice(2);
260
381
  const command = args[0];
@@ -266,6 +387,8 @@ if (!command || command === '--help' || command === '-h') {
266
387
 
267
388
  if (command === 'init') {
268
389
  init(args);
390
+ } else if (command === 'sync') {
391
+ sync();
269
392
  } else {
270
393
  error(`Unknown command: ${command}`);
271
394
  printHelp();