Manual placement
Hand-place the Product Genius widget or search bar in theme code when app blocks are not an option.
Prefer app blocks wherever they work
Everything on this page is a fallback. Hand-edited theme code is not managed by the Product Genius app: it does not travel with the app, it is not updated when the app is, it is lost when you replace or reinstall the theme, and it is outside what Product Genius support can fix remotely. Use the AI widget block and the search bar block if your theme offers them at all.
Before editing theme code: duplicate the theme (Online Store → Themes → … → Duplicate) and edit the copy, so you have a one-click way back.
When you would do this
- Your theme does not support app blocks. Older themes (Liquid templates rather than JSON templates) have no Add block → Apps menu, so the extension's blocks are never offered.
- You need the widget or bar somewhere a section cannot reach — most commonly a search bar inside a header that does not accept app blocks.
If neither applies, stop here and use the blocks.
The snippets below are the markup the app blocks emit, with the theme-editor plumbing removed. Editing theme code is done in Online Store → Themes → … → Edit code.
The AI widget by hand
The AI widget block's whole body is two elements, and neither depends on being inside an app block. Paste them where the widget should appear:
<div id="pg-app-wrapper"></div>
<script id="pg-app-fetch" src="https://tags.productgenius.io/tag.js?shop={{ shop.permanent_domain }}"></script>Copy it exactly as written:
- Keep the ids.
pg-app-wrapperis where the widget renders, and the loader script uses element ids as its once-only initialisation guard. Renaming either one can stop the widget loading with no error. - Keep
{{ shop.permanent_domain }}as a Liquid tag — do not paste your.myshopify.comdomain as a literal. The Liquid tag keeps working if your store's domains change, and it is the value the app block itself uses. - Include it once per rendered page. A second copy creates a duplicate
pg-app-wrapperid, and only one element can receive the widget.
Where to put it
Paste the two elements into the template or section file for the page that should
show the widget — for example sections/main-product.liquid for product pages, at
the point in the markup where the widget should sit.
This is the closer analogue of the app block: the widget appears on exactly the pages whose files you edited, in exactly the position you chose.
The search bar by hand
The search bar is harder to hand-place than the widget, because the app block relies on two things a theme file does not get for free: the theme editor's per-block settings, and the stylesheet the extension attaches to the block.
Check the container selector first
The live bar mounts into a container matching the selector in your store's Product
Genius configuration — for the app block, that is .pg-search-mount. A hand-placed
container must carry the same class, and your store's configuration must be pointing
at it. Confirm this with your Product Genius contact before you start; otherwise you
will hand-place markup that never gets replaced by the live bar.
Option 1: mount container only
The smallest possible version is the container the live bar looks for:
<div class="pg-search-mount"></div>Nothing to style, nothing to copy. The trade-off is that there is no search field at all until the Product Genius bundle mounts — no loading state and no working fallback if it never does. Whether the live bar mounts into an empty container is a property of your store's Product Genius configuration rather than of this markup, so verify it on a real storefront page before shipping.
Option 2: reproduce the skeleton
To keep the app block's behavior — a working native search that the live bar replaces — reproduce the block's markup with your chosen values written in directly. This is the Full bar layout:
{%- assign pg_search_action = routes.search_url | default: '/search' -%}
<div class="pg-search-mount"
style="max-width: 320px; --pg-skeleton-size: 38px; --pg-compact-expanded-width: 320px; --pg-skeleton-radius: 0px;">
<form class="pg-search-skeleton" role="search" action="{{ pg_search_action }}" method="get">
<span class="pg-search-skeleton__icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" width="16" height="16">
<circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="2"/>
<path d="M21 21l-4.35-4.35" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
</span>
<input class="pg-search-skeleton__input" type="search" name="q"
placeholder="Search" aria-label="Search" autocomplete="off"/>
<span class="pg-search-skeleton__shimmer" aria-hidden="true"></span>
</form>
</div>For the Icon only layout, add the pg-search-mount--compact class to the container
and replace the form with a link to the same URL, dropping the input:
{%- assign pg_search_action = routes.search_url | default: '/search' -%}
<div class="pg-search-mount pg-search-mount--compact"
style="--pg-skeleton-size: 38px; --pg-compact-expanded-width: 320px; --pg-skeleton-radius: 0px;">
<a class="pg-search-skeleton" href="{{ pg_search_action }}" aria-label="Search">
<span class="pg-search-skeleton__icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" width="16" height="16">
<circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="2"/>
<path d="M21 21l-4.35-4.35" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
</span>
<span class="pg-search-skeleton__shimmer" aria-hidden="true"></span>
</a>
</div>Notes on the differences from the app block:
- Settings become literal values. The block reads
block.settingsand writes them into a{% style %}block keyed on a per-instance id. With no block context, put the same custom properties in an inlinestyleattribute — inline declarations outrank the stylesheet's class-level defaults, so they behave the same way. The values above are the block's defaults:--pg-skeleton-sizeis Height (38 px),--pg-skeleton-radiusis Corner radius,max-widthand--pg-compact-expanded-widthare Max width (320 px). Add--pg-skeleton-bg,--pg-skeleton-border,--pg-skeleton-color,--pg-skeleton-placeholder-color, and--pg-skeleton-icon-colorif you need colors other than the defaults. block.shopify_attributesis gone. The block emits it so the theme editor can link the rendered element to its entry in the sidebar. It has no effect on the storefront, so hand-placed markup omits it.- The placeholder and the accessible label are separate strings. The block derives
the
aria-labelfrom the placeholder setting and falls back to the theme's translatedsearch.label. Written by hand, set both explicitly, as above.
The stylesheet
The skeleton in Option 2 is unstyled without pg-search.css. That file is an asset
of the app extension, and theme code cannot reference it — asset_url in your theme
resolves against your own theme's assets/ folder, not the extension's. So:
-
Ask your Product Genius contact for the current
pg-search.css. -
Add it to your theme as
assets/pg-search.css. -
Reference it from
layout/theme.liquid:{{ 'pg-search.css' | asset_url | stylesheet_tag }}
Your copy is a snapshot. If Product Genius changes the stylesheet, the app block picks the change up automatically and your copy does not — which is the core reason to prefer the block.
Also worth knowing
The class names in this markup (pg-search-mount, pg-search-skeleton, and its
__icon / __input / __shimmer parts) and the data-pg-search-ready attribute the
bundle sets on the container to hide the skeleton are the contract between the
stylesheet and the bundle. Do not rename them, and do not set
data-pg-search-ready yourself — the bundle owns it, and setting it early hides your
fallback while there is nothing to replace it.
Removing hand-placed code
Deleting a block in the theme editor is complete: nothing remains. Hand-placed code
has to be removed the same way it was added — delete the markup from every file you
edited, plus the stylesheet reference and assets/pg-search.css if you added them.
Uninstalling the Product Genius app does not remove it, which leaves a script tag
pointing at a service your store no longer uses.
How is this guide?