Skip to content

Render scripts from Script Manager#2477

Merged
bookernath merged 1 commit into
canaryfrom
script
Jul 14, 2025
Merged

Render scripts from Script Manager#2477
bookernath merged 1 commit into
canaryfrom
script

Conversation

@bookernath

@bookernath bookernath commented Jul 14, 2025

Copy link
Copy Markdown
Contributor

What/Why?

Checks for scripts in Script Manager tied to the Catalyst storefront's channel and renders them in the root layout using next/script.

Related docs PR: https://github.com/bigcommerce/docs/pull/1014

⚠️ This makes a best-effort attempt to map Scripts API properties to the optimal settings in a next/script context, but it does prefer performance over parity for purposes of rendering scripts on Catalyst ⚠️

⚠️ Scripts that worked on Stencil are NOT guaranteed to work on Catalyst, and may need to be re-written, especially if they depend on the DOM or need to fire on every navigation ⚠️

⚠️ Overall this is not the recommended way of integrating apps into Catalyst, but it may be appropriate for some use cases such as analytics pixels and popups ⚠️

⚠️ This does NOT yet handle cookie consent for scripts, all scripts will render all the time until we add a consent manager ⚠️

Future work will add a consent manager into Catalyst which will apply to both scripts as well as analytics calls, respecting cookie consent automatically.

Testing

Preview deployment

  • Inline script works
  • CDN script works
  • SRI works

Migration

N/A

@changeset-bot

changeset-bot Bot commented Jul 14, 2025

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 292574f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@bigcommerce/catalyst-core Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jul 14, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
catalyst-canary ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 14, 2025 10:42pm
4 Skipped Deployments
Name Status Preview Comments Updated (UTC)
catalyst ⬜️ Ignored (Inspect) Jul 14, 2025 10:42pm
catalyst-au ⬜️ Ignored (Inspect) Visit Preview Jul 14, 2025 10:42pm
catalyst-b2b ⬜️ Ignored (Inspect) Visit Preview Jul 14, 2025 10:42pm
catalyst-uk ⬜️ Ignored (Inspect) Visit Preview Jul 14, 2025 10:42pm

This comment was marked as outdated.

Comment thread core/components/scripts/scripts.tsx Outdated
Comment thread core/components/scripts/scripts.tsx Outdated
Comment thread core/components/scripts/README.md Outdated
Comment thread core/components/scripts/fragment.ts
@bookernath
bookernath requested a review from Copilot July 14, 2025 20:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull Request Overview

Adds a new mechanism to fetch and render BigCommerce Script Manager scripts in the Catalyst storefront using Next.js’s <Script> component.

  • Introduces ScriptManagerScripts to process and render inline (InlineScript) and external (SrcScript) scripts with proper strategies and integrity support.
  • Defines ScriptsFragment to retrieve header and footer scripts via GraphQL and integrates it into the root layout.
  • Updates documentation, GraphQL type mappings, and adds a changelog entry.

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
core/components/scripts/scripts.tsx Implements ScriptManagerScripts and script rendering
core/components/scripts/fragment.ts Adds GraphQL fragment for header and footer scripts
core/components/scripts/README.md Documents usage and component behavior
core/components/scripts/index.tsx Exports component and fragment
core/client/graphql.ts Adds UUID to GraphQL scalar mappings
core/app/[locale]/layout.tsx Integrates ScriptManagerScripts into the layout
.changeset/wise-ads-drive.md Changelog entry for script rendering feature
Comments suppressed due to low confidence (2)

core/components/scripts/scripts.tsx:16

  • No tests were added for ScriptManagerScripts. Consider adding unit tests to verify handling of external and inline scripts, including integrity hash and dangerouslySetInnerHTML scenarios.
export const ScriptManagerScripts = ({ scripts, strategy }: ScriptRendererProps) => {

core/components/scripts/README.md:10

  • Add a note that consumers must include ...ScriptsFragment in their GraphQL queries (headerScripts / footerScripts) to supply data to ScriptManagerScripts.
## Usage

Comment thread core/components/scripts/scripts.tsx
Comment on lines +3 to +12
export const ScriptsFragment = graphql(`
fragment ScriptsFragment on Content {
headerScripts: scripts(
first: 50
filters: { visibilities: [ALL_PAGES, STOREFRONT], location: HEAD }
) {
...ScriptTypeConnectionFragment
}
footerScripts: scripts(
first: 50

Copilot AI Jul 14, 2025

Copy link

Choose a reason for hiding this comment

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

[nitpick] The hardcoded limit of first: 50 may truncate scripts if more are added. Consider extracting this into a named constant or documenting the rationale for using 50.

Suggested change
export const ScriptsFragment = graphql(`
fragment ScriptsFragment on Content {
headerScripts: scripts(
first: 50
filters: { visibilities: [ALL_PAGES, STOREFRONT], location: HEAD }
) {
...ScriptTypeConnectionFragment
}
footerScripts: scripts(
first: 50
// Default limit for the number of scripts to fetch. Adjust this value as needed.
const DEFAULT_SCRIPT_LIMIT = 50;
export const ScriptsFragment = graphql(`
fragment ScriptsFragment on Content {
headerScripts: scripts(
first: DEFAULT_SCRIPT_LIMIT
filters: { visibilities: [ALL_PAGES, STOREFRONT], location: HEAD }
) {
...ScriptTypeConnectionFragment
}
footerScripts: scripts(
first: DEFAULT_SCRIPT_LIMIT

Copilot uses AI. Check for mistakes.

@chanceaclark chanceaclark left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The dom-purify is the only major thing, otherwise looks good to me.

Comment thread core/components/scripts/scripts.tsx Outdated
Comment on lines +39 to +48
// Handle inline scripts (InlineScript)
if (script.__typename === 'InlineScript' && script.scriptTag) {
const scriptMatch = /<script[^>]*>([\s\S]*?)<\/script>/i.exec(script.scriptTag);

if (scriptMatch?.[1]) {
scriptProps.dangerouslySetInnerHTML = {
__html: scriptMatch[1],
};
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we should have dom-purify here in the repo that you might want to use instead of a regex 🤔

Comment thread core/components/scripts/scripts.tsx Outdated

return (
<>
{scriptNodes.map((script) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🍹 Only if you want to update this... but a better practice, which might seem weird, is to do two .map's here. One to build the props, then another one to render. It allows each .map to have separate concerns.

{scriptNodes
  .map((script) => {
    // ...
    return {
      src: "...",
      // ....
    };
  })
  .map((script) => {
    return (
      <Script key={script.id} {...script} />
    );
  })
}

@bookernath
bookernath added this pull request to the merge queue Jul 14, 2025
Merged via the queue into canary with commit 02af32c Jul 14, 2025
10 checks passed
@bookernath
bookernath deleted the script branch July 14, 2025 22:54
bc-victor added a commit that referenced this pull request Aug 7, 2025
…rtal (#2504)

* Version Packages (`canary`) (#2452)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Bump next to latest canary (#2465)

* docs: how to verify new merge base established when syncing (#2451)

Improve explanation around the importance of establishing a new merge base every time `canary` is merged into `integrations/makeswift`

* chore(core): remove runtime edge declarations (#2464)

* Update translations (#2468)

* feat(other): LOCAL-1444 delivery translation

* chore(core): create translations patch

---------

Co-authored-by: bc-svc-local <bc-svc-local@users.noreply.github.com>
Co-authored-by: Jorge Moya <jorge.moya@bigcommerce.com>

* Use min and max purchase quantity to set bounds of quantity number input (#2474)

* chore: update ci to include @bigcommerce/catalyst (#2463)

* chore: update deps mostly related to packages/cli (#2461)

* chore: use @commander-js/extra-typings as devDep (#2462)

* feat: render scripts from Script Manager (#2477)

* chore: hoist eslint plugins for ide support (#2460)

* feat: recursively copy cwd into temp folder (#2479)

* feat(cli): scaffold deploy command and generate bundle zip (#2481)

* feat(cli): scaffold deploy command and generate bundle zip

* feat: remove archiver and only use adm-zip

* feat: add extra checks for build files

* refactor: move checks around

* fix: use .bigcommerce/dist as build path

* refactor: split mkTempDir to own lib file and update tests

* fix: remove file

* fix: set default value for prefix

* fix: remove extra-typings

* feat: install and build all deps required to bundle catalyst (#2486)

* chore: bump opennextjs-cloudflare version (#2487)

* feat(cli): generate upload signature and upload bundle.zip (#2484)

* feat(cli): generate upload signature and upload bundle.zip

* feat: read from env variables

* feat: use zod to validate response

* refactor: parse

* feat: read api host from env

* refactor: infer option types in deploy command action (#2490)

* feat: copy templates from cli to catalyst build tmpdir (#2489)

* Version Packages (`canary`) (#2466)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Nathan Booker <bookernath@users.noreply.github.com>
Co-authored-by: Matthew Volk <matt.volk@bigcommerce.com>
Co-authored-by: Jorge Moya <jorge.moya@bigcommerce.com>
Co-authored-by: bc-svc-local <102379007+bc-svc-local@users.noreply.github.com>
Co-authored-by: bc-svc-local <bc-svc-local@users.noreply.github.com>
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.

3 participants