This 2011 post originally described old plugins, manual ZIP uploads, affiliate links, and visitor-profile click tracking. Those practices should not be copied. The safer rule today is: link directly when possible; if an on-site short path is justified, map one fixed path to one fixed HTTPS destination and tell readers where it goes and whether there is a commercial relationship.
This guide was maintained on September 1, 2026. It does not promise traffic, customers, or revenue. A narrowly redacted copy of the historical source is preserved at the end for provenance; its services, downloads, and instructions are not recommendations.
Table of Contents
First ask whether a redirect is needed
A direct external link is usually simpler and more transparent, with fewer plugin, cache, logging, and failure points. Use link text that names the destination, such as “View Example's product documentation,” rather than “click here.” Do not force a new window without a clear reason; if one is necessary, warn readers and use rel="noopener".
An on-site redirect is suitable only for a limited, explainable purpose: maintaining a durable resource address that may move, repairing a historical short link, or using a fixed commercial link whose relationship is clearly disclosed. It must not disguise the destination, evade platform rules, hide risk, or accept an arbitrary visitor-supplied target.
Three implementation options
| Option | Suitable when | Advantage | Main responsibility |
|---|---|---|---|
| Direct external link | The default | Transparent, no redirect chain, least maintenance | Recheck the destination and disclosure |
| Maintained official-directory plugin | Many routes need a UI, import, or export | Easier for non-developers to manage | Updates, least privilege, and disabled/minimal logs |
| Fixed web-server rule | A few stable mappings and managed server access | Independent of WordPress, shorter request path | Configuration review, testing, release, rollback |
| Small WordPress implementation | A few mappings maintained with site code | Auditable behavior and WordPress safe redirects | Code, collision, and cache maintenance |
If a plugin is appropriate, install a currently maintained release compatible with your WordPress and PHP versions through the official WordPress plugin directory connected to WordPress Admin. Redirection is one directory example with current releases as of this maintenance date, not a security guarantee or commercial endorsement. Do not use the old article's third-party ZIP, dead download host, or an unknown mirror.
Status codes are not an “SEO switch”
| Status | Meaning | Method behavior | Guidance here |
|---|---|---|---|
302 | Temporary | Historically may change the next request to GET | Default for a fixed, GET-only mapping that may change |
307 | Temporary | Preserves method and body | Only if method preservation is required; this endpoint rejects non-GET |
301 | Permanent | A client may turn POST into GET | Only for a genuinely durable, fully tested destination |
308 | Permanent | Preserves method and body | Likewise only for a genuinely permanent rule |
These semantics come from HTTP Semantics (RFC 9110). Browsers, search engines, and CDNs can cache permanent redirects, and cache policy can affect temporary ones too. Start a new rule with 302; decide on permanence only after testing. Purge application and CDN caches when changing it.
Option A: a plugin, kept fixed and minimal
Install and update the plugin in staging. Give each short path one exact source path and one fixed HTTPS destination. Do not enable regexes, wildcards, or any feature that reads a destination from a query parameter. Never create ?url=https://…, ?next=…, or routes that support javascript:, data:, or another non-HTTP(S) scheme. An unknown short path should remain a 404, not redirect to visitor input.
Export/back up the existing rules first. Check that the /go/ namespace does not collide with a page, post, category, media item, locale prefix, or another plugin. Restrict administration to people who need it. Disable click logs by default; if the plugin cannot meet minimization and deletion requirements, do not use its statistics. Retain a restorable configuration export and rollback procedure after release.
Option B: one fixed web-server rule
This Caddy example matches only GET /go/example-docs with no query string. The destination is a constant. path is exact by default: do not add *, and do not interpolate {uri}, a query string, or visitor input into the target.
@outbound_example {
method GET
path /go/example-docs
query ""
}
redir @outbound_example https://docs.example.org/product 302
Run `caddy validate` against the staging configuration before loading it through the existing managed-service release process. Caddy's `redir` and request matcher documentation defines these fields. If the site uses another server, express the same “exact path → fixed target” model with that server's official documentation; do not copy an inapplicable configuration.
Option C: a minimal, fixed WordPress implementation
The following can be a small site-owned plugin after code review and staging. It has no admin UI, accepts only GET, rejects every query string on the short path, gets the destination only from a code map, and requires HTTPS plus an exact host match. It temporarily permits that exact external host, calls `wp_safe_redirect()`, removes the filter, and exits.
<?php
/**
* Plugin Name: Fixed Outbound Redirects
*/
function lazying_fixed_outbound_routes() {
return array(
'go/example-docs' => array(
'url' => 'https://docs.example.org/product',
'host' => 'docs.example.org',
),
);
}
add_action(
'template_redirect',
static function () {
$method = isset( $_SERVER['REQUEST_METHOD'] )
? strtoupper( wp_unslash( $_SERVER['REQUEST_METHOD'] ) )
: '';
if ( 'GET' !== $method ) {
return;
}
$request_uri = isset( $_SERVER['REQUEST_URI'] )
? wp_unslash( $_SERVER['REQUEST_URI'] )
: '';
$path = wp_parse_url( $request_uri, PHP_URL_PATH );
if ( ! is_string( $path ) ) {
return;
}
$slug = trim( $path, '/' );
$routes = lazying_fixed_outbound_routes();
if ( ! isset( $routes[ $slug ] ) ) {
return;
}
$query = wp_parse_url( $request_uri, PHP_URL_QUERY );
if ( is_string( $query ) && '' !== $query ) {
nocache_headers();
status_header( 404 );
exit;
}
$route = $routes[ $slug ];
$destination = $route['url'];
$expected_host = strtolower( $route['host'] );
$scheme = strtolower( (string) wp_parse_url( $destination, PHP_URL_SCHEME ) );
$host = strtolower( (string) wp_parse_url( $destination, PHP_URL_HOST ) );
$user = wp_parse_url( $destination, PHP_URL_USER );
$pass = wp_parse_url( $destination, PHP_URL_PASS );
if (
'https' !== $scheme
|| $host !== $expected_host
|| null !== $user
|| null !== $pass
) {
status_header( 500 );
exit;
}
$allow_exact_host = static function ( $hosts ) use ( $host ) {
$hosts[] = $host;
return array_values( array_unique( $hosts ) );
};
add_filter( 'allowed_redirect_hosts', $allow_exact_host );
nocache_headers();
$sent = wp_safe_redirect( $destination, 302, 'Fixed Outbound Redirects' );
remove_filter( 'allowed_redirect_hosts', $allow_exact_host );
if ( $sent ) {
exit;
}
status_header( 500 );
exit;
},
0
);
`wp_safe_redirect()` uses `wp_validate_redirect()` to check allowed hosts, but it does not terminate execution, so a successful redirect still needs exit. This code never expands the host list from visitor input and has no wildcard hosts. Route-map changes go through code review. If an admin editor is added later, use the Settings API, check an appropriate capability such as manage_options, and verify a nonce. A nonce is not authorization, and the public read-only redirect itself does not need one.
Show the real destination and disclose commercial relationships nearby
A short path is not an invisibility cloak. Link text and nearby copy should tell an ordinary reader where they will go. Disclose a paid, sponsored, or affiliate relationship clearly and close to the link; do not hide it only in a footer or terms page. For US readers, consult the FTC's Endorsement Guides Q&A. Check the rules that apply elsewhere.
Google currently prefers rel="sponsored" for paid links; nofollow remains acceptable, and the values can be combined. Neither attribute replaces a human-readable disclosure.
<p><strong>Disclosure:</strong> I may receive a commission if you buy through this link.</p>
<p><a href="/go/example-docs" rel="sponsored nofollow">View Example's product documentation (paid link; opens Example)</a></p>
Localize the visible text and keep it factual. Do not invent clicks, customers, conversions, or revenue. A redirect count is not a count of people, customers, or sales. Google's outbound-link qualification guide documents the current sponsored/nofollow use.
Click logs: collect nothing by default
The minimal implementation does not log clicks. Server access logs may still contain the path, IP address, User-Agent, referrer, or query string, so inspect the actual infrastructure rather than assuming that “plugin tracking off” means no logging. Without a clear necessary purpose, suppress detailed logging for the route or aggregate irreversibly as early as possible. Do not retain full IP addresses, User-Agents, referring URLs, or visitor identifiers by default.
If measurement is necessary, keep only the fields needed for the purpose—for example a short-lived “date + route + aggregate count.” Bots and duplicate requests distort it. State the purpose, lawful basis, retention, recipients, and access/deletion route; assess consent or objection mechanisms under applicable law. For cookies, device storage, or link decoration, consult the ICO's storage and access technologies guidance. A WordPress plugin processing personal data should also implement the platform's privacy notices, exporter, and eraser.
Staging tests and acceptance
Back up the database, plugin configuration, and server configuration first. Change one route only. After replacing the example host with the staging domain, run:
curl --silent --show-error --dump-header - --output /dev/null
https://staging.example.org/go/example-docs
curl --silent --show-error --dump-header - --output /dev/null
--request POST https://staging.example.org/go/example-docs
curl --silent --show-error --dump-header - --output /dev/null
'https://staging.example.org/go/example-docs?url=https://evil.example'
curl --silent --show-error --location --max-redirs 5 --output /dev/null
--write-out '%{http_code} %{url_effective}n'
https://staging.example.org/go/example-docs
Acceptance means: one redirect from the exact query-free GET to the expected HTTPS target; no redirect for POST or a url query; unknown slugs return 404; the final page is expected; there is no loop; and no visitor query is forwarded. Test logged-in/logged-out, mobile, caches on/off, and CDN edges separately. If the code is not installed in staging, these commands test only the site's current behavior, not the sample implementation.
For a multilingual site, decide whether /go/example-docs is shared. If /en/, /ja/, or other prefixes exist, list every exact mapping instead of using a wildcard that swallows locale paths. After a permalink or destination change, inspect WordPress rewrite rules, plugin priority, page slugs, reverse proxies, and CDNs for collisions or redirect chains.
Rollback and stop gates
Before release, retain a rule export, the code version, and the previous configuration. Roll out a 302 narrowly. If you see a wrong destination, a loop, an uncleared cache, capture of unknown paths, forwarded request parameters, logging beyond the disclosure, a transferred destination domain, or a security warning, disable the rule immediately, purge caches, and restore the direct link. Do not delay rollback to preserve statistics.
Minimum preflight checklist:
- Is a direct link already sufficient?
- Is the source an exact reserved slug and the destination a fixed HTTPS URL with an exact host?
- Are non-
GETmethods, any query-supplied target, non-HTTP(S) schemes, and unknown slugs rejected? - Were slug/locale collisions, cache/CDN behavior, loops, and destination ownership checked?
- Is the commercial relationship clear beside the link, and is the link text understandable?
- Are IP/User-Agent logs off by default, with minimized analytics and a deletion deadline?
- Is there a backup, configuration export, reviewer, test evidence, and one-step rollback path?
References
- WordPress Developer Resources: `wp_safe_redirect()`, `wp_validate_redirect()`, `template_redirect`
- WordPress Plugin Handbook: Security, Settings API, Roles and Capabilities, Nonces, Privacy
- OWASP Unvalidated Redirects and Forwards Cheat Sheet
- HTTP Semantics (RFC 9110)
- Google Search Central: Qualify your outbound links
- FTC's Endorsement Guides: What People Are Asking
- ICO: Guidance on the use of storage and access technologies
- Caddy: redir, Request matchers
Historical source archive (provenance only; do not follow)
Below is the complete visible body of the 2011 source export, unchanged except for narrow redactions. To avoid republishing old tracking or private/account-like identifiers, the Taskcity referral value (2 occurrences), old first-party tracking path (3 occurrences), and Filemarkets account-like download path (1 occurrence) are replaced with bracketed placeholders. The original strings remain only in source_export and Git provenance. The old plugin download, endorsement, visitor profiling, and commercial claims are preserved as rejected historical material; the links may be dead, transferred, or unsafe, so do not visit or follow them.
WordPress 怎样实现“站外链接”的跳转?
——WordPress短链接插件Pretty Link
**比如说我在一篇文章里添加了一个超链接,我想让这个超链接显示成本站的链接,(鼠标放上去变成小手,浏览器左下角显示的是本站的一个链接)但是点击后跳转成外链,这样如何实现?**
在[http://earnfs.sinaapp.com](http://earnfs.sinaapp.com/[historical redirect path redacted])站点中:
[http://www.taskcity.com/?dn=[historical referral value redacted]](http://www.taskcity.com/?dn=[historical referral value redacted])=>[http://earnfs.sinaapp.com/[historical redirect path redacted]](http://earnfs.sinaapp.com/[historical redirect path redacted])
**可以使用缩短连接插件**
**Pretty Link (推荐)**
**或**
**WordPress ShortUrl Plugin**
Petty Link可以生成基于你的域名的短网址,类似tinyurl.com, bit.ly等短网址服务的链接,并且这个链接基于你自己的域名,你可以对这些生成的网址链接进行点击跟踪,监测点户的来源地、浏览器、操作系统等,非常适合用来做推荐联盟链接等。
这款插件可以自定义URL,不过,前提是不能和已经存在的或者已经在使用的%postname%相同,使用Petty Link插件后,它会让你的网站变得更加的简洁、
**Petty Link插件安装使用:**
1. [下载Petty Link插件](http://filemarkets.com/file/[historical account/download path redacted]),解压后,把文件夹上传到wp-content/plugins/目录下,登录WordPress管理后台,点击“Plugins”找到上传的插件,激活该插件。
2. 激活该插件后,在后台页面的右侧最下方,会出现Pretty Link的图标,然后,在里面进行相关的设置。
**Pretty Link有以下选项:**
**Pretty Link:**页面中主要是当前添加的链接、点击量、组等相关信息
**Add New Link:**添加链接

**Groups:**创建组,让这些组使用这些pretty links
**Hits:**图示最近一段时间的点击量、流量IP、转向的链接,方便你的统计使用。
**Tools:**获取Pretty Link链接到工具栏安装书签,当你浏览网页,只要单击书签就可以创建Pretty Link
**Options:**设置相关信息
- **Link Option Defaults**:设置是否添加跟踪链接、nofollow及相关属性
- **PrettyBar Options**:设置Pretty Bar的是否显示标题、说明、分享链接及URL。
- **Reporting Options**:报告选项,不包含那些IP地址,在统计的时候对其进行排除。
**Pretty Link Pro**:设置PRO账户信息
这款插件的功能还是比较强的,这里这是简单的做了点介绍,更多更深的东西,还是需要大伙自己体会。
