If your community has been using legacy Pockets for banners, callouts, scripts, embeds, or other custom content, moving to Layout Editor is an important step toward a more modern and manageable setup.
- This guide is written for community managers and site owners who are planning that transition.
- You do not need to be deeply technical to use it.
- The goal is to help you understand what is changing, how to approach this type of migration, and where you may want help from a developer, technical partner, or AI assistant.
In many cases, this move is not just about replacing an older tool: It's a chance to simplify your site, reduce fragile customizations, and give your team a better way to manage page content over time.
This is an important update for your community
Pockets were built for Vanilla's older layout model. They made it possible to insert custom HTML, CSS, and JavaScript into specific locations across legacy pages. For a long time, that gave communities a flexible way to add promotions, help boxes, ad placements, scripts, and other enhancements.
The challenge is that Pockets belong to the legacy Vanilla experience. As your site moves into Layout Editor, those older injection points no longer provide a dependable foundation: content built with Pockets does not naturally move into Layout Editor pages, and older script patterns are becoming less dependable over time.
For community managers, this usually shows up in a practical way: a page gets redesigned using Layout Editor, and something that used to appear through a Pocket is suddenly gone or no longer behaves as expected.
That is why this update matters. It is not just housekeeping; it is part of making sure your community customizations continue to work as the Vanilla platform evolves.
Getting started
One of the most helpful mindset shifts is this: you do not need to recreate every Pocket exactly as it existed before.
Instead, for each Pocket, ask what the best supported solution is now.
For community managers, that means the first thing you ask yourself is NOT "Where do I paste this old code?" The first step is asking "What kind of thing is this? Do I still need this thing? Where should this thing live now?”
What are your Pockets actually doing?
Before rebuilding anything, take inventory of the Pockets your site uses today.
- Some Pockets are simply displaying content: a banner, an image, a call to action, or a block of promotional text. These are the easiest to migrate.
- Others are really acting more like mini-applications. They might load a third-party tool, run JavaScript, set up a tracker, or alter page behavior. These usually need more care and may require support from a developer.
- There are also Pockets that were used years ago because they were the only option at the time, but which can now be replaced by standard Layout Editor widgets. Those are often the best migration candidates, because they let you remove custom code entirely.
As you review your current Pockets, it helps to note where each one appears, who is supposed to see it, and whether it is still needed. Many teams discover that some older customizations can simply be retired instead of migrated.
TIP: You can see all your pocket information at once as a JSON file by navigating to this URL in your community:
yourcommunity.com/settings/pockets.json
This can be useful to provide yourself a birds-eye view of everything your pockets are doing right now and make it easy to group your pockets in different ways (by location, view permissions, etc).
Lean toward Vanilla’s out-of-the-box widgets
Not every old Pocket should become a Custom HTML widget.
If the Pocket was used to create something fairly standard, such as a call to action, a category display, a discussion feed, or a help-oriented content block, check Layout Editor first to see whether Vanilla already offers a built-in widget that fits the need.
This is often the simplest and best outcome. Built-in widgets are easier to manage, easier for non-technical teams to update, and less likely to create maintenance issues later.
A migration is a good opportunity to reduce custom code wherever possible. If a native widget gets you most or all of the way there, it is usually the right choice.
When a custom HTML widget just makes sense
Custom HTML widgets are often the natural replacement for legacy Pockets that displayed custom content in a specific part of a page.
They work well when you need a branded content block, a custom announcement, a special promotional area, a lightweight embed, or a page-specific call to action that does not have a standard built-in equivalent.
For community managers, the most important thing to know is that a Custom HTML widget is designed to live inside Layout Editor. That means you can place it in the layout intentionally, rather than relying on an older injection point. It is a much more visual and manageable way to control where custom content appears.
It is also important to know that Custom HTML widgets are more structured than old Pockets. Instead of mixing everything together, they separate markup, styling, and JavaScript into different tabs. That makes them cleaner to maintain, but it also means older code often needs to be reorganized before it will work properly.
When the work belongs somewhere else
Some legacy Pockets were never really page content at all. They were global behaviors that happened to be implemented through a Pocket because that was the available method at the time.
This is common with analytics snippets, tracking scripts, consent logic, and global event handlers. These should generally not be moved into Custom HTML widgets unless there is also a visible content component that belongs in the layout.
For site-wide behavior, the better home is usually Style Guide JavaScript. Community managers do not necessarily need to implement that themselves, but it is useful to understand the distinction so that the right work goes to the right place.
A practical method to approach this migration
The easiest way to manage this work is to think in stages.
- First, identify which Pockets matter for pages that are already in Layout Editor or are about to move there. Those are the ones that need attention first.
- Next, decide whether each customization should be replaced by a built-in widget, a Custom HTML widget, a global script configuration, or a more advanced custom widget. This step is less about code and more about choosing the right destination.
- Then, once you know the destination, you can either rebuild the content directly in Layout Editor or hand the more technical items to a developer with clear notes about what the Pocket used to do, where it should appear, and who should see it.
This type of planning makes the migration much easier, especially for teams where community managers and developers work together.
What should you know about Custom HTML widgets
The most important thing to understand is that Custom HTML widgets are not just "new Pockets." They are similar in purpose but they behave differently.
A Custom HTML widget separates content into HTML, CSS, and JavaScript tabs. This helps keep things organized, but it means older Pocket code often cannot be copied over exactly as-is.
The widget also uses a more isolated rendering model, which helps prevent styling conflicts with the rest of the site. That is usually a good thing, but it can affect how older code behaves, especially if a script expected direct access to the broader page structure.
For non-technical users, the main takeaway is simple: if a Pocket was purely presentational, it may be easy to move. If it depended on scripts, third-party services, or more complex behavior, it is wise to involve a developer early.
No developer or technical resources? Don’t let that stop you
Not every community team has immediate access to a developer, and in many organizations the first person handling a Pocket migration will be a community manager, digital manager, or platform owner. That does not mean this update has to stop.
If you have access to an AI assistant (an increasingly common resource in recent years) that can help with code, you may be able to use it as a practical support tool during the transition. This can be especially helpful for simpler Pockets, such as promotional banners, content blocks, light styling changes, or basic JavaScript behavior.
That said, it is important to approach AI-assisted migration carefully. Legacy Pocket code was often written for a different environment, and even when an AI assistant produces a promising result, the output should be treated as a draft to test rather than a finished solution to publish immediately.
IMPORTANT: The most important rule in this scenario is simple: Always test migrated widgets on a staging site before publishing them to production.
This matters even more when AI is helping with the code. A generated answer may look correct while still containing issues that only show up in a real layout, such as broken styling, JavaScript errors, unexpected behavior in the widget environment, visibility problems, or conflicts with third-party scripts and security settings.
For that reason, AI can be very useful as a helper, but it should not replace a staging and review process.
An AI assistant can often help you reorganize a Pocket's HTML, CSS, and JavaScript into the correct widget tabs, identify whether a Pocket is better suited for a built-in widget, a Custom HTML widget, or Style Guide JavaScript, and produce a cleaner starting point for testing.
What AI should not replace is judgment about where the customization belongs, or the responsibility to confirm that it works correctly. Even when AI helps with the rewrite, you still need to confirm that the page is actually using Layout Editor, that the widget appears in the correct place, that it behaves properly on desktop and mobile, and that any external scripts or assets are allowed by your security settings.
This is especially important for anything involving analytics, ads, consent management, or third-party integrations. In those cases, staging is essential and technical review is still strongly recommended.
- A good way to use AI is to start by gathering the old Pocket code and writing down, in plain language, what the Pocket is supposed to do. Note where it appears, whether it is visible to all users or only certain audiences, and whether it contains HTML, styling, JavaScript, or a third-party embed.
- Then, ask the AI assistant to help classify the Pocket before asking it to rewrite anything. In many cases, the best outcome is not a Custom HTML widget at all. The Pocket might be better replaced by an out-of-the-box widget or moved to a global script area.
- Once you are confident that a Custom HTML widget is the right destination, ask the AI assistant to rewrite the old Pocket specifically for Vanilla's Custom HTML widget structure. Make sure it returns separate content for the HTML, CSS, and JavaScript tabs, rather than a single mixed snippet.
- From there, copy the result into a staging environment and test it carefully. If something does not work, go back to the AI assistant with the error, screenshot, or behavior description and ask it to revise the code.
Sample prompt for using an AI Assistant
Here is a sample prompt a community manager can use with most AI tools to get useful help transitioning a Pocket into a Custom HTML widget:
======================================================================
I am migrating a legacy Pocket from Vanilla Forums into a Custom HTML widget in Layout Editor.
Please help me rewrite this Pocket for use in a Custom HTML widget.
Important requirements:
- Assume the target is a Vanilla Layout Editor Custom HTML widget.
- Separate the solution into three parts: HTML tab, CSS tab, and JavaScript tab.
- Do not use
<script> or <style> tags in the HTML output. - If part of this code should not live in a Custom HTML widget and would be better in Style Guide JavaScript or replaced by a built-in widget, tell me that clearly before giving code.
- Preserve the intended behavior, layout, and messaging as closely as possible.
- Simplify the code where appropriate so it is easier to maintain.
- Explain any part of the old Pocket that may not work the same way in a Custom HTML widget.
- Assume I will test this on a staging site before publishing.
Here is what the Pocket currently does:
[Describe what the Pocket is for, where it appears, and who should see it.]
Here is the old Pocket code:
[Paste the full Pocket code here]
Please return:
- A short assessment of whether this should become a Custom HTML widget, a built-in widget, or Style Guide JavaScript.
- If Custom HTML is appropriate, provide full code for the HTML tab.
- Provide full code for the CSS tab.
- Provide full code for the JavaScript tab.
- Include notes on anything I should test on staging before publishing.
======================================================================
This kind of prompt works well because it does more than ask for a code rewrite. It also asks the AI assistant to help confirm whether the migration path is correct in the first place.
When AI is helping with the rewrite, staging should be treated as a required step, not a nice-to-have. At a minimum, test whether:
- the widget appears in the correct layout,
- the content displays properly across screen sizes, and
- any buttons, links, or interactive behavior work as expected.
- Also confirm that the widget only appears where it should and for the users who should see it.
If the migrated Pocket includes JavaScript or a third-party integration, check the browser console for errors and confirm that nothing is being blocked by your site's security settings.
The safest mindset is this:
- use AI to accelerate the rewrite,
- use staging to validate the result, and
- use production only after both the code and the behavior have been checked carefully.
Common migration scenarios
- A promotional banner is usually a straightforward migration. In many cases, it can be rebuilt as either a built-in call-to-action widget or a Custom HTML widget, depending on how customized the design needs to be.
- A help box or content prompt may no longer need custom code at all if a built-in widget covers the use case.
- A review widget, calendar, ad integration, or third-party embed is more likely to need technical review. These often involve external scripts, security settings, or assumptions about how the page is structured.
- An analytics or tag manager Pocket should usually be treated as global site behavior, not page content. That work generally belongs in the Style Guide rather than Layout Editor itself.
Seeing your Pockets in those terms can make the migration feel much more manageable.
When to involve a developer
Community managers can often lead the planning and content decisions for this migration, but certain kinds of Pockets should be handed to a developer or technical resource.
- That includes anything with JavaScript, anything that loads content from a third-party service, anything that affects site-wide behavior, and anything that needs to behave differently based on user context or page state.
- It is also a good idea to involve a developer if the old Pocket is especially old, messy, or difficult to understand. In many cases, the right solution is not to translate the old code line by line, but to rewrite it in a cleaner way for the new environment.
For developers assisting with this work
If you are supporting a community manager with this project, here are the most useful technical principles to keep in mind when recoding legacy Pockets into Custom HTML widgets.
Treat this as a rebuild, not a copy-paste exercise
Legacy Pocket code often mixes HTML, CSS, inline styles, and JavaScript together. Custom HTML widgets expect those concerns to be separated cleanly. In practice, that means most non-trivial Pockets should be refactored rather than copied directly.
Remove <script> and <style> tags from old snippets and place their contents into the appropriate widget tabs. This alone resolves many failed first attempts at migration.
Understand the Shadow DOM boundary
Custom HTML widgets render inside a Shadow DOM. This is more than an implementation detail: it means that scripts running in the page head, and scripts in other widgets, cannot reach elements inside the widget using standard document-level selectors. Any migrated Pocket that relied on an external script targeting a container element by ID will silently fail in this environment.
The most common case is ad integrations. Google Ad Manager and similar tools work by locating pre-placed container divs in the main document. If those containers live inside the widget's Shadow DOM, the ad script will not find them. The correct pattern is to create the container element in JavaScript and append it to the widget's parent in the main document, rather than placing it in the widget's HTML tab directly.
customHtmlRoot.parentElement.appendChild(element) is the approach to follow.
This boundary also affects event handlers, DOM mutations, and any third-party code that assumes direct access to a globally visible element. When a migrated Pocket's JavaScript is not producing visible errors but also not doing anything, the Shadow DOM boundary is often the first thing to check.
Expect DOM access patterns to change
Beyond the Shadow DOM boundary, be aware that any older JavaScript relying on global selectors or assumptions about where elements live in the page may need to be rewritten. This is especially relevant when migrating event handlers, DOM mutations, or third-party code that expects a globally accessible container.
Account for SPA navigation and script re-execution
Vanilla is a React single-page application. Navigating between pages does not trigger a full page reload, which means scripts that executed when the widget first mounted may not re-execute when a user returns to that page through in-app navigation.
Always test migrated behavior by navigating away from a page and back, not just by refreshing. If re-execution on navigation is required, a MutationObserver watching for the widget container to appear is often the most reliable approach.
Avoid ID-based selectors when a widget may appear more than once
If a Custom HTML widget is placed more than once on a page, or reused across multiple layouts, any JavaScript using getElementById or CSS targeting a unique ID will break or produce unpredictable results. Use class-based selectors scoped to a unique wrapper class on the widget's root element, and use document.currentScript.closest() to isolate logic to a specific widget instance where needed.
The same principle applies to CSS. The widget's CSS tab injects styles into the page globally, not scoped to the widget container. Without a unique wrapper class on the root element, broad selectors can bleed into other layout components, especially if the widget appears across multiple page types.
Separate page content from global behavior
When reviewing old Pocket code, determine whether the logic is truly layout-specific or whether it is global behavior that happened to be implemented locally.
A visible banner or call to action belongs in Layout Editor. A site-wide analytics loader, tag manager integration, or consent gate belongs in Style Guide JavaScript. Many difficult migrations become easier once that separation is made clearly.
Isolate each function in its own onVanillaReady() call
When placing multiple functions in Style Guide JavaScript, wrap each one in its own onVanillaReady() rather than chaining them inside a single call.
Vanilla wraps each onVanillaReady() invocation in a try-catch block. If functions share a single call and one throws a fatal error, the others will silently stop executing — which is one of the harder failure modes to diagnose.
Keeping them separate means an error in one function does not affect the rest of the script.
Do not assume jQuery is available
Legacy Pocket code frequently relied on $() or jQuery(). In Layout Editor contexts, jQuery availability is not guaranteed in the same way it was in older Vanilla pages.
Write in vanilla JavaScript, or explicitly verify jQuery is present before using it. This is one of the more common reasons migrated code silently fails without producing an obvious error.
Be cautious with third-party embeds
Vendor snippets are one of the most common friction points. Many assume a traditional page environment, rely on raw script tags, expect access to the global DOM, or require external domains that may be restricted by CSP.
Where possible, split the integration into its functional parts:
- visible container markup targeting the main document,
- styles in the CSS tab, and
- logic in the JS tab.
If the vendor's approach does not adapt well to the widget environment, it may be more reliable to load the integration globally through Style Guide JavaScript and target a container more deliberately.
Scripts injected dynamically into the page head should carry the page's current nonce value, retrieved from an existing script element. Without it, CSP will often block the injected script from executing, and the failure may not produce a visible error in the widget itself — only in the browser console. This is particularly relevant for tag manager integrations, which frequently load additional scripts dynamically and require the nonce to be propagated to those child scripts as well.
Check security requirements early
If the migrated implementation pulls in external scripts, styles, fonts, or embedded assets, confirm that the required domains are properly allowed in the site's Content Security Policy settings:
Dashboard > Settings > Technical > Security
This is an easy issue to overlook and a common cause of content that worked through a Pocket but silently fails after migration. Check the browser console for CSP errors before concluding that a widget implementation is broken.
More detailed information on the security settings within the Vanilla platform can be found here.
Recreate targeting with product features where possible
Legacy Pockets often encoded page or audience logic through placement settings or custom conditions. When rebuilding in Layout Editor, try to reproduce that behavior through layout placement and widget visibility settings instead of hardcoding conditions into the widget itself. Code-based conditionals in the JavaScript tab should be a fallback, not the first instinct. Keeping targeting logic in the product layer means non-technical administrators can manage it later without touching code.
Map Pocket placements to Layout Editor slots explicitly
Old Pockets were assigned to named hooks such as BetweenDiscussions, AfterBody, or PanelAfter. These do not have automatic equivalents in Layout Editor, and the mapping is not always one-to-one.
As part of the migration, explicitly identify which Layout Editor section, page type, and position corresponds to each old Pocket placement. Some hooks may require creating a new page-specific layout or rethinking which page a piece of content belongs on.
Use the migration as a cleanup opportunity
Many older Pockets were built under different product constraints. A direct translation may preserve unnecessary complexity. If the original customization can now be replaced with a built-in widget, simplified into a lightweight Custom HTML block, or rebuilt as a reusable widget, that is usually preferable to carrying legacy structure forward.
Where Widget Builder may be the better long-term option
Sometimes a Pocket has evolved into something larger than a one-off content block. It may need configuration, richer interactivity, user awareness, reuse across multiple pages, or ongoing maintenance.
That is where Widget Builder can be a better long-term fit than Custom HTML. For community managers, the main benefit is that a developer can build something more robust once, and the team can then place and manage it more easily inside Layout Editor. For developers, Widget Builder offers a cleaner foundation for advanced components than trying to stretch Custom HTML beyond its intended use case.
A useful way to think about it:
- Custom HTML is often best for simple custom content.
- Widget Builder is better when the customization starts to behave more like a product feature.
A good working model for teams
The most successful migrations usually divide responsibilities clearly.
- Community managers are often best positioned to decide which content still matters, where it belongs in the page experience, and whether a built-in widget can meet the need.
- Developers are best positioned to refactor older code, handle third-party integrations, resolve security-related issues, and decide whether a Custom HTML widget or Widget Builder is the better technical path.
- AI can be a useful middle layer when a community manager needs help getting started or translating an older Pocket into a cleaner first draft. But AI works best when paired with staging, review, and clear ownership over final testing.
When those roles are clear, the migration tends to move faster and produce cleaner results.
Final guidance
If you are managing this transition, the most important thing to remember is that moving away from Pockets is not just about replacing an old customization tool: it is about adopting a more maintainable model for how content and behavior live on your site.
Whenever possible, reduce custom code. When custom code is needed, place it in the right layer.
- Use Layout Editor for layout content,
- use Custom HTML widgets for lightweight custom blocks,
- use Style Guide JavaScript for global behavior, and
- use Widget Builder when the solution needs to be more reusable or more sophisticated.
Approached this way, the migration becomes much less intimidating. It becomes a practical cleanup and modernization project, one that gives your team better control over the site in the long run.