TikTok ad price must match the landing page: burn one price with Sume

TikTok's example: an ad saying 'up to 50% off' while the site says 30% is not allowed. Drive the video and the page from one price variable. Code included.

4 min readSume
All posts

Make the number in the video and the number on the page come from one value. TikTok's Misleading and false content policy says ad content inconsistent with the product's website is not allowed, and its own example is an ad that states 'up to 50% off' while the website says 'up to 30% off'. It also lists an ad that introduces product A while the website shows product B, and a promotion such as 'Prizes to be won!' with no relevant information on the landing page.

The policy page also says ad content and landing pages with mismatched or inconsistent information on promotion, price or discounts, or missing disclaimers, are not allowed. A burned-in price that went stale after a sale ended is the most common way to fail this.

Mismatches TikTok names

Read your clip against the page, not against your memory of the campaign.

Ad-versus-site mismatches in TikTok's policy (read 2026-10-04)
MismatchPolicy example
Discount differsAd: up to 50% off; website: up to 30% off
Product differsAd introduces product A; site shows product B
Promotion unsupportedAd says 'Prizes to be won!'; no information on the page
Page too vagueAd features a clothing brand; site shows generic city images

Burn the price from one variable

With Sume video captions you can burn authored text onto an existing clip using cues, each with text, start and end in seconds. No speech-to-text runs on this path, so the text is exactly what you send. A standalone caption job is $0.20 for a clip up to 60 seconds, and video_url must be a public HTTPS video URL Sume can fetch. Set the same PRICE string on your landing page template and in this call:

import asyncio, json, os, urllib.request

PRICE = "Up to 30% off"

def post(body):
    req = urllib.request.Request(
        "https://api.sume.com/v1/video-captions",
        data=json.dumps(body).encode(),
        headers={
            "Authorization": "Bearer " + os.environ["SUME_API_KEY"],
            "Content-Type": "application/json",
            "Idempotency-Key": "price-cue-001",
        },
        method="POST",
    )
    with urllib.request.urlopen(req) as r:
        return json.load(r)

async def main():
    body = {
        "video_url": "https://media.sume.com/artifacts/example/clean.mp4",
        "cues": [{"text": PRICE, "start": 1.0, "end": 4.0}],
    }
    print(await asyncio.to_thread(post, body))

asyncio.run(main())

Steps

  • Keep one source of truth for the offer (price, percent, end date).
  • Render the landing page and the cue text from it.
  • When the offer changes, re-burn a fresh caption job on the clean master, not on an already captioned file.
  • Check the ad review preview and the live landing page side by side.

Where the number tends to drift

Three places hold a price: the video, the ad text, and the landing page. The ad text and the page are usually driven from a feed; the video is a file, and files do not update themselves. That is why the video is the one that goes stale.

A simple rule is to treat the burned-in text as a build artifact. When the offer string changes, a script re-runs the caption job against the same clean master and swaps the creative. The call above is idempotent per Idempotency-Key, so give each offer version its own key, such as one that includes the date, and a retry after a network failure will not create a second job.

Caveat

Burn onto a clean master each time. TikTok's rule is about consistency at review and afterwards; an expired offer in an already-live video is still inconsistent with the page. Replace the creative when the offer ends.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume