Google Consent Mode v2 stays denied when your callback never sends the update, sends it too late, or sends the wrong signal names. TermsFeed Free Cookie Consent does not send any Consent Mode signal of its own. Your page sets the defaults to denied in the first script in <head>, after only the charset meta. The user_consent_saved callback then sends each signal with gtag('consent', 'update', ...) on every answer. It sends them on every later page load too when user_consent_saved_on_page_load is true. Most causes of a denied state lie in that callback or in where the default script sits.

Check each cause in Google Tag Assistant. Tag Assistant opens your site in a new window, or in a new tab when the Tag Assistant extension runs in the window you start it from. An earlier answer hides the consent banner there. First delete the 3 cookie_consent_ cookies of your site in the Application tab of the window you start Tag Assistant from. Connect your page at tagassistant.google.com, click the "I agree" button ("OK" in implied mode) in the site tab Tag Assistant opens, and select the latest Consent event in the Summary. In the Output of your Google tag, the Consent tab shows the On-page Default and On-page Update columns for each signal.

Without "user_consent_saved_on_page_load": true, user_consent_saved runs on the page where the visitor answers but never on later page loads of a visitor who answered. Tag Assistant shows the update as granted right after a click on the "I agree" or "OK" button. The next page shows only the denied default, because Google does not remember an update from one page to the next.

After you add "debug": true to the configuration object and publish, the Console tab of a later page does not show a cc_userConsentSaved triggered line. Add "user_consent_saved_on_page_load": true next to callbacks in the configuration object. Read when the callback runs in Callbacks and DOM Events.

Cause 2: The default runs after the Google tag

The gtag('consent', 'default', ...) call must run before any Google tag, or the first hits go out without a consent state.

In Tag Assistant, the first Consent event appears after the first tag event, or the On-page Default column is empty. View the page source and confirm that the default script is the first script in <head>, after only the charset meta. Move it there with Step 1: Set every consent signal to denied before any Google tag.

Cause 3: The signal names are misspelled

Google ignores a signal name it does not know, so analytic_storage or ad_user_date leaves the real signal denied. The values must be the strings 'granted' and 'denied', never true or false.

Select the update Consent event in Tag Assistant and read the API Call section. Look for a signal that stays denied after an update that lists a similar name. The 6 signals of the default are ad_storage, ad_user_data, ad_personalization, analytics_storage, functionality_storage, and personalization_storage.

Spell each signal in your gtag('consent', 'update', ...) call exactly as in that list, and give it the string 'granted' or 'denied'. Reload the page and confirm in Tag Assistant that the update now changes the signal.

Cause 4: The callback maps a category to the wrong signal

Each Cookie Consent category maps to fixed Consent Mode signals that your callback sends, and a signal read from the wrong category stays denied. The tracking category maps to analytics_storage. The targeting category maps to ad_storage, ad_user_data, and ad_personalization. The functionality category maps to functionality_storage and personalization_storage.

Click the "Update cookies preferences" link to open the Preferences Center, and set the switch of the "Tracking cookies" tab to Active. Set the switches of the "Functionality cookies" and "Targeting and advertising cookies" tabs to Inactive, where those categories are in use, and click the "Save my preferences" button. Tag Assistant then shows analytics_storage granted and the 3 ad signals denied. Compare your configuration with this Cookie Consent block, which sends each signal from user_consent_saved.

<!-- Cookie Consent by TermsFeed https://www.TermsFeed.com -->
<script type="text/javascript" src="https://www.termsfeed.com/public/cookie-consent/4.2.0/cookie-consent.js" charset="UTF-8"></script>
<script type="text/javascript" charset="UTF-8">
document.addEventListener('DOMContentLoaded', function () {
  cookieconsent.run({
    "notice_banner_type": "headline",
    "consent_type": "express",
    "palette": "dark",
    "language": "en",
    "page_load_consent_levels": ["strictly-necessary"],
    "notice_banner_reject_button_hide": false,
    "preferences_center_close_button_hide": false,
    "page_refresh_confirmation_buttons": false,
    "website_name": "Example",
    "user_consent_saved_on_page_load": true,
    "callbacks": {
      "user_consent_saved": (details) => {
        gtag('consent', 'update', {
          'analytics_storage': details.tracking ? 'granted' : 'denied',
          'ad_storage': details.targeting ? 'granted' : 'denied',
          'ad_user_data': details.targeting ? 'granted' : 'denied',
          'ad_personalization': details.targeting ? 'granted' : 'denied',
          'functionality_storage': details.functionality ? 'granted' : 'denied',
          'personalization_storage': details.functionality ? 'granted' : 'denied'
        });
      }
    }
  });
});
</script>
<noscript>Free cookie consent management tool by <a href="https://www.termsfeed.com/">TermsFeed Generator</a></noscript>
<!-- End Cookie Consent by TermsFeed https://www.TermsFeed.com -->

<a href="#" id="open_preferences_center">Update cookies preferences</a>

The callback sends denied for every category the visitor refused, so a refusal or a withdrawal reaches Google tags on the page where the visitor answers. Check every mapping in Map Categories to Vendor Consent Signals.

Cause 5: The update is sent from scripts_specific_loaded

scripts_specific_loaded runs after Cookie Consent releases the tagged scripts of a category, so a Consent Mode update sent from it arrives late or never. Without "callbacks_force": true, the callback runs only for categories that hold a tagged script. An untagged Google tag then does not get an update for a category with no tagged script, on the answer page and on later pages. A tagged Google tag runs its configuration before the update arrives, and Tag Assistant shows a first page view before the update Consent event.

Search the scripts_specific_loaded callback for a gtag('consent', 'update' call to find this setup. Move the call into user_consent_saved, which runs before Cookie Consent releases any tagged script, so a tagged Google tag starts with the update in place. Copy the callback and user_consent_saved_on_page_load from Step 3: Send the consent state from user_consent_saved.

Cause 6: The callback name points to a let or const function

A callback given as a name runs only for a function on window, so a function declared with let, const, class, or inside a module never runs. Consent Mode then keeps the defaults on every page, with no error in the console.

After you add "debug": true to the configuration object and publish, the Console tab shows Calling Customer Callback: user_consent_saved, but your function does not send an update. Put the function where Cookie Consent finds it. Declare the callback as function updateGoogleConsent(details) { ... } in a classic script, or write the function inside the callbacks object of the configuration.

Google Analytics shows fewer sessions than before

Google Analytics 4 counts fewer sessions after you add Cookie Consent, because Google Analytics does not store cookies for visitors who decline or never answer. With express consent, every visitor who ignores the consent banner is therefore missing from the reports that rely on cookies.

The drop comes from asking for consent before Google Analytics sets cookies, so it points to no error in your setup. In Tag Assistant, a visit that leaves the consent banner unanswered shows analytics_storage denied in both the "On-page Default" and the "On-page Update" columns, which is the expected state. With the Google tag loaded untagged and Consent Mode defaults set to denied, the tag sends cookieless pings for those visitors.

Google Analytics 4 models the missing visitors from those cookieless pings only once the property meets the behavioral modeling thresholds. One threshold is 1,000 events a day with analytics_storage denied, for at least 7 days. Choose between advanced consent mode, with an untagged Google tag, and basic consent mode, with a tracking tag, in Set Up Google Consent Mode v2.

A working setup shows the default as denied and the update as granted after the answer, on the first page and on every later page. Check the first page and a second one after each fix. Publish your change and clear any page cache first.

  1. In the Application tab of your normal window, delete the 3 cookie_consent_ cookies for your site.
  2. Open Google Tag Assistant from that window, connect your page, and click the "I agree" or "OK" button in the site tab Tag Assistant opens.
  3. Select the latest Consent event and confirm that On-page Default shows denied and On-page Update shows granted for analytics_storage.
  4. Open a second page and confirm the same update on its Consent events.
  5. Open DevTools on the page, select the Network tab, type collect in the filter, and reload the page.
  6. Confirm that the requests to google-analytics.com/g/collect after the reload carry gcs=G111, which marks both storage signals as granted, or gcs=G101 when targeting is not in use, which marks analytics_storage alone.