Guides / End-to-end tutorials / Winning product & affiliate spy A–Z
Winning product & affiliate spy A–Z
Snipe breakout TikTok Shop (OEC) SKUs by tracking PDP inventory deltas to infer daily unit velocity, reverse-engineering top creator affiliate showcases, scraping video cart anchors, and monitoring LIVE bag rotations.
1. SKU stock-delta velocity & affiliate graph mapping
Public sales counters lag or round into coarse buckets, whereas mobile SDUI /v1/shop/product-page exposes exact per-SKU stock integers alongside flash-sale prices. Polling SKU stock across intervals (filtering restocks where currStock > prevStock) yields unit velocity, while /v1/shop/showcase, /v1/shop/anchors and /v1/shop/live-bag reveal every affiliate video and LIVE pin driving GMV.
| Action | Endpoint | Cost |
|---|---|---|
| Product page | GET /v1/shop/product-page | 25 cr |
| Creator showcase | GET /v1/shop/showcase | 25 cr |
| Shop anchors | GET /v1/shop/anchors | 25 cr |
| LIVE shopping bag | GET /v1/shop/live-bag | 25 cr |
| Shop search | GET /v1/shop/search | 25 cr |
2. Runnable OEC velocity & affiliate spy pipeline
TypeScript SDKPython SDKMCP / cURLoec_affiliate_spy
1import { TikUltra } from 'tikultra'
2
3const shop = new TikUltra({ apiKey: process.env.TIKULTRA_KEY, os: 'android', appFlavour: 'shop', region: 'US', city: 'los_angeles' })
4
5export async function spyProductAndAffiliates(productId: string, prevSkuStock: Record<string, number>, creatorHandle: string, liveRoomId: string) {
6 const [pdp, showcase, liveBag] = await Promise.all([
7 shop.shop.pdp(productId),
8 shop.shop.creatorShowcase(creatorHandle, { count: 30 }),
9 shop.shop.liveBag(liveRoomId),
10 ])
11 let estUnitsSold = 0, estGmvUsd = 0
12 for (const sku of pdp.data.skus ?? []) {
13 const prev = prevSkuStock[sku.sku_id]
14 if (prev !== undefined && sku.stock < prev) {
15 const delta = prev - sku.stock // ignore restock spikes where sku.stock > prev
16 estUnitsSold += delta
17 estGmvUsd += delta * Number(sku.sale_price_usd ?? sku.price ?? 0)
18 }
19 }
20 const posts = await shop.user.posts({ username: creatorHandle, count: 10 })
21 const anchors = await shop.shop.videoProducts(posts.data.items?.[0]?.aweme_id)
22 return {
23 estUnitsSold, estGmvUsd: Math.round(estGmvUsd * 100) / 100,
24 showcaseSkus: (showcase.data.items ?? []).length,
25 videoAnchors: anchors.data.anchors ?? [],
26 pinnedLiveProduct: liveBag.data.pinned_product ?? liveBag.data.items?.[0],
27 }
28}