TikTok Shop Listing Health Check
Pricing
from $3.19 / 1,000 results
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
Maintained by CommunityActor 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:
| Dimension | Weight | Built from |
|---|---|---|
review_health | 25 | Rating average, review volume, and the dominant complaint theme, reusing the same deterministic analysis as TikTok Shop Review Insights. |
content_completeness | 20 | Image count, title length, whether a description is set, and whether any purchasable variant exists, from the product page. |
keyword_coverage | 15 | Whether keyword appears in the title, and how many of TikTok's own related search terms for that keyword also appear in it. |
competitive_position | 15 | Whether the product appears at all in the top results for keyword, and its rating percentile against the products that do. |
creator_presence | 10 | How 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_benchmark | 10 | The product's rating percentile against the best-reviewed items TikTok Shop surfaces on the product's own page. |
shop_signal | 5 | The 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) — dropskeyword_coverage; removes the related-search-terms request.includeCompetitive(default on) — dropscompetitive_position; removes the keyword search request.includeCreators(default on) — dropscreator_presence; removes one request per product.includeCategoryBenchmark(default on) — dropscategory_benchmark; removes one request per product.includeShopSignal(default on) — dropsshop_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.
Related Actors
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.