Reading a Competitor's Launch Cadence from published_at
Most competitor research is a snapshot: what they sell today, what they charge today. But every Shopify store quietly publishes its own history, and almost nobody reads it. Each product in the public catalog carries a published_at timestamp — the moment it went live on the storefront. Collect them, group them by month, and you have a competitor's launch history going back to the day they opened.
It costs one HTTP request and about thirty seconds. It tells you more about where a business is heading than any pricing table.
Where the timestamp lives
The public catalog endpoint we covered in the /products.json trick returns every published product as JSON, and each one includes three dates:
created_at— when the product record was created in the admin. Often weeks before it went live, sometimes years before if it started as a draft.published_at— when it became visible on the online store. This is the launch date, and the one you want.updated_at— the last edit of any kind: a price change, a typo fix, an inventory sync. Noisy, but useful for spotting which products are actively maintained.
For cadence analysis, published_at is the only one that maps onto a real business event: "we put this in front of customers on this date."
Getting three years of history in one line
Pull the catalog, extract the year-month from each timestamp, count them:
curl -s "https://competitor.com/products.json?limit=250" \
| jq -r '.products[].published_at[0:7]' \
| sort | uniq -c
Output looks like this:
3 2025-09
2 2025-10
1 2025-11
14 2025-12
2 2026-01
4 2026-03
11 2026-04
1 2026-06
12 2026-07
That's a seasonal batch launcher — small trickle most months, then a dozen products at once in December, April and July. You've just learned their release rhythm without visiting a single product page.
One caveat before you trust the numbers: limit=250 is the maximum per request, so a store with more products needs pagination. Add &page=2, &page=3 until you get an empty array, and concatenate. If you skip this on a 900-product store you'll be reading the first 250 products in catalog order, which is not the same as the first 250 by date.
Want the calendar rather than the count? Drop the grouping and sort the raw dates:
curl -s "https://competitor.com/products.json?limit=250" \
| jq -r '.products[] | "\(.published_at[0:10]) \(.title)"' \
| sort
The four patterns, and what each one means
Once you have monthly counts, competitors fall into recognisable shapes.
The steady drip — two to five new products every month, almost no empty months. This is a store with an operating process: a supplier relationship that keeps producing, or an in-house product person with a roadmap. They're hard to surprise and hard to out-launch. Compete on positioning, service and content rather than on breadth.
The seasonal batch — nothing for months, then ten to thirty products in a single week. Classic in apparel, home goods, and anything with collections. The most useful thing about this pattern is that it's predictable: if the last three drops landed in late March, late July and late November, you know roughly when the next one is coming and can plan your own promo not to collide with it — or deliberately to.
The sprint and stall — heavy activity for a few months, then a long silence. Sometimes it means the owner got busy elsewhere, sometimes it means the store is being wound down, sometimes it means they found their winners and stopped experimenting. Combine it with stock data: a stalled catalog where sold-out items never come back is a store quietly closing, and that's an opening.
The blast — sixty products published on one day, then a trickle. Almost always a catalog import: a dropshipper syncing a supplier feed, a migration from another platform, or a new store launching with a bought catalog. It tells you little about their product strategy but a lot about their operating model — and dropship-blast catalogs tend to be priced reactively, which changes how you read their price moves.
Going one level deeper
The month histogram is the headline. Three cheap follow-ups make it actionable.
What are they launching into? Group recent launches by product_type or by tags and compare against the whole catalog. A store whose last twenty products are all in one category is placing a bet — and if it's a category you own, you'll want to know now rather than after their SEO catches up.
curl -s "https://competitor.com/products.json?limit=250" \
| jq -r '[.products[] | select(.published_at > "2026-05")] | group_by(.product_type)[]
| "\(length) \(.[0].product_type)"' \
| sort -rn
How deep is each launch? Count variants per new product. A competitor moving from three-variant products to twelve-variant ones is adding sizes or colourways — a real inventory commitment, not a test.
Do launches survive? Products published six months ago that are now permanently out of stock, or that have quietly vanished from the catalog, are failed experiments. A store with a high launch rate and a high disappearance rate is throwing things at the wall; you can let them pay for the testing and copy only what stays.
Four ways published_at will lie to you
This is public data, not a reliable audit log, and there are specific ways it misleads.
Republishing resets it. If a merchant unpublishes a product — seasonal item, out of stock for a while, temporarily hidden — and publishes it again, the timestamp becomes the new date. That two-year-old bestseller shows up in your histogram as a July launch. Sudden "new products" that have hundreds of reviews or a mature-looking URL handle are usually this.
Migrations flatten history. A store that moved to Shopify from WooCommerce or BigCommerce will show its entire catalog published on the migration date. If you see 400 products on a single day and the store clearly predates it, you're looking at an import, not a launch.
Drafts and scheduled publishing shift it. Merchants can schedule a publish date, and some backdate products deliberately. Treat individual dates as approximate; trust the aggregate pattern.
You only see what's public. Products hidden from the online store channel, B2B-only catalogs, and anything behind a password page are invisible here. Nothing tells you what they've delisted, either — you only ever see what's live right now, which is why comparing snapshots over time beats a one-off read. That limitation applies to the whole approach, and we've been explicit about it before in our 30-minute competitor analysis.
Turning cadence into decisions
Interesting data that doesn't change behaviour is a hobby. Four things a cadence read should actually change:
- Your own launch timing. If a competitor reliably drops in the second week of September and you're in the same category, launching the same week means fighting for the same attention. Two weeks earlier is usually free.
- Which competitors deserve a watch slot. A store that hasn't published anything in eight months is not going to surprise you. Give the slot to the one launching monthly.
- What to stock next. When two independent competitors both launch into the same sub-category within a quarter, that's a market signal you can verify cheaply before committing your own money.
- How seriously to take a price move. A price cut from a store in launch-sprint mode usually means promotion. The same cut from a stalled store often means clearing inventory. Same number, different meaning — the framing we use in should you match a competitor's price.
Or just get told when they launch
Running the histogram by hand once per competitor is a good afternoon's work. Doing it every week isn't. StoreSentry watches your competitors' Shopify and WooCommerce catalogs daily and emails or Telegrams you when something new appears — plus price moves and stockouts. Free for 2 competitors.
Install the app — free for 2 competitors →Being honest about the free version
Everything above works with curl and jq, costs nothing, and doesn't require our app or anyone else's. For a one-time read of three competitors — which is genuinely the right move before you pay for any tool — the manual approach is better: you'll look at the raw dates, notice the migration artefacts, and build intuition that a dashboard would hide from you.
What tooling adds is the second dimension: time. A single catalog pull shows what's live today; comparing pulls day after day shows what appeared, disappeared, changed price or went out of stock in between — the difference we drew in price monitoring vs page monitoring. If you'd rather build that yourself, saving a dated JSON file per competitor per day into a folder gets you 80% of the way there for the cost of a cron entry.
The one-line version
Pull /products.json, count published_at by month, and read the shape: steady drip, seasonal batch, sprint-and-stall, or import blast. Discount republishes and migrations, then use the pattern to time your own launches and to decide which competitors are worth watching at all.