惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - Franky
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
A
About on SuperTechFans
博客园 - 【当耐特】
Microsoft Security Blog
Microsoft Security Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
The GitHub Blog
The GitHub Blog
雷峰网
雷峰网
博客园_首页
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
IT之家
IT之家
博客园 - 叶小钗
Google DeepMind News
Google DeepMind News
aimingoo的专栏
aimingoo的专栏
博客园 - 聂微东
B
Blog RSS Feed
H
Help Net Security
Recent Announcements
Recent Announcements
阮一峰的网络日志
阮一峰的网络日志
D
DataBreaches.Net
L
LangChain Blog
Vercel News
Vercel News

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
How We Automated Shopify SEO at Scale with Python and Cla...
Thomas Lau · 2026-04-27 · via DEV Community

Thomas Lau

When we launched Reboot Hub — a Hong Kong-based specialist in pre-owned DJI drones and chip-level repair — we had a classic e-commerce SEO problem: 285 products, 50+ collections, and a blog with dozens of articles, all with inconsistent titles, missing schema markup, and zero internal linking strategy.

Doing this manually would take weeks and break the moment we updated anything. So we built a Python automation layer on top of the Shopify Admin API, driven by Claude Code. Here's how it works.

The Problem at Scale

Our Shopify store had accumulated SEO debt fast:

  • 285 product listings with inconsistent title formats ("DJI Mini 4 Pro Used" vs "Pre-Owned Mini 4 Pro" vs "DJI Mini 4 Pro Secondhand")
  • No JSON-LD schema on any page — Google and AI crawlers had no structured signal about what we sold
  • Zero internal links between blog articles and product collections
  • No hreflang despite having Russian and Portuguese market pages live
  • Missing meta descriptions on most products

Fixing this one-by-one in Shopify admin would have taken weeks and been impossible to maintain.

Architecture: Python + Shopify Admin API

All our SEO scripts talk to the Shopify Admin API using a simple shared pattern:

import requests, os
from dotenv import load_dotenv
load_dotenv()

store = os.getenv('SHOPIFY_STORE_URL')
token = os.getenv('SHOPIFY_ACCESS_TOKEN')
headers = {'X-Shopify-Access-Token': token, 'Content-Type': 'application/json'}

Enter fullscreen mode Exit fullscreen mode

Everything is cursor-paginated to handle our full catalogue without hitting rate limits:

def fetch_all_products():
    products = []
    url = f'https://{store}/admin/api/2024-01/products.json?limit=250'
    while url:
        r = requests.get(url, headers=headers)
        products.extend(r.json()['products'])
        link = r.headers.get('Link', '')
        url = next((p.split(';')[0].strip('<>')
                    for p in link.split(',') if 'next' in p), None)
    return products

Enter fullscreen mode Exit fullscreen mode

Step 1: Batch Product Title Standardisation

We defined a brand terminology spec and applied it across all 285 products programmatically:

import re

TITLE_RULES = [
    (r'(?i)used',           'Pre-Owned'),
    (r'(?i)secondhand',     'Pre-Owned'),
    (r'(?i)refurb(ished)?', 'Pristine Pre-Owned'),
]

def normalise_title(title):
    for pattern, replacement in TITLE_RULES:
        title = re.sub(pattern, replacement, title)
    if 'Pre-Owned' in title and not title.startswith('Grade A+'):
        title = 'Grade A+ ' + title
    return title

Enter fullscreen mode Exit fullscreen mode

Running this across all products took about 4 minutes with rate-limit-aware pacing (Shopify allows 2 req/sec on standard plans).

Step 2: JSON-LD Schema Injection into theme.liquid

Rather than using a Shopify app, we inject JSON-LD directly into theme.liquid via the Assets API. This gives full control over the markup:

ORGANIZATION_SCHEMA = (
    "{%- if template == 'index' -%}"
    '<script type="application/ld+json">'
    '{ "@type": "Organization", "name": "Reboot Hub" }'
    "</script>"
    "{%- endif -%}"
)

r = requests.get(
    f'https://{store}/admin/api/2024-01/themes/{THEME_ID}/assets.json',
    params={'asset[key]': 'layout/theme.liquid'},
    headers=headers
)
content = r.json()['asset']['value']
updated = content.replace('</head>', ORGANIZATION_SCHEMA + '</head>', 1)

requests.put(
    f'https://{store}/admin/api/2024-01/themes/{THEME_ID}/assets.json',
    json={'asset': {'key': 'layout/theme.liquid', 'value': updated}},
    headers=headers
)

Enter fullscreen mode Exit fullscreen mode

Step 3: Automated Internal Linking

This is the most complex piece. We built a keyword → URL map and a script that:

  1. Fetches all published blog articles
  2. Parses the HTML body
  3. Finds first occurrences of target keywords outside <h2>, <h3>, <h4>, and existing <a> tags
  4. Wraps them with contextual links
  5. PUTs the updated body back to Shopify
from bs4 import BeautifulSoup

KEYWORD_LINKS = [
    (r'DJI Mini 4 Pro', '/collections/refurbished-dji-mini-series', None),
    (r'DJI Air 3S',     '/collections/refurbished-dji-air-series',  None),
    (r'chip.level repair', '/pages/professional-drone-repair-with-genuine-parts', 'chip-level repair'),
    # 60+ more entries
]

def inject_links(html, article_url):
    soup = BeautifulSoup(html, 'html.parser')
    linked = set()

    for pattern, target, label in KEYWORD_LINKS:
        if target in article_url:
            continue  # skip self-links
        for text_node in soup.find_all(string=re.compile(pattern)):
            parent = text_node.parent
            if parent.name in ('h2', 'h3', 'h4', 'a') or parent.find_parent('a'):
                continue
            if pattern in linked:
                continue  # first occurrence only
            new_tag = soup.new_tag('a', href=f'https://reboot-hub.com{target}')
            new_tag.string = label or str(text_node)
            text_node.replace_with(new_tag)
            linked.add(pattern)

    return str(soup)

Enter fullscreen mode Exit fullscreen mode

Running this across 40+ articles injected ~280 contextual internal links in about 8 minutes.

Step 4: Programmatic 301 Redirects

When we renamed blog URLs, we generated all redirects from a list instead of clicking through Shopify admin:

REDIRECTS = [
    ('/blogs/news/buyer-guide-2026', '/blogs/the-reboot-hub-chronicle/buyer-guide-2026'),
    ('/repair-guide',               '/pages/professional-drone-repair-with-genuine-parts'),
    # 9 total
]

for path, target in REDIRECTS:
    r = requests.post(
        f'https://{store}/admin/api/2024-01/redirects.json',
        json={'redirect': {'path': path, 'target': target}},
        headers=headers
    )
    print(f'{r.status_code}  {path} -> {target}')

Enter fullscreen mode Exit fullscreen mode

Step 5: hreflang for Multilingual Markets

We serve Russian and Portuguese-speaking markets. We injected hreflang tags directly into <head> via the same Assets API approach:

<link rel="alternate" hreflang="en"     href="https://reboot-hub.com{{ canonical_url }}" />
<link rel="alternate" hreflang="ru"     href="https://reboot-hub.com/ru{{ canonical_url }}" />
<link rel="alternate" hreflang="pt-PT"  href="https://reboot-hub.com/pt{{ canonical_url }}" />
<link rel="alternate" hreflang="x-default" href="https://reboot-hub.com{{ canonical_url }}" />

Enter fullscreen mode Exit fullscreen mode

Step 6: llms.txt for AI Crawler Discovery

We also created a llms.txt file — the emerging standard for telling AI systems (ChatGPT, Perplexity, Claude) what your site is about. On Shopify, there's no native way to serve files at the root, so we:

  1. Created a page.llms.liquid template with {% layout none %} to strip HTML wrappers
  2. Created a page at /pages/llms-txt with the plain-text content
  3. Created a Shopify redirect: /llms.txt/pages/llms-txt

The file is now live at reboot-hub.com/llms.txt.

Results After 2 Weeks

What Result
Product titles 285 standardised to brand spec
Schema Organization + WebSite JSON-LD on homepage, FAQPage on all articles
Internal links ~280 contextual links injected across blog
Redirects 9 broken chains fixed
hreflang Live for en/ru/pt-PT
llms.txt Published, AI crawlers can discover site structure

What's Next

We're running a daily pipeline that harvests trending topics from Reddit and Google Trends, generates drafts using a Pinecone RAG index of product manuals, and publishes on a schedule. That's a separate post.

The scripts are internal, but if you're running a Shopify store and want to ask about any specific part — happy to share more in the comments.

Reboot Hub: Grade A+ Pre-Owned DJI drones and chip-level repair, Hong Kong.