AdSense Review Passed! But Ads Don't Show Up... The Culprit is "CSP"
After much effort, my tech blog built with Next.js finally passed the Google AdSense review. Elated that I had reached the starting line for monetization, I pasted the ad tags, but nothing appeared on the screen.
When you open the developer console (Chrome DevTools), are you seeing a large number of errors in red text?
Refused to load the script ''...'' because it violates the following Content Security Policy directive...
If you're seeing this error, the cause is the CSP (Content Security Policy) header returned by your server (or framework).
What exactly is CSP (Content Security Policy)?
CSP is a security feature designed to prevent attacks like XSS (Cross-Site Scripting). It's a mechanism that instructs the browser, "This site will only load scripts and images from allowed domains."
When using modern frameworks like Next.js, if you've set up headers with a high security consciousness, scripts from "Google AdSense" or "affiliate ASPs" will be blocked as "unauthorized external suspicious code".
Conclusion: The Complete Solution for next.config.js to Allow AdSense and ASPs
"I want to maintain security. But I also want to display ads." To resolve this dilemma, I'm sharing the next.config.js configuration that I'm currently using.
The following code is an "all-inclusive" configuration that permits major ASPs such as AdSense, Amazon Associates, Rakuten, A8.net, and Moshimo Affiliate, while also incorporating Sentry for error monitoring and image optimization settings.
Actual Code
Note: The above CSP settings (especially script-src) can become very long. This is because programmatic ads like AdSense communicate with countless ad serving servers (SSP/DSP) in the background, and if these are not comprehensively covered, ads may not display.
Deep Dive into Tricky CSP Configuration Points
1. The script-src Whitelist Hell
To display AdSense and affiliate ads, simply allowing google.com is not enough. Due to the ad delivery mechanism, domains such as doubleclick.net, googlesyndication.com, and also Amazon, Rakuten, and ValueCommerce need to be allowed.
The code above comprehensively lists domains corresponding to AdSense, as well as major Japanese affiliate ASPs (A8, Moshimo, ValueCommerce), Amazon, and Rakuten. The task of identifying and adding each of these one by one was truly a "swamp".
2. The Absolutely Necessary unsafe-inline and unsafe-eval
While not recommended from a security standpoint, the following specifications are virtually essential to run GTM (Google Tag Manager), AdSense, and many ASP-provided scripts.
unsafe-eval: Necessary for evaluating and executing code from strings.unsafe-inline: Necessary for executing code written directly within<script>...</script>tags.
If these are omitted, many external tools will stop functioning, so we're allowing them with an understanding of the risks.
3. Don't Forget Image Domains (img-src)
Even if ad scripts run, it's meaningless if banner images don't display. Separately from images.remotePatterns (Next.js image optimization settings), the img-src in the CSP header also needs to allow ad image distribution domains (e.g., *.rakuten.co.jp, *.amazon-adsystem.com).
Sentry and Bundle Optimization Introduced Concurrently
This next.config.js also includes improvements beyond security.
- Sentry Integration: By using
@sentry/nextjs, settings have been included to detect and notify unexpected errors occurring in the production environment in real-time. Since CSP violation errors can also be caught by Sentry, it helps in discovering forgotten settings. - Removal of console.log: With the
compiler: { removeConsole: ... }setting,console.logis removed only during production builds. This prevents information leakage due to forgotten debug code and reduces bundle size.
Summary: Aiming for Both Security and Monetization
In operating a site with Next.js, CSP configuration is a formidable hurdle that cannot be avoided. However, once properly configured, you can monetize your site while maintaining its security.
If you're panicking because "AdSense passed but isn't showing up!", please use the next.config.js introduced here as a base and adjust it according to your own services.

