Fire the TikTok Pixel only after visitors accept targeting cookies

Tag the TikTok Pixel base code with the targeting category of TermsFeed Free Cookie Consent, or load the pixel with ttq.holdConsent() and send ttq.grantConsent() from the scripts_specific_loaded callback. Both setups stop the pixel from sharing events with TikTok until the visitor accepts advertising cookies. With the tagged base code, the browser requests nothing from TikTok before consent.

The TikTok Pixel identifies visitors for ad measurement, optimization, and audiences, so it needs consent first for visitors in the EU and the UK. The TikTok Business Help Center article About using cookies with TikTok Pixel points advertisers to a consent management platform to use the pixel in line with visitor consent. Each approach takes about 10 minutes.

Approach 1: Tag the TikTok Pixel base code with targeting

The TikTok Pixel base code is one inline script that loads events.js from analytics.tiktok.com: tag it with targeting. TikTok asks for the base code in <head>: place it near the top of <head>, below any Consent Mode default. The tagged base code still runs from any place in the page markup. Cookie Consent reads tagged scripts when run() starts, which the generator code delays until the browser has read the whole page.

Replace YOUR_PIXEL_ID in this tagged base code with the pixel ID from TikTok Events Manager. To start from your own pixel instead, copy the base code from the pixel setup screen in Events Manager and change its opening <script> tag the same way. Compare the tagged base code with the template on the TikTok developer page Install Pixel using code.

<script type="text/plain" data-cookie-consent="targeting">
//Part1
!function (w, d, t) {
  w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.instance=function(t){for(var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e},ttq.load=function(e,n){var i="https://analytics.tiktok.com/i18n/pixel/events.js";ttq._i=ttq._i||{},ttq._i[e]=[],ttq._i[e]._u=i,ttq._t=ttq._t||{},ttq._t[e]=+new Date,ttq._o=ttq._o||{},ttq._o[e]=n||{};var o=document.createElement("script");o.type="text/javascript",o.async=!0,o.src=i+"?sdkid="+e+"&lib="+t;var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(o,a)};

//Part 2
  ttq.load('YOUR_PIXEL_ID');
  ttq.page();
}(window, document, 'ttq');
</script>

The browser skips a text/plain script. Once the visitor accepts targeting, Cookie Consent runs the base code with no reload, and ttq.page() records the page view.

Put every TikTok event call, such as ttq.track('Purchase', ...), in a script tagged with targeting below the base code. Cookie Consent runs the tagged scripts of one category in page order, so the event runs after the base code defines ttq. TikTok asks new pixel setups to send Purchase in place of the older CompletePayment event. Check the renamed events in the TikTok Business Help Center with How to adopt the updated TikTok standard events.

Add a tagged purchase event like this one to the order confirmation page, and replace the value and the currency with the values of the order.

<script type="text/plain" data-cookie-consent="targeting">
  ttq.track('Purchase', {
    value: 49.90,
    currency: 'USD'
  });
</script>

Cookie Consent runs the base code and the event at once for a visitor who accepts on the confirmation page itself, with no reload, so TikTok receives that event. Check the order rules and the attributes a tagged script keeps in Block Scripts Until Consent.

Approach 2: Load the pixel with ttq.holdConsent and grant from the callback

Keep the base code untagged, add ttq.holdConsent() before ttq.load(), and send ttq.grantConsent() from scripts_specific_loaded when Cookie Consent releases targeting. TikTok calls this the default opt-out solution of its pixel consent mode. The pixel queues its events and shares none with TikTok until it receives the grant, according to the TikTok developer page Pixel Cookie consent mode.

TikTok asks you to add holdConsent, revokeConsent, and grantConsent to the ttq.methods list of the base code. This base code from the TikTok consent mode page adds the 3 methods and calls ttq.holdConsent(). It stays untagged near the top of <head>, below any Consent Mode default. Replace YOUR_PIXEL_ID with your pixel ID.

<script>
 // Add the new methods "holdConsent", "revokeConsent", and "grantConsent" to the ttq.methods array
!function (w, d, t) {
  w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie","holdConsent","revokeConsent","grantConsent"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.instance=function(t){for(var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e},ttq.load=function(e,n){var i="https://analytics.tiktok.com/i18n/pixel/events.js";ttq._i=ttq._i||{},ttq._i[e]=[],ttq._i[e]._u=i,ttq._t=ttq._t||{},ttq._t[e]=+new Date,ttq._o=ttq._o||{},ttq._o[e]=n||{};var o=document.createElement("script");o.type="text/javascript",o.async=!0,o.src=i+"?sdkid="+e+"&lib="+t;var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(o,a)};

  // Hold consent before 'ttq.load' is called
  ttq.holdConsent();
  ttq.load('YOUR_PIXEL_ID');
  ttq.page();
}(window, document, 'ttq');
</script>

"callbacks_force": true makes the callback run for targeting although no script carries that tag, and the callback then sends the grant. Add the callbacks and callbacks_force options to your run() call, next to the options the TermsFeed generator writes.

"callbacks": {
  "scripts_specific_loaded": function (level) {
    switch (level) {
      case 'targeting':
        if (window.ttq && typeof window.ttq.grantConsent === 'function') {
          window.ttq.grantConsent();
        }
        break;
    }
  }
},
"callbacks_force": true

TikTok shares the events queued on the page, the page view among them, once ttq.grantConsent() runs. The callback only grants consent. The ttq.holdConsent() call in the base code holds the events again on every page load. The pixel then does not share the events of a visitor who declines, or those of a visitor who withdraws targeting from the next page on. Event calls such as ttq.track('Purchase', ...) stay untagged in this approach, and ttq.holdConsent() queues them with the other events. Look up every moment the callback runs in When scripts_specific_loaded Needs callbacks_force.

With Approach 2, the browser downloads events.js from analytics.tiktok.com before the visitor answers, which sends the IP address of every visitor to TikTok. The TikTok consent mode page does not say whether the pixel stores its cookies before the grant. Pick Approach 1 where your legal advice says that request needs consent.

The checks assume express consent with page_load_consent_levels left out or at the generator value ["strictly-necessary"], and the "I decline" button shown. Publish the change and clear any page cache before the check. Compare the TikTok requests in the Network tab and the cookies in the Application tab before the answer, after accepting, and after declining. Run the check in a new private window, opened after you close every other one.

  1. Open DevTools in that window, select the Network tab, and type tiktok in the filter box.
  2. Open your site. With Approach 1, no request appears while the consent banner shows, and the Application tab does not list a _ttp cookie under your site. With Approach 2, the request for events.js from analytics.tiktok.com appears. Note the requests listed at this point.
  3. Click the "I agree" button. With Approach 1, the request for events.js appears now, followed by the pixel requests. With Approach 2, new requests to analytics.tiktok.com appear after the grant.
  4. Select the Application tab, open Cookies, and check that the _ttp cookie appears under your site after the click.
  5. Close every private window and open a new one. Open DevTools, type tiktok in the Network filter, load your site, click the "I decline" button, and open a second page. With Approach 1, the filter stays empty, and no _ttp cookie appears. With Approach 2, only the requests you noted before the answer appear, on the page where you declined and on the next page.

The TikTok Pixel Helper browser extension reports a pixel only once it runs. A private window does not run an extension unless you allow it there. Use the Pixel Helper in your normal window after a click on the "I agree" button to check your events, and use the Network tab for the check before consent.

Cookies the TikTok Pixel sets

The TikTok Pixel stores 4 first-party cookies on your domain and third-party cookies on tiktok.com and analytics.pangle-ads.com, according to the TikTok Business Help Center. TikTok lists each one as an advertising cookie that expires 13 months after it was last used. List them in your Cookies Policy under targeting cookies.

Cookie Domain Purpose
_ttp Your domain Measures and improves the performance of ad campaigns, and personalizes ads on TikTok
ttcsid, and ttcsid_ followed by the pixel code Your domain Measures and improves the performance of ad campaigns, and personalizes ads on TikTok
ttclid Your domain Measures and improves the performance of ad campaigns, and personalizes ads on TikTok
_ttp .tiktok.com Measures and improves the performance of ad campaigns, and personalizes ads on TikTok
_pangle analytics.pangle-ads.com Measures and improves the performance of ad campaigns, and personalizes ads delivered by the TikTok Pangle ad network

TikTok turns first-party cookies on by default, and the pixel settings in Events Manager turn them off. Check the full list in About using cookies with TikTok Pixel.

Common mistakes with the TikTok Pixel

Each common mistake sends TikTok data without consent, keeps the pixel or its events from reaching TikTok, or leaves its cookies after a withdrawal. Search your pages and your tag manager container for each one.

  • A plugin, an app, or a tag manager adds the pixel. Cookie Consent holds only the tagged scripts in your own markup, so the copy such a tool adds runs before the answer. Search the page source and your tag manager container for your pixel ID to find each copy. Remove the pixel from that plugin, app, or tag manager, and keep the copy you tagged.
  • An event call stays untagged in Approach 1. An untagged ttq.track() call runs before the tagged base code defines ttq, so it fails with a ReferenceError in the Console and the event is lost. Tag every event call with targeting.
  • Approach 2 runs without callbacks_force. On a page with no script tagged targeting, the callback never sends ttq.grantConsent(), so the pixel does not send queued events to TikTok after you click the "I agree" button. Add "callbacks_force": true to the run() options.
  • The base code of Approach 2 lacks the consent methods. A base code whose ttq.methods list has no holdConsent throws a TypeError in the Console at the ttq.holdConsent() call, and the pixel never loads. Copy the base code from the TikTok consent mode page.
  • The pixel is tagged with tracking. The TikTok Pixel serves advertising, yet a tracking tag runs it for any visitor who accepts tracking cookies, whatever the answer for targeting. Look for data-cookie-consent="tracking" on the pixel scripts, and change it to targeting.
  • The TikTok Events API sends events from your server. Your server sends events to TikTok for visitors who declined, because the consent banner holds only scripts in the browser. Look in your server code for a read of the cookie_consent_level cookie before each event, and send an event only for a visitor whose targeting value is true. Read why server-side event sending bypasses the consent banner in Vendor Recipes for Free Cookie Consent.
  • You expect a withdrawal to delete TikTok cookies. A withdrawal reaches the TikTok Pixel only from the next page load, and _ttp stays in the Application tab afterward, because Cookie Consent does not delete cookies set by TikTok. Delete the _ttp cookie from a callback with the pattern in Rejecting Does Not Delete Cookies Already Set.