Skip to content

feat: add Google Ads 2024-2025 modern features - #3

Merged
hideokamoto merged 10 commits into
mainfrom
claude/add-google-ads-features-01JM9ZxJREaPJ3r4yHfnimtb
Nov 17, 2025
Merged

feat: add Google Ads 2024-2025 modern features#3
hideokamoto merged 10 commits into
mainfrom
claude/add-google-ads-features-01JM9ZxJREaPJ3r4yHfnimtb

Conversation

@hideokamoto

@hideokamoto hideokamoto commented Nov 16, 2025

Copy link
Copy Markdown
Owner

Add comprehensive support for the latest Google AdSense features:

  • Auto Ads with AI-powered placement (2024)
  • Consent Mode v2 for GDPR compliance (required since March 2024)
  • Ad Intents - new intent-driven ad format
  • Anchor Ads with collapsible mobile positioning
  • In-Article, In-Feed, and Multiplex modern ad formats
  • Non-personalized ads mode for privacy compliance
  • Enhanced TypeScript type definitions
  • Updated documentation with comprehensive usage examples

Breaking changes:

  • Upgraded Google AdSense script URLs to use https
  • Added crossOrigin="anonymous" attribute for better security

Version bumped to 0.2.0 to reflect new features.

Summary by CodeRabbit

  • New Features

    • Added In-Article, In-Feed, Multiplex, Anchor ad components plus Auto Ads script and modern script component.
    • Introduced Consent Mode v2, non-personalized ads (NPA), ad test mode, ad channel, ad density and ad intents options.
    • Improved explicit prop handling and NPA propagation across components.
  • Documentation

    • Major README overhaul with usage examples, feature-focused guides, API reference and migration updates.
  • Tests

    • Expanded test coverage for new components and behaviors.
  • Chores

    • Version bumped to 1.1.0; updated linter config.

Add comprehensive support for the latest Google AdSense features:

- Auto Ads with AI-powered placement (2024)
- Consent Mode v2 for GDPR compliance (required since March 2024)
- Ad Intents - new intent-driven ad format
- Anchor Ads with collapsible mobile positioning
- In-Article, In-Feed, and Multiplex modern ad formats
- Non-personalized ads mode for privacy compliance
- Enhanced TypeScript type definitions
- Updated documentation with comprehensive usage examples

Breaking changes:
- Upgraded Google AdSense script URLs to use https
- Added crossOrigin="anonymous" attribute for better security

Version bumped to 0.2.0 to reflect new features.
@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello @hideokamoto, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly upgrades the next-google-ads library by integrating the latest Google AdSense features for 2024-2025. It introduces new ad formats like Auto Ads and Anchor Ads, ensures GDPR compliance with Consent Mode v2, and enhances privacy options with non-personalized ads. The changes also include comprehensive TypeScript support and updated script loading mechanisms for improved security and modern web standards.

Highlights

  • New Ad Formats & Features: Added comprehensive support for the latest Google AdSense features, including Auto Ads with AI-powered placement, Ad Intents, Anchor Ads with collapsible mobile positioning, In-Article Ads, In-Feed Ads, and Multiplex Ads.
  • GDPR Compliance: Implemented Consent Mode v2, which is required since March 2024 for GDPR compliance, including new ad_user_data and ad_personalization signals.
  • Privacy & Security Enhancements: Introduced a non-personalized ads (NPA) mode for privacy-focused advertising and upgraded Google AdSense script URLs to use HTTPS with the crossOrigin="anonymous" attribute for improved security.
  • TypeScript Support: Enhanced TypeScript type definitions for all new components and props, providing full type safety and improving the developer experience.
  • Version Bump: The package version has been updated from 0.1.1 to 0.2.0 to reflect these significant feature additions and breaking changes.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces comprehensive support for modern Google AdSense features, including Auto Ads, Consent Mode v2, and various new ad formats. The changes are well-structured, with new components and types for each feature. The documentation in README.md has been significantly improved with detailed examples. My review focuses on improving code quality and fixing a potential bug. I've identified some dead code, a potential issue with an event handler, and a minor optimization for an inline script.

Comment thread src/index.tsx Outdated

// Anchor and Side Rail positioning (2024 feature)
export type AnchorPosition = 'top' | 'bottom' | 'both';
export type SideRailPosition = 'left' | 'right' | 'both';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The type SideRailPosition is defined but it's not used anywhere in the codebase. To improve maintainability, it's best to remove unused code. If this is intended for future use, consider adding a comment explaining its purpose.

Comment thread src/index.tsx
Comment on lines +225 to +229
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('consent', 'default', ${JSON.stringify(consentMode)});
`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The inline script within dangerouslySetInnerHTML contains unnecessary newlines and whitespace. While this works, it adds a few extra bytes to the HTML payload. For a cleaner and slightly more optimized output, you can format the script as a single line.

            __html: `window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('consent', 'default', ${JSON.stringify(consentMode)});`,

Update CI workflows to use supported Node.js versions and latest GitHub Actions:

- Update Node.js versions from 10.x/12.x/14.x to 18.x/20.x/22.x
- Update actions/checkout from v1/v2 to v4
- Update actions/setup-node from v1 to v4
- Add npm caching for faster builds
- Remove Windows/macOS matrix to reduce CI time
- Switch from yarn to npm commands for consistency
- Update package.json engines to require Node.js >=18

This fixes CI failures caused by EOL Node.js versions.
@hideokamoto

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Nov 17, 2025

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Nov 17, 2025

Copy link
Copy Markdown

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Rewrote README with new project name and feature-centric docs; bumped package to 1.1.0. Added ConsentModeV2, AutoAdsConfig, AnchorPosition and multiple ad components (AutoAdsScript, InArticleAd, InFeedAd, MultiplexAd, AnchorAd, NextGoogleAdsenseScript). Adjusted script/widget load order and added npa/adTest/adChannel attributes. Updated linter rule.

Changes

Cohort / File(s) Summary
Documentation
README.md
Full rewrite: renamed project, restructured content into Usage Examples and feature sections, removed migration guide, added modern examples and expanded API/appendix.
Package Manifest
package.json
Version bumped from 1.0.0 to 1.1.0.
Core Sources (components & types)
src/index.tsx
Added exported types: ConsentModeV2, AutoAdsConfig, AnchorPosition, and props types for new ad components. Added components: AutoAdsScript, InArticleAd, InFeedAd, MultiplexAd, AnchorAd, and updated NextGoogleAdsenseScript and GoogleAdsense composition. Introduced npaMode, adTest, adChannel data-attribute wiring and reordered script → widget rendering.
Linter config
biome.json
Added linter.rules.security.noDangerouslySetInnerHtml set to "off".
Tests
test/blah.test.tsx, test/index.test.tsx
Removed legacy mount test (test/blah.test.tsx). Added comprehensive tests (test/index.test.tsx) covering rendering, data-attribute propagation, AutoAdsScript and NextGoogleAdsenseScript behaviors, crossOrigin and npaMode handling.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant App as Client App
    participant GoogleAdsense as GoogleAdsense (composed)
    participant Script as NextGoogleAdsenseScript
    participant Widget as GoogleAdsenseWidget
    participant AutoScript as AutoAdsScript
    participant AdsJS as google ad.js

    App->>GoogleAdsense: render <GoogleAdsense client=... npaMode=... />
    GoogleAdsense->>Script: render with client, npaMode
    Script->>AdsJS: load ad.js (crossorigin when requested)
    GoogleAdsense->>Widget: render widget with props (adTest, adChannel, npaMode)
    Widget->>Widget: set data-* attributes (data-ad-client, data-ad-slot, data-npa-mode...)
    Widget->>AdsJS: trigger ad processing

    alt Auto Ads configured
        App->>AutoScript: render <AutoAdsScript client=... config=... consentMode=... />
        AutoScript->>AdsJS: push auto-ads config into window.adsbygoogle
        AutoScript->>Script: optionally inject consent-mode script
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Areas to focus review on:

  • New public component APIs and exported types in src/index.tsx
  • Data-attribute correctness and DOM attribute rendering for npaMode, adTest, adChannel
  • Script element attributes (id, crossorigin) and the load ordering between NextGoogleAdsenseScript and widgets
  • AutoAdsScript behavior: window.adsbygoogle pushes and ConsentModeV2 serialization
  • Tests in test/index.test.tsx for coverage and correctness

Poem

🐇 A rabbit hops with glee tonight,

Scripts align and data's right,
Anchors, feeds and articles sing,
Consent whispers, auto-ads spring,
Version 1.1 — a nimble flight!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add Google Ads 2024-2025 modern features' clearly and specifically describes the main change: introducing modern Google Ads features from 2024-2025. It directly aligns with the substantial additions of Auto Ads, Consent Mode v2, Anchor Ads, modern ad formats, and enhanced TypeScript support documented in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/add-google-ads-features-01JM9ZxJREaPJ3r4yHfnimtb

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/index.tsx (1)

256-277: Avoid overriding window.onload inside NextGoogleAdsenseScript

Assigning window.onload in the Script's onLoad callback will clobber any existing window.onload handler, and it can fail if the load event has already fired before the script finishes loading. Initialize script-dependent code directly inside the onLoad callback instead; onLoad is script-scoped and fires as soon as that specific script is ready, whereas window.onload fires much later after all page resources and is not ideal for initializing a single third-party library.

-      onLoad={() => {
-        if (typeof window !== 'undefined') {
-          window.onload = () => {
-            ((window as any).adsbygoogle =
-              (window as any).adsbygoogle || []).push({});
-          };
-        }
-      }}
+      onLoad={() => {
+        if (typeof window !== 'undefined') {
+          (window as any).adsbygoogle = (window as any).adsbygoogle || [];
+          (window as any).adsbygoogle.push({});
+        }
+      }}
♻️ Duplicate comments (1)
src/index.tsx (1)

20-22: Unused SideRailPosition type – consider documenting or removing

SideRailPosition is defined but not used in this file; if it’s meant for a future SideRail component or external consumption, a short comment explaining that intent would help. Otherwise, consider removing it to keep the surface minimal.

🧹 Nitpick comments (3)
src/index.tsx (3)

122-141: Format-specific ad components are consistent; duplication could be reduced

InArticleAd, InFeedAd, MultiplexAd, and AnchorAd all follow a consistent ins.adsbygoogle pattern and correctly set the expected data-ad-* attributes for their formats. There is quite a bit of repeated JSX (client/slot/npaMode wiring and base styles), so if this grows further it might be worth extracting a small shared helper or base component to DRY it up.

Also applies to: 143-165, 166-186, 187-207


220-231: Add explanatory comment or linter disable for dangerouslySetInnerHTML

React documentation recommends using dangerouslySetInnerHTML only when absolutely necessary for trusted content, and this pattern with JSON.stringify(consentMode) meets that requirement for the official gtag Consent Mode snippet. However, the code currently lacks an inline comment or linter disable directive. To make the intent explicit and prevent linter warnings, add either:

  • An inline comment explaining this is a controlled, non–user-input script injection (official gtag pattern)
  • Or a Biome linter disable comment (e.g., // biome-ignore js/noDangerouslySetInnerHtml: official gtag pattern)

233-239: Align AdSense script tag with current Google recommendations and simplify Auto Ads enablement

The web search confirms both patterns are supported, but Google's current recommendations favor ?client=ca-pub-... in the script src URL for Auto Ads. More importantly, Auto Ads are controlled entirely through the AdSense account UI—your code doesn't need to push enable_page_level_ads config or require a config object. Both AutoAdsScript and NextGoogleAdsenseScript currently use data-ad-client and require config wiring, but this can be simplified:

  • Update both script URLs to include ?client=${client} in the src instead of (or in addition to) data-ad-client
  • Remove the requirement for config?.enableAutoAds and the enable_page_level_ads push; Auto Ads activation is handled in the AdSense account settings, not via script config

This aligns with Google's recommended pattern and eliminates unnecessary configuration overhead for consumers.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between df066a2 and 6fa05e3.

📒 Files selected for processing (1)
  • src/index.tsx (4 hunks)
🧰 Additional context used
🪛 ast-grep (0.39.9)
src/index.tsx

[warning] 223-223: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 Biome (2.1.2)
src/index.tsx

[error] 224-224: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (3)
src/index.tsx (3)

4-18: Typed API surface for Consent Mode v2 and modern formats looks solid

The new type definitions (ConsentModeV2, AutoAdsConfig, extended GoogleAdsenseProps, and the various *AdProps/AutoAdsProps) are well-structured and keep values constrained ('granted' | 'denied', specific formats, etc.), which should make the public API safer and easier to use from TypeScript.

Also applies to: 24-40, 42-85


280-285: Updated GoogleAdsense composition looks good

Wrapping GoogleAdsenseWidget with NextGoogleAdsenseScript and forwarding client/npaMode gives a clear separation between script loading and ad slot rendering, which should simplify usage for consumers.


209-254: Review comment is based on incorrect assumptions about Google AdSense Auto Ads behavior

Including the script tag with the client parameter is sufficient to enable Auto Ads; the adsbygoogle.push({ enable_page_level_ads: true, ... }) call is only needed for special cases like pausing requests for consent, requesting non-personalized ads, or using extra options.

The code correctly always renders the script tag with data-ad-client={client}, which automatically enables Auto Ads. The conditional adsbygoogle.push() call in the onLoad handler handles optional features (ad density, ad intents) only when config.enableAutoAds is truthy. Omitting config entirely does not prevent Auto Ads from functioning—it simply skips optional configuration tweaks.

Likely an incorrect or invalid review comment.

Comment thread src/index.tsx
claude and others added 3 commits November 17, 2025 04:22
… build

Merge main branch (v1.0.0) with Google Ads 2024-2025 modern features.

Main branch changes (from v1.0.0):
- Migrated from TSDX to Vite build system
- Replaced ESLint/Prettier with Biome
- Upgraded to React 19 and Next.js 16
- Modernized CI/CD workflows
- Improved type definitions and error handling

Google Ads features added (bumped to v1.1.0):
- Auto Ads with AI-powered placement (2024)
- Consent Mode v2 for GDPR compliance (required since March 2024)
- Ad Intents - new intent-driven ad format
- Anchor Ads with collapsible mobile positioning (2024)
- In-Article, In-Feed, and Multiplex modern ad formats
- Non-personalized ads mode for privacy compliance
- Enhanced TypeScript type definitions

Breaking changes:
- Minimum Node.js version: 18 → 20.19.0
- Minimum React version: 16 → 19
- Minimum Next.js version: 11 → 16
- Build system: TSDX → Vite
- Linter: ESLint/Prettier → Biome

Conflict resolutions:
- Used Vite-based package.json from main
- Preserved all new Google Ads components and types
- Merged NextGoogleAdsenseScript improvements (error handling + new params)
- Updated Biome config to allow dangerouslySetInnerHTML for Consent Mode v2
- Removed deprecated size.yml workflow

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/index.tsx (1)

106-122: Non‑personalized ads attribute name is incorrect (data-npa-mode vs data-npa)

The npaMode prop is currently wired to data-npa-mode, but AdSense expects the npa flag via data-npa="1" (or an equivalent npa=1 request parameter). With the current attribute name, the non‑personalized ads signal is likely ignored, so your advertised NPA/privacy behavior won’t actually take effect.

This affects all usages:

  • GoogleAdsenseWidget (Line 120)
  • InArticleAd (Line 143)
  • InFeedAd (Line 166)
  • MultiplexAd (Line 187)
  • AnchorAd (Line 209)
  • AutoAdsScript script tag (Line 244)
  • NextGoogleAdsenseScript script tag (Line 274)

Suggested fix:

-      data-npa-mode={npaMode ? '1' : undefined}
+      data-npa={npaMode ? '1' : undefined}

Apply the same change to each of the components and script tags listed above so that npaMode reliably maps to the documented AdSense NPA signal.

Please double‑check the expected attribute name and behavior against the latest AdSense documentation before releasing, since this directly impacts GDPR/non‑personalized ad compliance.

Also applies to: 133-143, 155-167, 177-187, 198-209, 244-244, 274-274

🧹 Nitpick comments (1)
biome.json (1)

31-36: Avoid disabling noDangerouslySetInnerHtml globally

Turning the security.noDangerouslySetInnerHtml rule off for the entire project weakens your safety net for future changes. Since the current use is a single, controlled consent‑mode script, consider keeping this rule enabled and suppressing it only where necessary (e.g., via a file‑specific override or per‑line ignore) instead of at the global level.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa05e3 and a6ce846.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • README.md (2 hunks)
  • biome.json (1 hunks)
  • package.json (1 hunks)
  • src/index.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
🪛 ast-grep (0.39.9)
src/index.tsx

[warning] 228-228: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 LanguageTool
README.md

[grammar] ~318-~318: Use a hyphen to join words.
Context: ... in /dist, so if you are seeing an out of date component, make sure TSDX is run...

(QB_NEW_EN_HYPHEN)


[grammar] ~318-~318: Use a hyphen to join words.
Context: ... /dist, so if you are seeing an out of date component, make sure TSDX is runnin...

(QB_NEW_EN_HYPHEN)


[grammar] ~334-~334: Ensure spelling is correct
Context: .../ai/size-limit) with npm run size and visulize it with npm run analyze. #### Setup ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[style] ~434-~434: Consider shortening or rephrasing this to strengthen your wording.
Context: ...project. To fix that you will need to make changes to thepackage.jsonfile _inside theex...

(MAKE_CHANGES)


[style] ~449-~449: Consider using a different verb for a more formal wording.
Context: ...react-dom" }, ``` An alternative to fixing this problem would be to remove aliases...

(FIX_RESOLVE)

🪛 markdownlint-cli2 (0.18.1)
README.md

295-295: Blank line inside blockquote

(MD028, no-blanks-blockquote)

Comment thread README.md
```

### Development Mode
The default example imports and live reloads whatever is in `/dist`, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. **No symlinking required**, we use [Parcel's aliasing](https://parceljs.org/module_resolution.html#aliases).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix minor README typos and markdown lint issues

Only small documentation nits:

  • Line 318: use a hyphen in “out-of-date”.
  • Line 334: fix the typo “visulize” → “visualize”.
  • Lines 294–297: remove the blank line inside the blockquote to satisfy MD028.

Example patch:

- The default example imports and live reloads whatever is in `/dist`, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. **No symlinking required**, we use [Parcel's aliasing](https://parceljs.org/module_resolution.html#aliases).
+ The default example imports and live reloads whatever is in `/dist`, so if you are seeing an out-of-date component, make sure TSDX is running in watch mode like we recommend above. **No symlinking required**, we use [Parcel's aliasing](https://parceljs.org/module_resolution.html#aliases).

- Calculates the real cost of your library using [size-limit](https://github.com/ai/size-limit) with `npm run size` and visulize it with `npm run analyze`.
+ Calculates the real cost of your library using [size-limit](https://github.com/ai/size-limit) with `npm run size` and visualize it with `npm run analyze`.

-> This TSDX setup is meant for developing React component libraries (not apps!) that can be published to NPM. If you’re looking to build a React-based app, you should use `create-react-app`, `razzle`, `nextjs`, `gatsby`, or `react-static`.
-
-> If you’re new to TypeScript and React, checkout [this handy cheatsheet](https://github.com/sw-yx/react-typescript-cheatsheet/)
+> This TSDX setup is meant for developing React component libraries (not apps!) that can be published to NPM. If you’re looking to build a React-based app, you should use `create-react-app`, `razzle`, `nextjs`, `gatsby`, or `react-static`.
+> If you’re new to TypeScript and React, checkout [this handy cheatsheet](https://github.com/sw-yx/react-typescript-cheatsheet/)

Also applies to: 334-334, 294-297

🧰 Tools
🪛 LanguageTool

[grammar] ~318-~318: Use a hyphen to join words.
Context: ... in /dist, so if you are seeing an out of date component, make sure TSDX is run...

(QB_NEW_EN_HYPHEN)


[grammar] ~318-~318: Use a hyphen to join words.
Context: ... /dist, so if you are seeing an out of date component, make sure TSDX is runnin...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
In README.md around lines 318, 334, and 294-297, apply three small doc fixes:
change “out of date” to “out-of-date” at line 318, correct the typo “visulize”
to “visualize” at line 334, and remove the stray blank line inside the
blockquote spanning lines 294–297 so the blockquote has no internal blank line
(satisfying MD028).

- 全8コンポーネントのユニットテストを追加
  - GoogleAdsenseWidget
  - InArticleAd
  - InFeedAd
  - MultiplexAd
  - AnchorAd
  - AutoAdsScript
  - NextGoogleAdsenseScript
  - GoogleAdsense
- next/scriptのモックを実装
- 各コンポーネントの必須プロパティ、デフォルト値、オプショナルプロパティをテスト
- window.adsbygoogleの動作をテスト
- 古いblah.test.tsxを削除し、index.test.tsxに統合

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a6ce846 and b5167ea.

📒 Files selected for processing (2)
  • test/blah.test.tsx (0 hunks)
  • test/index.test.tsx (1 hunks)
💤 Files with no reviewable changes (1)
  • test/blah.test.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
test/index.test.tsx (1)
src/index.tsx (8)
  • GoogleAdsenseWidget (93-125)
  • InArticleAd (128-146)
  • InFeedAd (149-169)
  • MultiplexAd (172-190)
  • AnchorAd (193-212)
  • AutoAdsScript (215-258)
  • NextGoogleAdsenseScript (260-284)
  • GoogleAdsense (286-293)
🪛 ast-grep (0.39.9)
test/index.test.tsx

[warning] 41-41: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🔇 Additional comments (8)
test/index.test.tsx (8)

38-44: Static analysis warning is a false positive.

The static analysis tool flagged the dangerouslySetInnerHTML usage as a potential XSS risk. However, this is test mock code with fully controlled content (consent mode script from AutoAdsScript), not user-supplied input. This usage is safe and necessary for testing components that inject scripts.


50-136: LGTM!

The GoogleAdsenseWidget test suite is comprehensive, covering required props, default values, optional props, and npaMode behavior. React 19 APIs are used correctly with proper cleanup.


138-209: LGTM!

The InArticleAd test suite properly validates required props, format/layout attributes, npaMode, and custom styling.


211-271: LGTM!

The InFeedAd test suite correctly validates the layoutKey requirement and other ad-specific attributes.


339-411: LGTM!

The AnchorAd test suite properly validates default values and the position/collapsible configuration options.


413-517: LGTM!

The AutoAdsScript test suite comprehensively covers null returns, script rendering, Consent Mode v2, configuration push behavior, and npaMode. The time-based wait at line 488 aligns with the mocked script loading behavior.


519-628: LGTM!

The NextGoogleAdsenseScript test suite is thorough, covering null returns, script rendering, adsbygoogle initialization, and crossOrigin attribute handling (both enabled and disabled). The defensive check at line 574 is reasonable given the async nature of the tests.


630-683: LGTM!

The GoogleAdsense composition test suite correctly validates that both child components render and that props are properly forwarded to each component.

Comment thread test/index.test.tsx
Comment on lines +306 to +321
it('applies custom format', () => {
const div = document.createElement('div');
const root = createRoot(div);
act(() => {
root.render(
<MultiplexAd client="ca-pub-123" slot="123456" format="autorelaxed" />
);
});

const ins = div.querySelector('ins');
expect(ins?.getAttribute('data-ad-format')).toBe('autorelaxed');

act(() => {
root.unmount();
});
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Redundant test case.

This test claims to validate "custom format" but uses the same autorelaxed value as the default format test (lines 291-304). This doesn't actually test custom format behavior.

Apply this diff to test a different format value or remove the redundant test:

  it('applies custom format', () => {
    const div = document.createElement('div');
    const root = createRoot(div);
    act(() => {
      root.render(
-        <MultiplexAd client="ca-pub-123" slot="123456" format="autorelaxed" />
+        <MultiplexAd client="ca-pub-123" slot="123456" format="rectangle" />
      );
    });

    const ins = div.querySelector('ins');
-    expect(ins?.getAttribute('data-ad-format')).toBe('autorelaxed');
+    expect(ins?.getAttribute('data-ad-format')).toBe('rectangle');

    act(() => {
      root.unmount();
    });
  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('applies custom format', () => {
const div = document.createElement('div');
const root = createRoot(div);
act(() => {
root.render(
<MultiplexAd client="ca-pub-123" slot="123456" format="autorelaxed" />
);
});
const ins = div.querySelector('ins');
expect(ins?.getAttribute('data-ad-format')).toBe('autorelaxed');
act(() => {
root.unmount();
});
});
it('applies custom format', () => {
const div = document.createElement('div');
const root = createRoot(div);
act(() => {
root.render(
<MultiplexAd client="ca-pub-123" slot="123456" format="rectangle" />
);
});
const ins = div.querySelector('ins');
expect(ins?.getAttribute('data-ad-format')).toBe('rectangle');
act(() => {
root.unmount();
});
});
🤖 Prompt for AI Agents
In test/index.test.tsx around lines 306 to 321, the "applies custom format" test
is redundant because it uses the same 'autorelaxed' value as the default-format
test; update the test to use a different format (for example 'fluid' or
'rectangle') and assert that the rendered <ins> has data-ad-format equal to that
new value (or alternatively remove the entire test if you prefer to keep only
the default-format case).

@hideokamoto
hideokamoto merged commit 4725877 into main Nov 17, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants