TikTok Shop Listing Health Check avatar

TikTok Shop Listing Health Check

Pricing

from $3.19 / 1,000 results

Go to Apify Store
TikTok Shop Listing Health Check

TikTok Shop Listing Health Check

Audit a TikTok Shop product and get one 0-100 health score back, broken into review, content, keyword, competitive, creator, category and shop dimensions — each with a ranked, evidence-backed list of specific fixes. Deterministic scoring, not an AI summary; toggle off any dimension to control cost.

Pricing

from $3.19 / 1,000 results

Rating

0.0

(0)

Developer

The Netaji

The Netaji

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

TikTok Shop Listing Health

The Actor diagnoses one or many TikTok Shop products and returns one 0-100 health score per product, built from up to seven independently-scored dimensions — review health, content completeness, keyword coverage, competitive position, creator presence, category benchmark, and shop signal — each with a ranked, evidence-backed list of specific fixes. It does not return product rows; for that, see the TikTok Shop Product Scraper.

{
"product_ids": [
"https://shop.tiktok.com/us/pdp/1730927783781307026",
"1729447567685489298"
],
"region": "US",
"keyword": "wireless earbuds"
}

What the score is built from

health_score is a weighted blend of seven dimensions, each scored 0-100 on its own evidence:

DimensionWeightBuilt from
review_health25Rating average, review volume, and the dominant complaint theme, reusing the same deterministic analysis as TikTok Shop Review Insights.
content_completeness20Image count, title length, whether a description is set, and whether any purchasable variant exists, from the product page.
keyword_coverage15Whether keyword appears in the title, and how many of TikTok's own related search terms for that keyword also appear in it.
competitive_position15Whether the product appears at all in the top results for keyword, and its rating percentile against the products that do.
creator_presence10How many distinct creators have posted a showcase or affiliate video for the product, their combined play count, and whether any carry a paid-partnership label.
category_benchmark10The product's rating percentile against the best-reviewed items TikTok Shop surfaces on the product's own page.
shop_signal5The seller's shop-level star rating.

These weights and the thresholds each dimension checks against (a 4.3★ rating benchmark, 7+ images, a 40-250 character title, 20 creators and 30M combined plays for full creator credit, and so on) are a scoring model this Actor defines to make the report usable, not a number TikTok publishes anywhere. Treat health_score as a heuristic diagnostic, not an official TikTok Shop metric — two reasonable scoring models would rank the same two listings differently at the margin, even if they agree on the direction of a genuine problem like a missing description or zero creator videos.

Where the thresholds come from. They are calibrated against live listings rather than guessed. A sample of eight US listings across hair oil, wireless earbuds, lip gloss and phone chargers measured: images min 3 / median 7 / max 9; title length min 22 / median 196 / max 230; rating median 4.32; creators per listing median 19; combined creator plays median 32.3M. Benchmarks sit at or near those medians, because a benchmark below the 25th percentile never fires and one above the maximum penalises everybody. Two consequences worth knowing: long titles are normal on TikTok Shop and are not penalised until 250 characters, and a listing needs real creator traction — not merely a few videos — to score well on creator presence. The sample is small, so expect these to move as they are re-measured against more listings and more categories.

Partial data does not fail the run

A single product's diagnosis needs up to eight separate upstream lookups. Any one of them can fail, return nothing, or not apply — a product with no keyword set has nothing to check keyword coverage or competitive position against, for instance. When a dimension cannot be scored it is left out of health_score entirely rather than counted as a 0: health_score is always a blend of the dimensions that genuinely produced a score, reweighted so they still sum to 100%. Every excluded dimension is listed in dimensions_unavailable with the reason — fetch_failed, disabled (the input option was turned off), no_keyword_input, no_detail, no_seller_id, no_search_results, no_benchmark_data, or no_own_rating.

A product is only skipped, and only then left uncharged, when every dimension is unavailable — nothing was fetched successfully enough to say anything about the listing. A product whose page fetch fails but whose reviews and creator videos still come back is still diagnosed and still billed, just on fewer dimensions; dimensions_unavailable says exactly which ones and why, so the reduced basis is never hidden.

Cost control

Each product's full diagnosis costs up to eight upstream requests: one each for the product page and its reviews (always run — these carry content_completeness and review_health, the two largest weights), one each for creator videos and the category benchmark (per product), and one each for the keyword-coverage terms, the competitive-position search, and the shop lookup — the last three are cached and fetched only once per distinct keyword or shop across the whole run, not once per product, so a batch of 50 products that share one keyword and one shop still costs one keyword-terms request, one competitive-search request, and one shop-info request in total, not 150.

Five input options turn a dimension off to cut cost further, each shown with what it removes:

  • includeKeywordCoverage (default on) — drops keyword_coverage; removes the related-search-terms request.
  • includeCompetitive (default on) — drops competitive_position; removes the keyword search request.
  • includeCreators (default on) — drops creator_presence; removes one request per product.
  • includeCategoryBenchmark (default on) — drops category_benchmark; removes one request per product.
  • includeShopSignal (default on) — drops shop_signal; removes one request per shop.

review_health and content_completeness cannot be turned off — they are what the product/reviews and product/detail lookups already fetch to build every other dimension, and together they carry 45 of the 100 weighted points.

keyword_coverage and competitive_position both need keyword; without it they report no_keyword_input regardless of their toggle. keyword applies to the whole run, not per product — a batch of unrelated products sharing one keyword will get a keyword-coverage and competitive-position check against a term that may only be relevant to some of them. Run products with different primary keywords in separate calls when that distinction matters.

Result fields

{
"product_id": "1730927783781307026",
"name": "Lifter Glaze Oil Balm with Hyaluronic Acid",
"keyword": "lip oil",
"health_score": 54,
"dimensions": {
"review_health": {
"available": true,
"score": 86,
"weight": 25,
"weight_applied": 27.78,
"evidence": { "rating_average": 4.2, "reviews_analysed": 63, "top_pain_point": { "theme": "Sizing & fit", "share_of_reviews": 0.11 } }
},
"content_completeness": {
"available": true,
"score": 52,
"weight": 20,
"weight_applied": 22.22,
"evidence": { "image_count": 1, "title_length": 42, "sku_count": 1, "has_description": false }
},
"keyword_coverage": {
"available": true,
"score": 0,
"weight": 15,
"weight_applied": 16.67,
"evidence": { "keyword": "lip oil", "primary_keyword_present": false, "related_terms_checked": 3, "related_terms_matched": 0 }
},
"creator_presence": { "available": false, "weight": 10, "reason": "fetch_failed" }
},
"dimensions_unavailable": [{ "dimension": "creator_presence", "reason": "fetch_failed" }],
"fix_items": [
{
"dimension": "category_benchmark",
"message": "Rating trails the shop's own top-reviewed items: 0th percentile of 2 compared, which average 4.65★.",
"observed": 0,
"benchmark": 0.4,
"impact": 11.11
},
{
"dimension": "keyword_coverage",
"message": "Primary keyword \"lip oil\" does not appear anywhere in the title.",
"observed": false,
"benchmark": true,
"impact": 8.34
},
{
"dimension": "content_completeness",
"message": "Only 1 image on the listing, below the 5-image benchmark.",
"observed": 1,
"benchmark": 5,
"impact": 6.22
}
]
}

This is a real record produced by the scorer (from a synthetic fixture rather than a live product, shortened to fit — a full run carries all seven entries in dimensions and one fix_items entry per issue found, not three). weight_applied is the dimension's share of health_score after excluding whatever was unavailable for that product; creator_presence's weight of 10 is missing here, so the other six were rescaled from summing to 90 up to 100 — review_health's weight_applied of 27.78 is its weight of 25 divided by that 90, not 25 itself. impact on a fix item is weight_applied × how many of that dimension's own 100 points the issue cost, so it reads directly as "how many of the 100 health_score points fixing this is worth." The largest impact is not necessarily on the lowest-scoring dimension: category_benchmark scored 0 here but ranks first only because nothing else in that dimension needed fixing once it did; a dimension with several smaller issues can out-rank one with a single larger one, and a heavily-weighted dimension's issues generally rank above equivalent gaps in a lightly-weighted one.

Charging

Each product that produces a health_score — meaning at least one dimension was scoreable — is billed the listing-health event once. A product where every dimension came back unavailable yields no row and is not billed; the run continues to the next product in product_ids rather than failing outright.

Questions

Why is health_score lower than the product's actual star rating would suggest? review_health is only 25 of the 100 weighted points. A product with a strong rating but three images, no description, and zero creator videos scores well on review_health and poorly on content_completeness and creator_presence, and the blended score reflects all three, not just the rating.

Why does competitive_position say the product is missing from its own search results? That is a real finding, not an error: the top results for keyword at the time of the run did not include this product. Combined with a fetch_failed on nothing else, it means the product genuinely is not surfacing for the keyword it is being measured against — one of the more actionable signals this Actor produces, and the reason appears_in_search sits in competitive_position's evidence rather than only in the fix list.

Why is creator_presence scored at 0 instead of marked unavailable? Zero showcase or affiliate videos is a successful lookup that came back empty, not a failed one — a real, common state for a listing and worth reporting as a score rather than hiding as unavailable. fetch_failed is reserved for when the lookup itself could not be completed.

For the underlying product page this Actor's content_completeness and shop_signal dimensions are built from, use the TikTok Shop Product Scraper. For the full ranked pain-point and praise-point analysis behind review_health, use TikTok Shop Review Insights. For the raw creator and affiliate videos behind creator_presence, use the TikTok Shop Creator Videos Scraper.