{"id":288783,"date":"2026-03-21T05:34:00","date_gmt":"2026-03-21T05:34:00","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/gt-link-manager\/"},"modified":"2026-07-26T03:20:24","modified_gmt":"2026-07-26T03:20:24","slug":"gt-link-manager","status":"publish","type":"plugin","link":"https:\/\/ps.wordpress.org\/plugins\/gt-link-manager\/","author":13255989,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.7.0","stable_tag":"1.7.0","tested":"7.0.2","requires":"6.4","requires_php":"8.0","requires_plugins":null,"header_name":"GT Link Manager","header_author":"Gaurav Tiwari","header_description":"Fast pretty-link manager with direct redirects and low overhead.","assets_banners_color":"f6f9fa","last_updated":"2026-07-26 03:20:24","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/wordpress.org\/plugins\/gt-link-manager\/","header_author_uri":"https:\/\/gauravtiwari.org\/","rating":0,"author_block_rating":0,"active_installs":100,"downloads":2362,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.6.1":{"tag":"1.6.1","author":"gauravtiwari","date":"2026-04-11 18:31:41"},"1.7.0":{"tag":"1.7.0","author":"gauravtiwari","date":"2026-07-26 03:20:24"},"v1.5.1":{"tag":"v1.5.1","author":"gauravtiwari","date":"2026-03-21 05:33:49"},"v1.5.2":{"tag":"v1.5.2","author":"gauravtiwari","date":"2026-03-21 05:38:23"},"v1.5.3":{"tag":"v1.5.3","author":"gauravtiwari","date":"2026-03-21 07:07:27"},"v1.6.0":{"tag":"v1.6.0","author":"gauravtiwari","date":"2026-03-28 08:57:36"},"v1.6.1":{"tag":"v1.6.1","author":"gauravtiwari","date":"2026-03-31 10:54:30"}},"upgrade_notice":{"1.7.0":"<p>Adds geolocation targeting: route each link by visitor country using the header your CDN already sends \u2014 no GeoIP database, no external API, no added latency. Two columns are added to the links table automatically on upgrade; existing links are untouched and keep redirecting exactly as before. Enable it under GT Links \u2192 Settings \u2192 Geolocation Targeting.<\/p>","1.6.1":"<p>Fixes nonce mismatch bug affecting trash\/restore\/delete actions, hardens regex pattern validation, adds REST API descriptions and category caching.<\/p>","1.6.0":"<p>Adds direct (prefix-free) and regex (pattern-based) redirect modes. Enable in Settings &gt; Advanced Redirects. Fully backwards compatible.<\/p>","1.5.2":"<p>Data is now preserved on uninstall by default. Enable &quot;Delete Data on Uninstall&quot; in Settings to remove all data.<\/p>","1.5.1":"<p>Fixes admin CSS rendering issues (double card borders, stacked buttons) and adds WordPress.org plugin assets.<\/p>","1.4.0":"<p>Renamed internal prefix to <code>gtlm_<\/code> for wp.org compliance, fixed nonce and SQL safety issues, added card UI to admin pages.<\/p>","1.3.1":"<p>Fixes GT Link toolbar popover alignment in the block editor to match core behavior.<\/p>","1.3.0":"<p>Admin refactor, Pretty Links import preset, improved sanitization, build tooling, and PHP 8.0 support.<\/p>","1.2.3":"<p>Fixes release packaging so the GT Link block editor toolbar assets are included in update zips.<\/p>","1.2.2":"<p>Fixes block editor GT Link toolbar button not showing on WordPress 6.8+.<\/p>","1.2.0":"<p>Critical fix: restores links that disappeared after 1.1.9 update. Adds automatic DB migration on update.<\/p>","1.1.9":"<p>Links can now be activated\/deactivated and deleted links go to trash first with restore support.<\/p>","1.1.7":"<p>Fixes editor scroll jump when opening GT Link popover from the toolbar.<\/p>","1.1.6":"<p>Full REST API pagination, args validation on all write endpoints, XSS fix in admin quick edit.<\/p>","1.1.4":"<p>Positions link search popover near selected text instead of top-left corner.<\/p>","1.1.3":"<p>Fixes format not registering on WP 6.9+ due to tagName conflict with core\/underline.<\/p>","1.1.2":"<p>Uses standard RichTextToolbarButton for reliable format toolbar placement.<\/p>","1.1.1":"<p>Ensures GT Link toolbar button appears on all RichText instances.<\/p>","1.1.0":"<p>Rebuilt block editor link inserter with proper WordPress scripts build. Fixes toolbar button not showing.<\/p>","1.0.4":"<p>Improves block editor toolbar behavior and redirect reliability.<\/p>","1.0.0":"<p>Initial release.<\/p>"},"ratings":{"1":0,"2":0,"3":0,"4":0,"5":0},"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3487610,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3487610,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3487610,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3487610,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{"blueprint.json":{"filename":"blueprint.json","revision":3622966,"resolution":false,"location":"assets","locale":"","contents":"{\"$schema\":\"https:\\\/\\\/playground.wordpress.net\\\/blueprint-schema.json\",\"meta\":{\"title\":\"GT Link Manager\",\"description\":\"Fast, free branded link manager with custom database tables, early redirects, CSV import\\\/export, and block editor integration.\",\"author\":\"gauravtiwari\",\"categories\":[\"links\",\"redirects\",\"marketing\"]},\"landingPage\":\"\\\/wp-admin\\\/admin.php?page=gtlm-links\",\"preferredVersions\":{\"php\":\"8.2\",\"wp\":\"latest\"},\"phpExtensionBundles\":[\"kitchen-sink\"],\"features\":{\"networking\":true},\"login\":true,\"steps\":[{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"gt-link-manager\"},\"options\":{\"activate\":true}}]}"}},"all_blocks":[],"tagged_versions":["1.6.1","1.7.0","v1.5.1","v1.5.2","v1.5.3","v1.6.0","v1.6.1"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3487613,"resolution":"1","location":"assets","locale":"","width":2600,"height":1452},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3487613,"resolution":"2","location":"assets","locale":"","width":3088,"height":1694},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3487613,"resolution":"3","location":"assets","locale":"","width":3034,"height":1916},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3487613,"resolution":"4","location":"assets","locale":"","width":3084,"height":1806},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3487613,"resolution":"5","location":"assets","locale":"","width":3086,"height":1508}},"screenshots":{"1":"<strong>All Links<\/strong> \u2014 admin list with search, filters, status views, and bulk actions","2":"<strong>Add\/Edit Link<\/strong> \u2014 form with branded URL preview, redirect type, rel attributes, and categories","3":"<strong>Categories<\/strong> \u2014 manage link categories with parent\/child hierarchy","4":"<strong>Settings<\/strong> \u2014 configure prefix, defaults, flush permalinks, and run diagnostics","5":"<strong>Import\/Export<\/strong> \u2014 CSV import with column mapping preview and preset support"}},"plugin_section":[],"plugin_tags":[5362,175,456,233598,726],"plugin_category":[55],"plugin_contributors":[90890],"plugin_business_model":[],"class_list":["post-288783","plugin","type-plugin","status-publish","hentry","plugin_tags-affiliate-links","plugin_tags-links","plugin_tags-marketing","plugin_tags-pretty-links","plugin_tags-redirects","plugin_category-seo-and-marketing","plugin_contributors-gauravtiwari","plugin_committers-gauravtiwari"],"banners":{"banner":"https:\/\/ps.w.org\/gt-link-manager\/assets\/banner-772x250.png?rev=3487610","banner_2x":"https:\/\/ps.w.org\/gt-link-manager\/assets\/banner-1544x500.png?rev=3487610","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/gt-link-manager\/assets\/icon-128x128.png?rev=3487610","icon_2x":"https:\/\/ps.w.org\/gt-link-manager\/assets\/icon-256x256.png?rev=3487610","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/gt-link-manager\/assets\/screenshot-1.png?rev=3487613","caption":"<strong>All Links<\/strong> \u2014 admin list with search, filters, status views, and bulk actions"},{"src":"https:\/\/ps.w.org\/gt-link-manager\/assets\/screenshot-2.png?rev=3487613","caption":"<strong>Add\/Edit Link<\/strong> \u2014 form with branded URL preview, redirect type, rel attributes, and categories"},{"src":"https:\/\/ps.w.org\/gt-link-manager\/assets\/screenshot-3.png?rev=3487613","caption":"<strong>Categories<\/strong> \u2014 manage link categories with parent\/child hierarchy"},{"src":"https:\/\/ps.w.org\/gt-link-manager\/assets\/screenshot-4.png?rev=3487613","caption":"<strong>Settings<\/strong> \u2014 configure prefix, defaults, flush permalinks, and run diagnostics"},{"src":"https:\/\/ps.w.org\/gt-link-manager\/assets\/screenshot-5.png?rev=3487613","caption":"<strong>Import\/Export<\/strong> \u2014 CSV import with column mapping preview and preset support"}],"raw_content":"<!--section=description-->\n<p><strong>GT Link Manager<\/strong> is a <strong>100% free<\/strong> high-performance branded link manager for WordPress \u2014 no upsells, no premium tiers, no paywalls. It stores links in <strong>custom database tables<\/strong> (not custom post types), resolves redirects early on <code>init<\/code>, and keeps your site fast \u2014 even with thousands of links.<\/p>\n\n<p>Your links follow a clean URL pattern: <strong>yoursite.com\/go\/your-slug<\/strong> (the prefix is configurable and can even be removed on individual links).<\/p>\n\n<p><strong><a href=\"https:\/\/gauravtiwari.org\/product\/gt-link-manager\/\">Official Page &amp; Documentation<\/a><\/strong> | <strong><a href=\"https:\/\/gauravtiwari.org\/course\/gt-link-manager-training\/\">Free Training Course<\/a><\/strong> | <strong><a href=\"https:\/\/gauravtiwari.org\/gt-link-manager-rest-api-guide-ai-tools\/\">REST API &amp; AI Tools Guide<\/a><\/strong><\/p>\n\n<h4>Why GT Link Manager?<\/h4>\n\n<p>Most link management plugins use custom post types, which means every redirect loads the full WordPress template stack. GT Link Manager takes a different approach \u2014 it intercepts the request early, looks up the slug in a <strong>UNIQUE-indexed database column<\/strong>, sends the redirect header, and exits. No theme loading, no unnecessary queries.<\/p>\n\n<h4>Key Features<\/h4>\n\n<ul>\n<li><strong>Fast direct redirects<\/strong> \u2014 resolves links on <code>init<\/code> (priority 0) via direct DB lookup, no CPT overhead<\/li>\n<li><strong>301, 302, and 307 redirects<\/strong> \u2014 choose the right redirect type for SEO, temporary, or method-preserving redirects<\/li>\n<li><strong>Rel attribute controls<\/strong> \u2014 set <code>nofollow<\/code>, <code>sponsored<\/code>, and <code>ugc<\/code> per link for proper SEO attribution<\/li>\n<li><strong>Noindex support<\/strong> \u2014 sends <code>X-Robots-Tag: noindex<\/code> header to prevent search engines from indexing redirect URLs<\/li>\n<li><strong>Categories and tags<\/strong> \u2014 organize links into categories with parent\/child hierarchy and free-form tags<\/li>\n<li><strong>Full admin list table<\/strong> \u2014 search, filter by category\/status, sort by any column, and perform bulk actions<\/li>\n<li><strong>Quick Edit<\/strong> \u2014 update URL, slug, redirect type, rel, category, and status inline without leaving the list<\/li>\n<li><strong>Activate \/ Deactivate<\/strong> \u2014 disable a link without deleting it; inactive links stop redirecting but stay in the database<\/li>\n<li><strong>Trash and restore<\/strong> \u2014 soft-delete links to trash with the option to restore or permanently delete<\/li>\n<li><strong>CSV import and export<\/strong> \u2014 import links from CSV with column mapping preview, or export filtered links; includes <strong>LinkCentral<\/strong> and <strong>Pretty Links<\/strong> compatible presets, supports any CSV though as it allows you to map fields manually.<\/li>\n<li><strong>Block editor integration<\/strong> \u2014 a toolbar button lets you search your links and insert them directly into post content<\/li>\n<li><strong>Branded URL preview<\/strong> \u2014 see the full branded URL as you type, with one-click copy<\/li>\n<li><strong>Normal and Regex Redirects<\/strong> supported too. Don't want to use a prefix like <code>\/go\/<\/code> ? Sure thing. Use the GT Link Manager as an alternative to Rank Math Redirections, Yoast Redirects, Redirection plugin etc. <strong>Tested to be faster<\/strong> than these top tools.<\/li>\n<li><strong>Geolocation targeting<\/strong> \u2014 send visitors from different countries to different destinations on a per-link basis (e.g. India to amazon.in, the US to amazon.com). The country comes from the header your CDN already sends \u2014 Cloudflare, CloudFront, Vercel, App Engine, or an nginx\/Apache GeoIP module \u2014 so there is <strong>no GeoIP database to install, no external API call, and no added latency<\/strong>. Adds roughly 20 microseconds to a geo-enabled redirect and nothing measurable to the rest.<\/li>\n<li><strong>Click tracking<\/strong> \u2014 log clicks via the <code>gtlm_before_redirect<\/code> hook; integrate with GA4, Plausible, Fathom, and more<\/li>\n<li><strong>Developer-friendly<\/strong> \u2014 actions and filters for redirect interception, URL modification, capability control, cache TTL, and more<\/li>\n<\/ul>\n\n<h4>Developer Hooks<\/h4>\n\n<p>GT Link Manager provides a comprehensive set of hooks for customization:<\/p>\n\n<ul>\n<li><code>gtlm_before_redirect<\/code> \u2014 action fired before redirect (use for click tracking or logging)<\/li>\n<li><code>gtlm_redirect_url<\/code> \u2014 filter to modify the destination URL<\/li>\n<li><code>gtlm_redirect_code<\/code> \u2014 filter to modify the HTTP status code<\/li>\n<li><code>gtlm_rel_attributes<\/code> \u2014 filter to modify rel attribute values<\/li>\n<li><code>gtlm_headers<\/code> \u2014 filter to modify redirect response headers<\/li>\n<li><code>gtlm_prefix<\/code> \u2014 filter to override the URL prefix<\/li>\n<li><code>gtlm_capabilities<\/code> \u2014 filter to override the required user capability<\/li>\n<li><code>gtlm_cache_ttl<\/code> \u2014 filter to set object cache TTL for link lookups<\/li>\n<li><code>gtlm_geo_country<\/code> \u2014 filter the detected country code (plug in any detection method you like)<\/li>\n<li><code>gtlm_geo_sources<\/code> \u2014 filter the list of request variables checked for a country<\/li>\n<li><code>gtlm_geo_country_groups<\/code> \u2014 filter country groups usable in rules (ships with <code>EU<\/code>)<\/li>\n<li><code>gtlm_geo_matched_rule<\/code> \u2014 filter the resolved geo rule before the redirect is sent<\/li>\n<li><code>gtlm_geo_blocked<\/code> \u2014 action fired when a visitor is blocked by a geo rule's 404 fallback<\/li>\n<\/ul>\n\n<h4>Free Training Course<\/h4>\n\n<p>The <strong><a href=\"https:\/\/gauravtiwari.org\/course\/gt-link-manager-training\/\">GT Link Manager Training<\/a><\/strong> is a free 25-lesson course (under 2 hours) covering everything from installation to advanced developer integrations:<\/p>\n\n<ul>\n<li><strong>Getting Started<\/strong> \u2014 installation, admin interface, link creation, categories, and redirect configuration<\/li>\n<li><strong>Configuration &amp; Features<\/strong> \u2014 settings, redirect mechanics, block editor integration, and bulk import\/export<\/li>\n<li><strong>Developer Reference<\/strong> \u2014 REST API, hooks and filters, analytics integrations, webhooks, and advanced redirects<\/li>\n<\/ul>\n\n<h4>Analytics &amp; Advanced Integrations<\/h4>\n\n<p>The <strong><a href=\"https:\/\/gauravtiwari.org\/course\/gt-link-manager-training\/developer-reference-1771422601\/\">Developer Reference<\/a><\/strong> includes step-by-step integration guides for:<\/p>\n\n<ul>\n<li><strong>Analytics<\/strong> \u2014 Google Analytics 4 (GA4), Plausible Analytics, Fathom Analytics, Matomo, and Simple Analytics<\/li>\n<li><strong>Tracking<\/strong> \u2014 custom click logging to a database table, dashboard widget, and UTM parameter passthrough<\/li>\n<li><strong>Automation<\/strong> \u2014 webhook notifications for Zapier, Make, and n8n<\/li>\n<li><strong>Advanced redirects<\/strong> \u2014 role-based redirects (route by user role) and geo-based redirects (route by location)<\/li>\n<li><strong>Customization<\/strong> \u2014 custom response headers, hooks and filters reference<\/li>\n<\/ul>\n\n<h4>REST API &amp; AI Tools<\/h4>\n\n<p>GT Link Manager has a full REST API that works with AI tools for programmatic link management. The <strong><a href=\"https:\/\/gauravtiwari.org\/gt-link-manager-rest-api-guide-ai-tools\/\">REST API &amp; AI Tools Guide<\/a><\/strong> covers authentication setup, all available endpoints, and integration with AI platforms including Claude Code, OpenAI Codex, WP-MCP, Novamira, Claudeus WordPress MCP, and WordPress MCP Adapter.<\/p>\n\n<h3>Source Code<\/h3>\n\n<p>The block editor assets (blocks\/link-inserter\/build\/) are compiled from the source at blocks\/link-inserter\/src\/ using @wordpress\/scripts. The full source code is available in this plugin and on GitHub at https:\/\/github.com\/wpgaurav\/gt-link-manager.<\/p>\n\n<p>To build from source:\n    cd blocks\/link-inserter &amp;&amp; npm install &amp;&amp; npm run build<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin folder to <code>\/wp-content\/plugins\/<\/code>.<\/li>\n<li>Activate it from <strong>Plugins<\/strong>.<\/li>\n<li>Go to <strong>GT Links<\/strong> in your wp-admin sidebar.<\/li>\n<li>Create your first link and test it using your prefix (default: <strong>yoursite.com\/go\/your-slug<\/strong>).<\/li>\n<\/ol>\n\n<p>You can change the prefix from <strong>GT Links &gt; Settings<\/strong> at any time.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"is%20this%20a%20pretty%20links%20replacement%3F\"><h3>Is this a Pretty Links replacement?<\/h3><\/dt>\n<dd><p>Yes. GT Link Manager is built for <strong>speed and simplicity<\/strong>. It uses custom database tables instead of custom post types, which means redirects resolve faster and don't pollute your posts table.<\/p><\/dd>\n<dt id=\"does%20it%20track%20clicks%3F\"><h3>Does it track clicks?<\/h3><\/dt>\n<dd><p>Click tracking is supported via the <code>gtlm_before_redirect<\/code> action hook, which fires on every redirect. Use it to log clicks to a custom database table or integrate with external analytics tools \u2014 the <a href=\"https:\/\/gauravtiwari.org\/course\/gt-link-manager-training\/developer-reference-1771422601\/\">Developer Reference<\/a> has step-by-step guides for GA4, Plausible, Fathom, Matomo, Simple Analytics, and custom click logging.<\/p><\/dd>\n<dt id=\"can%20i%20import%20from%20pretty%20links%20or%20linkcentral%3F\"><h3>Can I import from Pretty Links or LinkCentral?<\/h3><\/dt>\n<dd><p>Yes. Go to <strong>GT Links &gt; Import \/ Export<\/strong>, choose the <strong>Pretty Links<\/strong> or <strong>LinkCentral<\/strong> preset, upload your CSV, preview the column mapping, and import. You can also use the <strong>Generic<\/strong> preset for custom CSV formats.<\/p><\/dd>\n<dt id=\"how%20are%20redirects%20resolved%3F\"><h3>How are redirects resolved?<\/h3><\/dt>\n<dd><p>The plugin hooks into WordPress <code>init<\/code> at <strong>priority 0<\/strong> (before most plugins load). It parses the request URI, checks for your configured prefix, and looks up the slug in a <strong>UNIQUE-indexed column<\/strong> in a custom database table. If a match is found, it sends the redirect header and exits immediately \u2014 no theme or template loading.<\/p><\/dd>\n<dt id=\"can%20i%20customize%20which%20users%20can%20manage%20links%3F\"><h3>Can I customize which users can manage links?<\/h3><\/dt>\n<dd><p>Yes. By default, any user with the <code>edit_posts<\/code> capability can manage links. Use the <code>gtlm_capabilities<\/code> filter to change this per context (e.g., require <code>manage_options<\/code> for settings but allow <code>edit_posts<\/code> for link creation).<\/p><\/dd>\n<dt id=\"is%20gt%20link%20manager%20really%20free%3F\"><h3>Is GT Link Manager really free?<\/h3><\/dt>\n<dd><p>Yes, 100%. There are no premium tiers, upsells, or paywalls. Every feature \u2014 including advanced redirects, the REST API, CSV import\/export, and block editor integration \u2014 is included for free. There is also a free training course at <a href=\"https:\/\/gauravtiwari.org\/course\/gt-link-manager-training\/\">gauravtiwari.org<\/a>.<\/p><\/dd>\n<dt id=\"can%20i%20manage%20links%20with%20ai%20tools%20or%20the%20rest%20api%3F\"><h3>Can I manage links with AI tools or the REST API?<\/h3><\/dt>\n<dd><p>Yes. GT Link Manager includes a full REST API for creating, updating, and deleting links programmatically. This works with AI platforms like Claude Code, OpenAI Codex, and MCP adapters. See the <a href=\"https:\/\/gauravtiwari.org\/gt-link-manager-rest-api-guide-ai-tools\/\">REST API &amp; AI Tools Guide<\/a> for setup instructions.<\/p><\/dd>\n<dt id=\"can%20i%20integrate%20with%20google%20analytics%2C%20plausible%2C%20or%20other%20analytics%3F\"><h3>Can I integrate with Google Analytics, Plausible, or other analytics?<\/h3><\/dt>\n<dd><p>Yes. The <a href=\"https:\/\/gauravtiwari.org\/course\/gt-link-manager-training\/developer-reference-1771422601\/\">Developer Reference<\/a> has step-by-step guides for GA4, Plausible, Fathom, Matomo, and Simple Analytics. You can also set up webhook notifications for Zapier, Make, and n8n.<\/p><\/dd>\n<dt id=\"what%20happens%20when%20i%20uninstall%3F\"><h3>What happens when I uninstall?<\/h3><\/dt>\n<dd><p>Uninstalling the plugin (deleting it from <strong>Plugins<\/strong>) will <strong>remove all data<\/strong> \u2014 both database tables and plugin options. Deactivating the plugin preserves all data.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.7.0<\/h4>\n\n<ul>\n<li>New: Geolocation targeting. Any link can route visitors to a different destination based on their country, with rules evaluated in order and the first country match winning.<\/li>\n<li>New: Country detection with zero dependencies. The country is read from request variables your CDN or web server already provides \u2014 Cloudflare (<code>CF-IPCountry<\/code>), CloudFront, Vercel, Google App Engine, nginx GeoIP2, Apache mod_geoip, mod_maxminddb, or a custom header you name. No GeoIP database file, no third-party API, no outbound request.<\/li>\n<li>New: <code>EU<\/code> country group expands to all 27 member states in a single rule; extendable via <code>gtlm_geo_country_groups<\/code>.<\/li>\n<li>New: Per-rule status codes, and a \"show a 404\" fallback for visitors matching no rule.<\/li>\n<li>New: Geolocation settings section with a live \"Detected Now\" readout showing which country and source resolved for the current request \u2014 the fastest way to confirm your CDN is forwarding a country header.<\/li>\n<li>New: \"Check Detection\" button. Lists every country header present on the request with its raw value, and runs a loopback self-test \u2014 it sends the site a request carrying a country header and reports what the plugin detected at the other end. That proves detection works even on a local or staging install with no CDN in front, where \"no country on this request\" is correct rather than a fault. Also validates a country code you type before you use it in a rule.<\/li>\n<li>New: The detection readout distinguishes \"nothing is proxying this site, so no country is expected\" from \"your CDN is in front but sent no country header\" \u2014 only the second is a misconfiguration, and it now says how to fix it.<\/li>\n<li>New: Rule builder in the link editor. Numbered rows show match precedence, rules can be reordered, one-click picks cover common markets (US + CA, EU, UK, India, AU + NZ), the long country list is filterable, selections show as removable chips, and the \"Everyone else\" fallback reads as the final row. It warns when a country is listed twice (only the highest rule can ever match) or when a rule has countries but no URL.<\/li>\n<li>New: Rule preview. Pick a country and see exactly which rule wins and where it sends \u2014 evaluated in the browser against your unsaved edits, with no request made.<\/li>\n<li>New: Privacy disclosure. The plugin registers a suggested privacy-policy section under Settings \u2192 Privacy \u2192 Policy Guide, and states inline that country detection reads only a CDN-provided header \u2014 never the visitor's IP address, never an external service, and the country is never stored or logged.<\/li>\n<li>Fixed: a partial REST update (PATCH) of one field silently reset every field that was not included, because each write argument declared a schema default that WP_REST_Request materialises into the request. Sending only <code>geo_rules<\/code> would reset <code>redirect_type<\/code> to 301 \u2014 which quietly breaks geo targeting \u2014 and blank <code>tags<\/code>, <code>notes<\/code>, and <code>rel<\/code>. Omitted fields now keep their stored values. Create defaults are unchanged.<\/li>\n<li>New: Optional <code>X-GTLM-Country<\/code> debug response header showing the detected country, its source, and whether a rule matched.<\/li>\n<li>New: Geo rules are exposed in the REST API on <code>\/links<\/code> (create, read, update) with a self-describing schema, so links can be geo-targeted programmatically. Posting <code>geo_rules<\/code> without <code>geo_mode<\/code> opts the link in automatically.<\/li>\n<li>New: Geo rules round-trip through CSV import and export; a malformed rules cell is dropped without failing the row.<\/li>\n<li>New: Geo column in the links list table, and geolocation status in Diagnostics.<\/li>\n<li>Performance: geolocation costs nothing on links that do not use it \u2014 the check is a single array read, and country detection is never invoked unless a matched link opts in. Detection and settings are resolved once per request.<\/li>\n<li>Note: geo-targeted links should use 302, not 301. A 301 is cached by the browser permanently, which pins a visitor to whichever country they were in on their first click. The link editor warns when a geo link is set to 301.<\/li>\n<li>Note: a country header can be forged on requests that reach your site without passing through your CDN, so the 404 fallback is not a security control. Behind Cloudflare, <code>CF-IPCountry<\/code> is rewritten at the edge and cannot be spoofed; the \"Cloudflare only\" detection method is the strictest setting.<\/li>\n<\/ul>\n\n<h4>1.6.1<\/h4>\n\n<ul>\n<li>Fixed nonce mismatch bug \u2014 trash, restore, and permanent delete actions were failing due to inconsistent nonce prefixes.<\/li>\n<li>Fixed potential ReDoS vulnerability \u2014 removed error suppression on regex pattern matching, added pattern length validation.<\/li>\n<li>Standardized all nonce prefixes to <code>gtlm_<\/code> across admin actions and list table.<\/li>\n<li>Added REST API route descriptions to all endpoints for better discoverability.<\/li>\n<li>Added object caching for admin category dropdown with proper invalidation on create, update, and delete.<\/li>\n<li>Updated readme with free training course, developer reference, REST API guide, and new FAQ entries.<\/li>\n<\/ul>\n\n<h4>1.6.0<\/h4>\n\n<ul>\n<li>Added advanced redirects: Direct (prefix-free) and Regex (pattern-based) link modes.<\/li>\n<li>Direct links redirect without the prefix \u2014 e.g., <code>yoursite.com\/my-page<\/code> instead of <code>yoursite.com\/go\/my-page<\/code>.<\/li>\n<li>Regex links match request paths against patterns with capture group substitution in destination URLs.<\/li>\n<li>New \"Enable Advanced Redirects\" toggle in Settings (off by default) to opt in.<\/li>\n<li>Link edit form shows mode selector (Standard \/ Direct \/ Regex) with contextual fields.<\/li>\n<li>Conflict detection warns when direct link paths match existing WordPress posts or pages.<\/li>\n<li>Regex patterns are validated on save; invalid patterns are rejected.<\/li>\n<li>List table shows link mode with filter support.<\/li>\n<li>REST API accepts and returns <code>link_mode<\/code>, <code>regex_replacement<\/code>, and <code>priority<\/code> fields.<\/li>\n<li>New database columns: <code>link_mode<\/code>, <code>regex_replacement<\/code>, <code>priority<\/code> \u2014 fully backwards compatible.<\/li>\n<\/ul>\n\n<h4>1.5.3<\/h4>\n\n<ul>\n<li>Fixed plugin zip size bloat \u2014 excluded .wordpress-org assets directory from distribution package.<\/li>\n<\/ul>\n\n<h4>1.5.2<\/h4>\n\n<ul>\n<li>Added \"Delete Data on Uninstall\" setting \u2014 data is now preserved by default when the plugin is deleted.<\/li>\n<li>Uninstall only removes tables and options if the user explicitly opts in via Settings.<\/li>\n<\/ul>\n\n<h4>1.5.1<\/h4>\n\n<ul>\n<li>Fixed CSS custom properties not resolving on some admin pages \u2014 all values are now hardcoded.<\/li>\n<li>Fixed form-table double-card styling when rendered inside a card container.<\/li>\n<li>Improved edit form submit buttons layout \u2014 buttons now display in a single horizontal row.<\/li>\n<li>Improved branded URL preview styling with distinct blue tint.<\/li>\n<li>Added subtle row separators inside card form tables.<\/li>\n<li>Added WordPress.org SVN deploy to release workflow.<\/li>\n<li>Added plugin banner and icon assets for WordPress.org listing.<\/li>\n<\/ul>\n\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>Renamed internal code prefix from <code>gt_<\/code> to <code>gtlm_<\/code> (4+ characters) per WordPress.org guidelines.<\/li>\n<li>Fixed nonce verification order in CSV import handler \u2014 nonce is now checked before reading POST data.<\/li>\n<li>Fixed SQL injection vector \u2014 <code>$orderby<\/code> now uses <code>%i<\/code> identifier placeholder in prepared queries.<\/li>\n<li>Added Source Code section to readme for compiled block editor assets.<\/li>\n<li>Added card-based UI styling to all admin pages (edit link, categories, settings, import\/export).<\/li>\n<li>Settings page reorganized into General, Tools, and Diagnostics cards.<\/li>\n<li>Clean uninstall now removes both old (<code>gt_<\/code>) and new (<code>gtlm_<\/code>) prefix options and tables.<\/li>\n<\/ul>\n\n<h4>1.3.1<\/h4>\n\n<ul>\n<li>Block editor: aligned GT Link popover anchoring with core rich text behavior using selection-based anchor.<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>Refactored admin into separate actions and rendering classes for maintainability.<\/li>\n<li>Added Pretty Links CSV import preset alongside Generic and LinkCentral.<\/li>\n<li>Improved input sanitization on redirect URI parsing.<\/li>\n<li>Added PHPCS configuration and Composer dev tooling.<\/li>\n<li>Added uninstall.php for clean plugin removal (drops tables and options).<\/li>\n<li>Improved build.sh with .distignore support and critical file verification.<\/li>\n<li>Improved release workflow with version verification, checksums, and distribution validation.<\/li>\n<li>Block editor popover anchor now uses bounding rect snapshot for reliable positioning.<\/li>\n<li>Button primary color now follows WordPress admin theme color.<\/li>\n<li>Lowered PHP requirement from 8.2 to 8.0.<\/li>\n<li>Tested up to WordPress 6.9.<\/li>\n<\/ul>\n\n<h4>1.2.3<\/h4>\n\n<ul>\n<li>Fixed release packaging bug that accidentally removed <code>blocks\/link-inserter\/build\/*<\/code> from zip assets.<\/li>\n<li>GitHub release workflow now compiles block editor assets before zipping and verifies build files exist.<\/li>\n<\/ul>\n\n<h4>1.2.2<\/h4>\n\n<ul>\n<li>Fixed block editor link inserter not appearing on WordPress 6.8+.<\/li>\n<li>Removed deprecated useAnchor hook that crashed the toolbar button on render.<\/li>\n<li>Eliminated react-jsx-runtime dependency that prevented the script from loading on some WordPress versions.<\/li>\n<li>Popover now anchors to the toolbar button for reliable positioning.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>Fixed critical bug: links disappeared after 1.1.9 update because new DB columns were not added on plugin update (only on fresh activation).<\/li>\n<li>Added automatic DB migration that runs on update to add missing columns and backfill existing rows.<\/li>\n<li>Fixed WordPress admin sidebar menu getting unintended card styles on the Settings page.<\/li>\n<li>Improved Settings page: Flush Permalinks and Run Diagnostics buttons are now inline, diagnostics output uses a clean table layout with status badges.<\/li>\n<\/ul>\n\n<h4>1.1.9<\/h4>\n\n<ul>\n<li>Added link activate\/deactivate toggle. Inactive links stop redirecting but remain in the database.<\/li>\n<li>Delete now moves links to trash instead of permanent deletion. Links can be restored from trash.<\/li>\n<li>Trash view with restore and permanent delete actions.<\/li>\n<li>New bulk actions: Activate, Deactivate, Move to Trash, Restore, Delete Permanently.<\/li>\n<li>REST API: DELETE defaults to trash (use <code>?force=true<\/code> for permanent). New <code>\/restore<\/code> and <code>\/toggle-active<\/code> endpoints.<\/li>\n<li>Status column and views (All \/ Active \/ Inactive \/ Trash) in the links list table.<\/li>\n<li>New <code>is_active<\/code> and <code>trashed_at<\/code> columns added to the links table on upgrade.<\/li>\n<\/ul>\n\n<h4>1.1.8<\/h4>\n\n<ul>\n<li>Maintenance release.<\/li>\n<\/ul>\n\n<h4>1.1.7<\/h4>\n\n<ul>\n<li>Block editor: Fixed editor scroll jump when opening GT Link popover from the toolbar.<\/li>\n<li>Block editor: Improved search input focus behavior so opening popover does not move viewport.<\/li>\n<\/ul>\n\n<h4>1.1.6<\/h4>\n\n<ul>\n<li>REST API: Added full pagination (page, per_page, category_id, orderby, order) to GET \/links endpoint.<\/li>\n<li>REST API: Added args schema validation to all write endpoints (links, categories, bulk-category).<\/li>\n<li>Security: Replaced innerHTML with DOM methods in admin quick edit to prevent XSS.<\/li>\n<li>DB: Added rel whitelist validation on filter queries.<\/li>\n<li>Build: build.sh now compiles block editor assets before packaging.<\/li>\n<\/ul>\n\n<h4>1.1.5<\/h4>\n\n<ul>\n<li>Maintenance release.<\/li>\n<\/ul>\n\n<h4>1.1.4<\/h4>\n\n<ul>\n<li>Anchor popover to selected text using useAnchor from @wordpress\/rich-text.<\/li>\n<\/ul>\n\n<h4>1.1.3<\/h4>\n\n<ul>\n<li>Fixed format registration conflict with core\/underline on WP 6.9+ (both used bare span tag).<\/li>\n<li>Added unique className to avoid tagName collision.<\/li>\n<\/ul>\n\n<h4>1.1.2<\/h4>\n\n<ul>\n<li>Switch to RichTextToolbarButton for standard format toolbar integration.<\/li>\n<\/ul>\n\n<h4>1.1.1<\/h4>\n\n<ul>\n<li>Force-inject format into RichText allowedFormats for reliable toolbar display.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Rebuilt block editor link inserter with @wordpress\/scripts build pipeline.<\/li>\n<li>Fixed toolbar button not appearing in block editor.<\/li>\n<li>Proper dependency resolution via index.asset.php.<\/li>\n<\/ul>\n\n<h4>1.0.4<\/h4>\n\n<ul>\n<li>Fixed toolbar button registration in block editor for GT Link inserter.<\/li>\n<li>Added selected-text autofill in GT Link inserter search field.<\/li>\n<li>Improved redirect detection for WordPress installs in subdirectories.<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li>Enhance block editor integration with additional dependencies and improved format registration<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Minor internal hardening and cleanup.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Fixed uninstall to preserve links and settings data across reinstalls.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"Fast, free branded link manager with custom database tables, early redirects, CSV import\/export, and block editor integration.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/ps.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/288783","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ps.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/ps.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/ps.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=288783"}],"author":[{"embeddable":true,"href":"https:\/\/ps.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/gauravtiwari"}],"wp:attachment":[{"href":"https:\/\/ps.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=288783"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/ps.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=288783"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/ps.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=288783"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/ps.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=288783"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/ps.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=288783"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/ps.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=288783"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}