Forked from henu-wang/shopify-geo-optimization.liquid
Last active
August 29, 2026 00:20
-
-
Save dexit/709c34099d23e1ab9861bfafec1b60f9 to your computer and use it in GitHub Desktop.
Shopify Liquid snippets for JSON-LD structured data, AI crawler meta tags, and GEO optimization
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {% comment %} | |
| ============================================================================ | |
| Shopify Theme: GEO Optimization Snippets for AI Search Visibility | |
| ============================================================================ | |
| Generative Engine Optimization (GEO) snippets for Shopify Liquid themes. | |
| Helps your store appear in AI-generated answers from ChatGPT, Perplexity, | |
| Google AI Overviews, and other generative search engines. | |
| Measure your AI search visibility: https://geoscoreai.com | |
| Installation: | |
| 1. Copy each snippet into your theme's snippets/ directory | |
| 2. Include them in your theme.liquid or relevant templates | |
| 3. Customize variables to match your store's data | |
| Snippets included: | |
| - geo-product-schema.liquid → Product JSON-LD structured data | |
| - geo-faq-schema.liquid → FAQ Page schema for AI answers | |
| - geo-breadcrumb-schema.liquid → BreadcrumbList for navigation context | |
| - geo-ai-meta-tags.liquid → Meta tags for AI crawlers | |
| - geo-llms-txt.liquid → llms.txt content via Shopify Pages | |
| ============================================================================ | |
| {% endcomment %} | |
| {% comment %} | |
| ============================================================ | |
| SNIPPET 1: geo-product-schema.liquid | |
| ============================================================ | |
| Enhanced Product structured data optimized for AI consumption. | |
| Place in: snippets/geo-product-schema.liquid | |
| Include via: {% render 'geo-product-schema', product: product %} | |
| {% endcomment %} | |
| {% comment %} --- BEGIN geo-product-schema.liquid --- {% endcomment %} | |
| <script type="application/ld+json"> | |
| { | |
| "@context": "https://schema.org", | |
| "@type": "Product", | |
| "name": {{ product.title | json }}, | |
| "description": {{ product.description | strip_html | truncate: 5000 | json }}, | |
| "url": "{{ shop.url }}{{ product.url }}", | |
| "image": [ | |
| {% for image in product.images limit: 5 %} | |
| "{{ image | image_url: width: 1200 }}"{% unless forloop.last %},{% endunless %} | |
| {% endfor %} | |
| ], | |
| "sku": {{ product.selected_or_first_available_variant.sku | json }}, | |
| "brand": { | |
| "@type": "Brand", | |
| "name": {{ product.vendor | json }} | |
| }, | |
| "offers": { | |
| "@type": "AggregateOffer", | |
| "priceCurrency": {{ cart.currency.iso_code | json }}, | |
| "lowPrice": {{ product.price_min | money_without_currency | json }}, | |
| "highPrice": {{ product.price_max | money_without_currency | json }}, | |
| "offerCount": {{ product.variants.size }}, | |
| "availability": "https://schema.org/{% if product.available %}InStock{% else %}OutOfStock{% endif %}", | |
| "url": "{{ shop.url }}{{ product.url }}" | |
| } | |
| {% if product.metafields.reviews.rating.value %} | |
| ,"aggregateRating": { | |
| "@type": "AggregateRating", | |
| "ratingValue": {{ product.metafields.reviews.rating.value | json }}, | |
| "reviewCount": {{ product.metafields.reviews.rating_count.value | default: 1 }} | |
| } | |
| {% endif %} | |
| ,"additionalProperty": [ | |
| {% for tag in product.tags limit: 10 %} | |
| { | |
| "@type": "PropertyValue", | |
| "name": "tag", | |
| "value": {{ tag | json }} | |
| }{% unless forloop.last %},{% endunless %} | |
| {% endfor %} | |
| ] | |
| } | |
| </script> | |
| {% comment %} --- END geo-product-schema.liquid --- {% endcomment %} | |
| {% comment %} | |
| ============================================================ | |
| SNIPPET 2: geo-faq-schema.liquid | |
| ============================================================ | |
| FAQ structured data for product pages and informational pages. | |
| AI engines heavily reference FAQ schemas for direct answers. | |
| Place in: snippets/geo-faq-schema.liquid | |
| Include via: {% render 'geo-faq-schema', faqs: page.metafields.custom.faqs.value %} | |
| Store FAQs in a metafield (JSON) with this structure: | |
| [ | |
| { "question": "What is ...?", "answer": "It is ..." }, | |
| { "question": "How does ...?", "answer": "You can ..." } | |
| ] | |
| {% endcomment %} | |
| {% comment %} --- BEGIN geo-faq-schema.liquid --- {% endcomment %} | |
| {% if faqs and faqs.size > 0 %} | |
| <script type="application/ld+json"> | |
| { | |
| "@context": "https://schema.org", | |
| "@type": "FAQPage", | |
| "mainEntity": [ | |
| {% for faq in faqs %} | |
| { | |
| "@type": "Question", | |
| "name": {{ faq.question | json }}, | |
| "acceptedAnswer": { | |
| "@type": "Answer", | |
| "text": {{ faq.answer | json }} | |
| } | |
| }{% unless forloop.last %},{% endunless %} | |
| {% endfor %} | |
| ] | |
| } | |
| </script> | |
| {% comment %} Also render visible FAQ content for AI crawlers that parse HTML {% endcomment %} | |
| <section class="geo-faq-section" itemscope itemtype="https://schema.org/FAQPage"> | |
| <h2>Frequently Asked Questions</h2> | |
| {% for faq in faqs %} | |
| <details itemscope itemprop="mainEntity" itemtype="https://schema.org/Question"{% if forloop.first %} open{% endif %}> | |
| <summary itemprop="name">{{ faq.question }}</summary> | |
| <div itemscope itemprop="acceptedAnswer" itemtype="https://schema.org/Answer"> | |
| <p itemprop="text">{{ faq.answer }}</p> | |
| </div> | |
| </details> | |
| {% endfor %} | |
| </section> | |
| {% endif %} | |
| {% comment %} --- END geo-faq-schema.liquid --- {% endcomment %} | |
| {% comment %} | |
| ============================================================ | |
| SNIPPET 3: geo-breadcrumb-schema.liquid | |
| ============================================================ | |
| BreadcrumbList schema — gives AI engines navigational context | |
| about where a page sits in your store hierarchy. | |
| Place in: snippets/geo-breadcrumb-schema.liquid | |
| Include in theme.liquid or relevant templates. | |
| {% endcomment %} | |
| {% comment %} --- BEGIN geo-breadcrumb-schema.liquid --- {% endcomment %} | |
| {% assign crumbs = "" %} | |
| <script type="application/ld+json"> | |
| { | |
| "@context": "https://schema.org", | |
| "@type": "BreadcrumbList", | |
| "itemListElement": [ | |
| { | |
| "@type": "ListItem", | |
| "position": 1, | |
| "name": "Home", | |
| "item": "{{ shop.url }}" | |
| } | |
| {% if template.name == 'product' %} | |
| ,{ | |
| "@type": "ListItem", | |
| "position": 2, | |
| "name": {{ product.collections.first.title | default: "Products" | json }}, | |
| "item": "{{ shop.url }}{% if product.collections.first %}{{ product.collections.first.url }}{% else %}/collections/all{% endif %}" | |
| } | |
| ,{ | |
| "@type": "ListItem", | |
| "position": 3, | |
| "name": {{ product.title | json }}, | |
| "item": "{{ shop.url }}{{ product.url }}" | |
| } | |
| {% elsif template.name == 'collection' %} | |
| ,{ | |
| "@type": "ListItem", | |
| "position": 2, | |
| "name": {{ collection.title | json }}, | |
| "item": "{{ shop.url }}{{ collection.url }}" | |
| } | |
| {% elsif template.name == 'article' %} | |
| ,{ | |
| "@type": "ListItem", | |
| "position": 2, | |
| "name": {{ blog.title | json }}, | |
| "item": "{{ shop.url }}{{ blog.url }}" | |
| } | |
| ,{ | |
| "@type": "ListItem", | |
| "position": 3, | |
| "name": {{ article.title | json }}, | |
| "item": "{{ shop.url }}{{ article.url }}" | |
| } | |
| {% elsif template.name == 'page' %} | |
| ,{ | |
| "@type": "ListItem", | |
| "position": 2, | |
| "name": {{ page.title | json }}, | |
| "item": "{{ shop.url }}{{ page.url }}" | |
| } | |
| {% endif %} | |
| ] | |
| } | |
| </script> | |
| {% comment %} --- END geo-breadcrumb-schema.liquid --- {% endcomment %} | |
| {% comment %} | |
| ============================================================ | |
| SNIPPET 4: geo-ai-meta-tags.liquid | |
| ============================================================ | |
| Meta tags optimized for AI crawlers and generative search engines. | |
| Controls how ChatGPT, Perplexity, Google Gemini, etc. index your site. | |
| Place in: snippets/geo-ai-meta-tags.liquid | |
| Include in theme.liquid <head>: {% render 'geo-ai-meta-tags' %} | |
| {% endcomment %} | |
| {% comment %} --- BEGIN geo-ai-meta-tags.liquid --- {% endcomment %} | |
| {% comment %} === Core AI Discovery Meta Tags === {% endcomment %} | |
| <meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large"> | |
| {% comment %} Allow specific AI crawlers {% endcomment %} | |
| <meta name="GPTBot" content="index, follow"> | |
| <meta name="Google-Extended" content="index, follow"> | |
| <meta name="CCBot" content="index, follow"> | |
| <meta name="anthropic-ai" content="index, follow"> | |
| <meta name="PerplexityBot" content="index, follow"> | |
| <meta name="Bytespider" content="index, follow"> | |
| {% comment %} === llms.txt Discovery === {% endcomment %} | |
| <link rel="alternate" type="text/plain" href="{{ shop.url }}/pages/llms-txt" title="LLMs.txt"> | |
| {% comment %} === Enhanced Description for AI === {% endcomment %} | |
| {% if template.name == 'product' %} | |
| <meta name="description" content="{{ product.title }} by {{ product.vendor }} — {{ product.description | strip_html | truncate: 300 }}. Shop at {{ shop.name }}."> | |
| <meta property="og:type" content="product"> | |
| <meta property="product:price:amount" content="{{ product.price | money_without_currency }}"> | |
| <meta property="product:price:currency" content="{{ cart.currency.iso_code }}"> | |
| <meta property="product:availability" content="{% if product.available %}in stock{% else %}out of stock{% endif %}"> | |
| {% elsif template.name == 'collection' %} | |
| <meta name="description" content="Shop {{ collection.title }} — {{ collection.description | strip_html | truncate: 250 }}. {{ collection.products_count }} products available at {{ shop.name }}."> | |
| {% elsif template.name == 'article' %} | |
| <meta name="description" content="{{ article.title }} — {{ article.excerpt_or_content | strip_html | truncate: 300 }}"> | |
| <meta property="article:published_time" content="{{ article.published_at | date: '%Y-%m-%dT%H:%M:%S%z' }}"> | |
| <meta property="article:author" content="{{ article.author }}"> | |
| {% elsif template.name == 'page' %} | |
| <meta name="description" content="{{ page.title }} — {{ page.content | strip_html | truncate: 300 }}"> | |
| {% else %} | |
| <meta name="description" content="{{ shop.name }} — {{ shop.description | strip_html | truncate: 300 }}"> | |
| {% endif %} | |
| {% comment %} === Canonical URL (critical for AI deduplication) === {% endcomment %} | |
| <link rel="canonical" href="{{ canonical_url }}"> | |
| {% comment %} --- END geo-ai-meta-tags.liquid --- {% endcomment %} | |
| {% comment %} | |
| ============================================================ | |
| SNIPPET 5: geo-llms-txt.liquid (for Shopify Pages) | |
| ============================================================ | |
| Shopify doesn't allow serving raw .txt files at custom paths, | |
| but you can create a Page with handle "llms-txt" and use a | |
| custom template to output plain-text-like content. | |
| Setup: | |
| 1. Create a new page template: templates/page.llms-txt.liquid | |
| 2. In Shopify admin, create a page with handle "llms-txt" | |
| 3. Assign the "page.llms-txt" template to that page | |
| 4. Add your llms.txt content below | |
| Alternative: Use a Shopify app or serverless function to serve | |
| /llms.txt directly as text/plain. | |
| {% endcomment %} | |
| {% comment %} --- BEGIN templates/page.llms-txt.liquid --- {% endcomment %} | |
| {% layout none %} | |
| {% comment %} | |
| This template serves llms.txt content without the theme layout. | |
| Access at: {{ shop.url }}/pages/llms-txt | |
| {% endcomment %} | |
| <pre style="white-space: pre-wrap; font-family: monospace; max-width: 80ch;"> | |
| # {{ shop.name }} | |
| > {{ shop.description | strip_html }} | |
| ## About | |
| {{ shop.name }} is an online store offering quality products. | |
| Website: {{ shop.url }} | |
| ## Products | |
| {% for collection in collections limit: 10 %} | |
| - [{{ collection.title }}]({{ shop.url }}{{ collection.url }}): {{ collection.description | strip_html | truncate: 150 }} | |
| {% endfor %} | |
| ## Policies | |
| {% if shop.privacy_policy %} | |
| - [Privacy Policy]({{ shop.privacy_policy.url }}) | |
| {% endif %} | |
| {% if shop.terms_of_service %} | |
| - [Terms of Service]({{ shop.terms_of_service.url }}) | |
| {% endif %} | |
| {% if shop.refund_policy %} | |
| - [Refund Policy]({{ shop.refund_policy.url }}) | |
| {% endif %} | |
| {% if shop.shipping_policy %} | |
| - [Shipping Policy]({{ shop.shipping_policy.url }}) | |
| {% endif %} | |
| ## Contact | |
| - Email: {{ shop.email }} | |
| - Address: {{ shop.address.street }}, {{ shop.address.city }}, {{ shop.address.province }}, {{ shop.address.country }} | |
| --- | |
| Measure your AI search visibility at https://geoscoreai.com | |
| </pre> | |
| {% comment %} --- END templates/page.llms-txt.liquid --- {% endcomment %} | |
| {% comment %} | |
| ============================================================ | |
| USAGE GUIDE | |
| ============================================================ | |
| 1. Add to theme.liquid <head>: | |
| {% render 'geo-ai-meta-tags' %} | |
| {% render 'geo-breadcrumb-schema' %} | |
| 2. Add to product template: | |
| {% render 'geo-product-schema', product: product %} | |
| {% render 'geo-faq-schema', faqs: product.metafields.custom.faqs.value %} | |
| 3. Create llms.txt page: | |
| - Create template: templates/page.llms-txt.liquid | |
| - Create page with handle "llms-txt" in Shopify admin | |
| - Assign the template | |
| 4. Monitor your GEO score: | |
| Visit https://geoscoreai.com to measure and track your | |
| store's visibility in AI-powered search engines. | |
| ============================================================ | |
| {% endcomment %} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment