Description
Linkjet manages redirects and affiliate links with an emphasis on safety and automation: regular-expression redirects are validated when you save and can be tested against a sample path before going live, a conflict guard warns before a redirect shadows a real page or touches critical paths such as checkout and login, a 404 monitor separates real broken links from bot and scanner noise, and the complete feature set is scriptable through a documented REST API with an OpenAPI manifest, for automation and AI-assisted workflows.
Features
- Pretty short links / branded links on your own domain (e.g.
your-site.com/go/product) - Affiliate link management: cloaking,
rel="nofollow"/rel="sponsored", query-parameter forwarding - Redirect types 301, 302, 307, 308 and 410 (Gone)
- Regular-expression redirects with
$1–$9back-references, validated when you save and testable against a sample URL before going live - Conflict guard: warns you before a redirect shadows a real page, overlaps another rule or hits critical paths such as checkout, login or the REST API – and blocks redirect loops outright
- Click statistics with time-series charts, plus device, browser and country breakdowns
- Click log without IP addresses or user agents (since 1.5.4), bot filtering, optional referrer tracking
- Automatic click-log cleanup after a configurable number of days (WP-Cron)
- Categories to organise your links and bulk actions to manage many at once
- QR code per link, generated locally in the browser (optional drop-in library, no external calls)
- Gutenberg block and
[linkjet]shortcode for clean affiliate anchors in your content - 404 monitor that separates real broken links from bot traffic and vulnerability-scanner probes, with automatic log rotation so the table cannot grow forever
- CSV and full JSON backup (import/export) for migration and backups
- One-click import wizard for existing Pretty Links (v3 and the v4 custom-table data model) and Redirection setups, including click statistics
- Fully internationalised interface, ready for community translations on translate.wordpress.org, plus a language override in the settings
- Complete REST API under
/wp-json/linkjet/v1/, authenticated via Application Passwords
REST API endpoints
GET/POST /wp-json/linkjet/v1/linksGET/PUT/DELETE /wp-json/linkjet/v1/links/<id>GET /wp-json/linkjet/v1/links/<id>/clicksGET/POST /wp-json/linkjet/v1/categoriesDELETE /wp-json/linkjet/v1/categories/<id>GET /wp-json/linkjet/v1/statsGET/PUT /wp-json/linkjet/v1/settingsPOST /wp-json/linkjet/v1/links/test-pattern(validate a regular expression and test it against a sample path)GET /wp-json/linkjet/v1/404s(add?noise=0for real 404s,?noise=1for scanner/bot noise) andPOST /wp-json/linkjet/v1/404s/<id>/redirectGET /wp-json/linkjet/v1/exportPOST /wp-json/linkjet/v1/import(?mode=replaceto overwrite)GET /wp-json/linkjet/v1/openapi(machine-readable API manifest)
Endpoints require the manage_linkjet capability, which is granted to administrators automatically and can optionally be granted to editors. A machine-readable OpenAPI manifest is available at /wp-json/linkjet/v1/openapi, ready to import into Postman, Insomnia or any API client.
Screenshots
Blocks
This plugin provides 1 block.
- Link
Installation
- Upload the
linkjetfolder to/wp-content/plugins/, or install it through the Plugins screen. - Activate the plugin.
- Open the Linkjet menu. On first activation the import wizard opens automatically and offers to import existing Pretty Links / Redirection data.
- Create your first link, or import via CSV/JSON.
FAQ
-
Is any of this limited, or nagging me to upgrade?
-
No. Everything described above is part of this plugin, without usage limits, feature locks or upgrade banners in your admin area. There is a separate paid add-on (Linkjet Pro) for agency-style extras such as geo/device targeting, split tests, a broken-link checker and scheduled client reports, but this plugin never asks you to buy it and works completely on its own.
-
Can I import my Pretty Links setup after the 4.0 rewrite?
-
Yes. The import wizard reads both the classic Pretty Links tables and the new v4 custom-table data model, and it reads the columns that are actually present – so half-migrated installations are imported as far as the data allows instead of failing. Entries without a target URL are reported separately rather than silently skipped.
-
Does it send any data to external servers?
-
No. Click tracking is first-party and stays in your own database. No external analytics, no CDN calls.
-
How do I control Linkjet from outside WordPress (or from an AI/automation)?
-
Use the REST API under
/wp-json/linkjet/v1/with an Application Password (Users Profile Application Passwords). The OpenAPI manifest at/wp-json/linkjet/v1/openapidescribes every endpoint and can be imported into any API client. -
Can I import my existing Pretty Links or Redirection links?
-
Yes. The import wizard (Linkjet Import wizard) detects both plugins’ database tables and imports your links with one click, optionally including click statistics.
-
Is it GDPR-compliant?
-
Since version 1.5.4, new clicks are stored without IP address and user agent. Clicks recorded with an earlier version keep their IP address (shortened if IP anonymisation was switched on) and user agent until the click log retention deletes them; with the default retention of 0 days they are kept. Bots are not counted, country is only read from headers your server/CDN already provides (no external GeoIP database), and click logs can be auto-deleted after a chosen retention period.
-
How do I enable the QR code feature?
-
Drop an MIT-licensed
qrcode.min.js(e.g. davidshimjs/qrcodejs) intoadmin/assets/. The plugin makes no external calls; the QR button appears only when the library is present. -
Where do I get support?
-
Please use the plugin’s support forum on WordPress.org. Linkjet is developed by hafenstudios (https://hafenstudios.com); you can also reach us at info@hafenstudios.com.
Reviews
Contributors & Developers
“Linkjet” is open source software. The following people have contributed to this plugin.
ContributorsTranslate “Linkjet” into your language.
Interested in development?
Browse the code, check out the SVN repository, or subscribe to the development log by RSS.
Changelog
1.5.4
- Security: a regular-expression redirect whose target starts with a placeholder (for example
/$1) can no longer send visitors to a foreign site. Linkjet checks the target after the placeholders are filled in, the way a browser reads it (backslashes, encoded slashes and a scheme without//included), and only allows the host the rule itself names; before, the request/go//evil.comproduced the target//evil.com. Targets such ashttp:$1orhttps:/$1, where a placeholder would decide the host, are refused when the rule is saved. - Security: with parameter forwarding switched on, incoming query parameters no longer overwrite parameters that are already part of the target URL, so a visitor cannot replace your affiliate ID by appending
?tag=…. - Security: settings and the “replace everything” backup import now require an administrator. Editors with Linkjet access still manage links and can import backups in merge mode, but such an import no longer changes settings.
- Security: the language setting is checked against the list of available languages before a translation file is loaded, and settings from a backup import are cleaned key by key.
- Security: the CSV export prefixes cells that start with
=,+,-or@, so spreadsheet programs do not run them as formulas. Linkjet’s own CSV import removes the prefix again. - Privacy: the click log no longer stores IP addresses or user agents. Click counts, time, device, browser, country and referrer statistics work as before. Rows recorded before this update are not changed. The IP anonymisation setting was removed because there is nothing left to anonymise.
- Fix: target URLs with percent-encoding (for example
%20or%C3%A4) were damaged when a link was saved in the admin form. They are stored unchanged again, as they already were through the REST API. - Fix: request paths and query strings are decoded before they are cleaned. Redirects for addresses with umlauts such as
/%C3%9Cber-unsmatch again, regular-expression redirects also match paths with spaces, and forwarded parameters keep their values (kaffee%20maschineno longer turns intokaffeemaschine). - Fix: slugs may contain dots and letters with accents or umlauts, so 404 entries such as
llms.txt,old-page.htmlorÜber-unsbecome working redirects. If a 404 path still cannot be matched, or belongs to WordPress itself, turning it into a redirect is refused with a message and the entry stays open, instead of creating a rule that never fires. - Fix: WordPress loopback and cron requests, requests that identify themselves with your own site address, and common HTTP libraries (python-requests, Go-http-client, okhttp) are no longer counted as clicks.
- Fix: on installations in a subdirectory such as
/shop, a path like/shopping-guideis no longer shortened toping-guide. - Fix: the admin form no longer damages the short URL. A pasted percent-encoded path such as
%C3%9Cber-unsis stored asÜber-uns, and regex patterns keep named groups such as(?<id>…). - Fix: exact slugs can no longer cover addresses that WordPress serves itself, such as
wp-sitemap.xml,wp-comments-post.php,wp-signup.phporxmlrpc.php. Saving such a slug is refused with a message.
1.5.3
- Change: translations are no longer shipped inside the plugin. They come from translate.wordpress.org, where anyone can contribute and WordPress installs them automatically.
- Change: every table name now goes through the %i identifier placeholder of wpdb::prepare(), so no query builds its own SQL from an interpolated name. Because %i needs WordPress 6.2, that is the new minimum version.
- Change: the bundled translation loader now handles all translation loading on its own; the redundant load_plugin_textdomain() call was removed. Behaviour is unchanged, including the language override setting.
- Fix: four strings with placeholders now carry a translators comment, so translators can see what the placeholder stands for.
- Change: input is sanitised at the point of entry as well, not only in the data layer. No behavioural change; the data layer already cleaned every value.
- Change: database queries, view templates and view filters now carry the reasoning for the coding-standard exceptions they need, so reviewers and contributors can see why they are there.
1.5.1
- Change: English is now the source language of all interface strings. German, French, Spanish, Italian and Dutch were bundled with that release; as of 1.5.3 translations come from translate.wordpress.org instead. The language setting keeps working as before.
- Change: tested up to WordPress 7.1.
1.5.0
- New: regular-expression redirects. Patterns are validated when you save (an invalid pattern is refused instead of silently never matching) and can be tested against a sample path right in the editor. Back-references
$1–$9are available in the target URL. - New: conflict guard. Before saving, Linkjet warns you if a redirect would shadow an existing page, overlap another rule, or affect critical paths such as checkout, login or the REST API. Redirect loops are refused outright.
- New: the 404 monitor separates real broken links from bot traffic and vulnerability-scanner probes (
wp-config,phpmyadmin,cgi-binand friends). The badge counts real 404s only, noise has its own tab, and a configurable row limit rotates the log automatically so it cannot grow forever. - New: the import wizard understands the Pretty Links 4.0 data model, including installations left half-migrated by that upgrade. Columns are detected instead of assumed, and entries without a target URL are reported rather than dropped silently.
- New: REST endpoint
POST /links/test-patternand anoisefilter onGET /404s; both are documented in the OpenAPI manifest. - Fix: the language setting works again. Since WordPress 6.5 loads bundled translation files by itself, the plugin’s own language override was silently ignored – picking e.g. French on an English site kept showing English. An explicitly chosen language now takes precedence.
- Fix: the conflict guard’s warnings and several other new texts were only available in German; all six languages are complete again.
- Fix: two placeholder texts in the admin UI were hard-coded in German and stayed German in every language.
1.4.2
- Fix: bulk-deleting links now fires
linkjet_link_deletedfor each link so add-ons can clean up their data (previously only single deletes did). - New:
linkjet_links_purgedaction fires when a backup import replaces all links – add-ons must clear link-related data there because link IDs are reused after the reset.
1.4.1
- Fix: the per-link
nofollowsetting is now also applied to the redirect itself via anX-Robots-Tag: nofollowresponse header – previously it only affected shortcode/block HTML, so search engines still followed cloaked affiliate redirects. Links with nofollow disabled stay dofollow (no header). New filterlinkjet_redirect_robotsto customise the directives (e.g. addnoindex).
1.4.0
- New: developer hooks and filters so add-ons can extend Linkjet cleanly (
linkjet_before_redirect,linkjet_redirect_target,linkjet_click_logged,linkjet_link_created/_updated/_deleted,linkjet_admin_menu,linkjet_admin_tabs,linkjet_link_edit_fields,linkjet_after_save_link,linkjet_settings_fields,linkjet_after_save_settings,linkjet_link_row_actions,linkjet_rest_prepare_link). See HOOKS.md.
1.3.1
- New: case-insensitive redirect fallback – redirects now also catch differently-cased URLs (e.g. /Programm and /PROGRAMM), but only when the URL would otherwise return a 404, so real pages are never hijacked.
- Change: removed promotional wording from the plugin name/description and assets.
1.3.0
- New: dedicated
manage_linkjetcapability – administrators always keep access; editors can optionally be granted access without full admin rights.
1.2.1
- Fix: slugs now preserve upper/lower case (e.g. /Programm); exact redirect matching is case-sensitive so an existing lower-case page is not hijacked.
1.2.0
- New: 404 monitor – logs dead URLs and turns them into redirects, with REST support for AI-assisted maintenance.
- New: REST endpoints for settings (
/settings) and a machine-readable API manifest (/openapi). - Fix: reliable UI translation loading, independent of the WordPress translation-file parser.
1.1.0
- New: performance cache for the redirect engine (slug index, avoids DB queries on non-matches).
- New: GDPR auto-cleanup – click logs are deleted automatically after X days via WP-Cron.
- New: device, browser and country statistics (country only from server/CDN headers, no external GeoIP DB).
- New: bulk actions in the link list (activate, deactivate, delete, assign category).
- New: slug collision warning when saving.
- New: QR code per link, generated locally (optional drop-in library, no external calls).
- New: Gutenberg block “Linkjet link”.
- New: import wizard for Pretty Links and Redirection (incl. click statistics).
- New: full JSON backup (admin + REST
/export&/import). - New: multilingual UI (English, German, French, Spanish, Italian, Dutch) + language override.
- Security: protection against PHP object injection in the Redirection importer.
1.0.0
- Initial release.
