Tool
Build and manage lists of anchor text and URLs for Shopify internal linking. The JSON output powers the blink-auto-linker Liquid snippet, which automatically turns matching phrases in your store content into links.
Open tool āStore a list of anchor text strings mapped to internal URLs, ready to export as JSON.
Paste a two-column CSV or a JSON array to bulk-load entries in one step.
Drag entries into the order you want before exporting.
Sort AāZ or ZāA, remove duplicates, and apply Proper Case to selected entries.
Instantly filter the list by find text or URL to locate and edit specific entries.
Download your list as a .blink-links.json file and reload it at any time.
Use the Find and URL fields at the top of the left panel. Enter the anchor text you want to match (e.g. Nike) and the destination URL (e.g. /collections/nike), then click + Add entry or press Enter.
Switch to the csv or paste tab in the right panel:
find, url. A header row is detected and skipped automatically.{"{"}"find":"...","url":"..."{"}"} objects. Click Extract entries.Both modes replace all current entries.
Click edit on any row to load it into the form. Make your changes and click Update entry, or press Escape to cancel.
Drag the ā æ handle on the left of any row to reorder entries. Drag-to-reorder is disabled while the filter is active.
Tick the checkbox on individual rows, or use the checkbox in the panel header to select all visible entries. With a selection active you can:
Use the AāZ and ZāA buttons to sort all entries alphabetically by find text. Remove Duplicates removes any entries with the same find text (case-insensitive), keeping the first occurrence. Both actions appear when there are two or more entries.
The blink-auto-linker Liquid snippet reads the JSON from a shop metafield and automatically wraps matching phrases in your store content with anchor tags ā no manual link insertion needed. The rules are applied in order of phrase length (longest first) to prevent shorter rules from matching inside longer ones.
In your Shopify admin go to Settings ā Custom data ā Shop and add a new metafield definition:
blinkautolinkerUse the Auto Link Manager to build your list of find/URL pairs, then click copy in the output panel and paste the JSON into the metafield value. The expected format is:
[
{ "find": "Nike", "url": "/collections/nike" },
{ "find": "Running Shoes", "url": "/collections/running-shoes" }
]
Create a new snippet in your Shopify theme called blink-auto-linker.liquid and paste in the snippet code below.
Pass any text variable into the snippet using the text parameter:
{%- render 'blink-auto-linker', text: your_text_variable -%}
The snippet wraps matched phrases in <a> tags. It skips text already inside an anchor element to prevent nested links.
{% comment %}
SETUP
1. Create a shop metafield definition with namespace "blink" and key "autolinker". Set the content type to "JSON".
2. In the metafield value, add an array of objects with "find" and "url" properties. For example:
[
{
"find": "Your Brand Name",
"url": "https://yourbrand.com"
},
{
"find": "Another Phrase",
"url": "https://anotherlink.com"
}
]
3. Use the Blink Auto Link Manager tool to generate the JSON, then copy the output into the metafield value.
4. Render the snippet wherever you need auto-linking:
{%- render 'blink-auto-linker', text: your_text_variable -%}
{%- endcomment -%}
<div id="blink-autolinker">{{ text }}</div>
<script>
window.blinkAutoLinkerRules = {{ shop.metafields.blink.autolinker.value | json }};
(function () {
const rules = window.blinkAutoLinkerRules;
const container = document.getElementById('blink-autolinker');
if (!rules || !rules.length || !container) return;
// Sort longest find phrase first to prevent shorter rules matching inside longer ones
rules.sort(function (a, b) {
return b.find.length - a.find.length;
});
// Work on a temporary element so we can walk text nodes safely
const temp = document.createElement('div');
temp.innerHTML = container.innerHTML;
rules.forEach(function (rule) {
const escaped = rule.find.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const regex = new RegExp('\\b' + escaped + '\\b', 'gi');
applyRule(temp, regex, rule.url);
});
container.innerHTML = temp.innerHTML;
function applyRule(node, regex, url) {
// Walk child nodes ā skip anchor elements entirely to prevent nested links
Array.from(node.childNodes).forEach(function (child) {
if (child.nodeType === Node.TEXT_NODE) {
if (regex.test(child.nodeValue)) {
regex.lastIndex = 0;
const span = document.createElement('span');
span.innerHTML = child.nodeValue.replace(regex, function (match) {
return '<a href="' + url + '">' + match + '</a>';
});
child.replaceWith(...span.childNodes);
}
} else if (child.nodeType === Node.ELEMENT_NODE && child.tagName !== 'A') {
applyRule(child, regex, url);
}
});
}
})();
</script>
document.getElementById, so if you render it more than once on the same page only the first instance will be processed. Wrap each call in a unique container if you need multiple instances.
.blink-links.json file. This preserves the full entry list including IDs and order..blink-links.json file to restore your list exactly as you left it.