# Link rewriting for affiliate codes

**URL:** https://meta.discourse.org/t/link-rewriting-for-affiliate-codes/52949
**Category:** Feature
**Created:** [2016年十一月16日 02:51 UTC](https://meta.discourse.org/t/link-rewriting-for-affiliate-codes/52949 "2016-11-16T02:51:40Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![daath](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/daath/32/115536_2.png) [@daath](https://meta.discourse.org/u/daath)
#### Post date: [2016年十一月16日 02:51 UTC](https://meta.discourse.org/t/link-rewriting-for-affiliate-codes/52949/1 "2016-11-16T02:51:40Z")

</div>

I saw this and was thrilled:

> [@Amazon link rewriting for affiliate codes](https://meta.discourse.org/t/amazon-link-rewriting-for-affiliate-codes/12174/52):
>
> I’m happy to announce that we’re developping an official affiliate plugin for discourse It only works for amazon right now but more will come later wink

Then I installed it, and realized that it still only works for Amazon. Would it be hard to add support for ShareASale? Maybe even a “generic” rewrite where you regex an URL and do a replacement?

---

<div class="post-metadata">

### Author: ![dis](https://avatars.discourse-cdn.com/v4/letter/d/e99b99/32.png) [@dis](https://meta.discourse.org/u/dis)
#### Post date: [2020年十一月24日 00:40 UTC](https://meta.discourse.org/t/link-rewriting-for-affiliate-codes/52949/2 "2020-11-24T00:40:19Z")

</div>

我知道这来自2016年，但我找不到相关答案，正在寻找类似方案。是否有插件允许对社区成员提交的 URL 进行“通用”重写，例如添加联盟标签，或将用户提交的链接替换为联盟链接？

---

<div class="post-metadata">

### Author: ![daath](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/daath/32/115536_2.png) [@daath](https://meta.discourse.org/u/daath)
#### Post date: [2020年十一月24日 01:26 UTC](https://meta.discourse.org/t/link-rewriting-for-affiliate-codes/52949/3 "2020-11-24T01:26:29Z")

</div>

我不太清楚，但我很想听听这方面是否有新进展：slight\_smile:

---

<div class="post-metadata">

### Author: ![Johani](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/johani/32/176920_2.png) [@Johani](https://meta.discourse.org/u/Johani)
#### Post date: [2020年十一月24日 13:22 UTC](https://meta.discourse.org/t/link-rewriting-for-affiliate-codes/52949/4 "2020-11-24T13:22:55Z")

</div>

如今，这在一个主题组件中应该是可行的，具体取决于链接的样式。

你能贴出一个基础链接的示例，以及它作为联盟链接时的样式示例吗？

---

<div class="post-metadata">

### Author: ![ljpp](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ljpp/32/96506_2.png) [@ljpp](https://meta.discourse.org/u/ljpp)
#### Post date: [2021年一月26日 17:38 UTC](https://meta.discourse.org/t/link-rewriting-for-affiliate-codes/52949/5 "2021-01-26T17:38:21Z")

</div>

此讨论已过早结束。我可能需要重新考虑我们社区的变现方式。

就我而言，我需要为 URL 添加一个前缀。

`http://merchantxyz.com/....`

并将其转换为…

`https://tracker.adagency123.com/t/t?a=12345678&as=87654321&t=2&tk=1&url=https://merchantxyz.com/...`

已有多个主题涉及此问题，但是否已有可供生产环境使用的解决方案？

---

<div class="post-metadata">

### Author: ![justin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/justin/32/157614_2.png) [@justin](https://meta.discourse.org/u/justin)
#### Post date: [2021年一月26日 18:16 UTC](https://meta.discourse.org/t/link-rewriting-for-affiliate-codes/52949/6 "2021-01-26T18:16:18Z")

</div>

可惜我不这么认为。这很可能是一个非常适合发布在 #Marketplace 上的工作机会。

---

<div class="post-metadata">

### Author: ![ljpp](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ljpp/32/96506_2.png) [@ljpp](https://meta.discourse.org/u/ljpp)
#### Post date: [2021年一月28日 20:42 UTC](https://meta.discourse.org/t/link-rewriting-for-affiliate-codes/52949/7 "2021-01-28T20:42:50Z")

</div>

能否将此作为主题自定义功能实现？我正在考虑修改这个 [JSFiddle](https://jsfiddle.net/samliew/ks3y8059)，但不确定在 Discourse 实例中（如果可行的话）正确的实现方式是什么？

```javascript
// 将下方的 "my-affiliate-id" 替换为您实际的联盟 ID
const aid = 'my-affiliate-id';

// 仅当链接中尚未包含联盟 ID 时，追加带联盟 ID 的斜杠
const goglinks = document.querySelectorAll('a[href*="gog.com"]');
goglinks.forEach(function(el) {
  if(!el.href.includes('pp=')) {
    el.href = el.href.replace(/\?.*$/, '') + '?pp=' + aid
  }
})

```

---

<div class="post-metadata">

### Author: ![Johani](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/johani/32/176920_2.png) [@Johani](https://meta.discourse.org/u/Johani)
#### Post date: [2021年一月29日 11:01 UTC](https://meta.discourse.org/t/link-rewriting-for-affiliate-codes/52949/8 "2021-01-29T11:01:33Z")

</div>

是的，这是可行的。让我们从简单的开始。首先，将以下内容添加到新主题组件的“头部（header）”标签页中。

```xml
<script type="text/discourse-plugin" version="0.8.42">

</script>

```

这是做什么的？这是一种由 Discourse 处理的特殊脚本标签。有什么好处呢？它允许你访问 [插件 API](https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/app/lib/plugin-api.js) 的方法。

你想给某些链接附加联盟代码。这意味着你需要修改帖子的内容。如果你查看插件 API，会发现确实有对应的方法。

[https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/app/lib/plugin-api.js#L224-L262](https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/app/lib/plugin-api.js#L224-L262)

使用方法如下：

```javascript
api.decorateCookedElement(
  element =\u003e {
    // 在这里执行你的操作。
    // 此处传入的 element 是已渲染帖子的 HTML 节点
  },
  {
    // 选项放在这里
  }
);

```

这是你需要包裹代码的容器，以便在帖子渲染时触发它。那么，让我们尝试一下。

我们将你的代码原样添加进去：

```diff
api.decorateCookedElement(
  element =\u003e {
++ // 将下面的 "my-affiliate-id" 替换为你实际的联盟 ID
++ const aid = "my-affiliate-id";
++
++ // 仅在链接中尚未包含联盟 ID 时，追加带联盟 ID 的斜杠
++ const goglinks = document.querySelectorAll('a[href*="gog.com"]');
++ goglinks.forEach(function (el) {
++ if (!el.href.includes("pp=")) {
++ el.href = el.href.replace(/\?.*$/, "") + "?pp=" + aid;
++ }
++ });
  },
  {
    // 选项放在这里
  }
);

```

这样能行吗？可以，但它也在做一些多余的工作，因为我们是在查询整个 `document` 中的链接，而不是针对帖子元素。那么如何修复呢？

还记得我们传入方法的 `element` 参数吗？这时候它就派上用场了。

我们不再查询整个文档，而是查询我们要针对的元素。因此，我们将这行代码：

`const goglinks = document.querySelectorAll('a[href*="gog.com"]');`

改为：

`const goglinks = element.querySelectorAll('a[href*="gog.com"]');`

最终结果如下：

```diff
api.decorateCookedElement(
  element =\u003e {
    // 将下面的 "my-affiliate-id" 替换为你实际的联盟 ID
    const aid = "my-affiliate-id";

    // 仅在链接中尚未包含联盟 ID 时，追加带联盟 ID 的斜杠
-- const goglinks = document.querySelectorAll('a[href*="gog.com"]');
++ const goglinks = element.querySelectorAll('a[href*="gog.com"]');
    goglinks.forEach(function (el) {
      if (!el.href.includes("pp=")) {
        el.href = el.href.replace(/\?.*$/, "") + "?pp=" + aid;
      }
    });
  },
  {
    // 选项放在这里
  }
);

```

现在效果很好，但我们还可以再优化一下。由于你只是给链接添加联盟 ID，因此在编辑器（composer）中并不需要触发这段代码。这时方法选项就派上用场了。

你可以传递给方法的一个选项是 `onlyStream`。

它的作用是什么？它告诉该方法，你只希望在帖子在主题内渲染时才执行此代码。让我们添加这个选项。

```diff
api.decorateCookedElement(
  element =\u003e {
    // 将下面的 "my-affiliate-id" 替换为你实际的联盟 ID
    const aid = "my-affiliate-id";

    // 仅在链接中尚未包含联盟 ID 时，追加带联盟 ID 的斜杠
    const goglinks = element.querySelectorAll('a[href*="gog.com"]');
    goglinks.forEach(function (el) {
      if (!el.href.includes("pp=")) {
        el.href = el.href.replace(/\?.*$/, "") + "?pp=" + aid;
      }
    });
  },
  {
++ onlyStream: true
  }
);

```

现在，唯一剩下的就是将这段代码放入我们之前提到的特殊脚本标签中。

```xml
<script type="text/discourse-plugin" version="0.8.42">
api.decorateCookedElement(
  element =\u003e {
    // 将下面的 "my-affiliate-id" 替换为你实际的联盟 ID
    const aid = "my-affiliate-id";

    // 仅在链接中尚未包含联盟 ID 时，追加带联盟 ID 的斜杠
    const goglinks = element.querySelectorAll('a[href*="gog.com"]');
    goglinks.forEach(function (el) {
      if (!el.href.includes("pp=")) {
        el.href = el.href.replace(/\?.*$/, "") + "?pp=" + aid;
      }
    });
  },
  {
    onlyStream: true
  }
);
</script>

```

然后将其添加到你的组件的“头部（header）”标签页中，就完成了。我在这个示例中使用了 GOG，因为这是你询问的对象，但只要你知道 URL 结构，这种模式可以用于_任何_联盟计划。

---

<div class="post-metadata">

### Author: ![ljpp](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ljpp/32/96506_2.png) [@ljpp](https://meta.discourse.org/u/ljpp)
#### Post date: [2021年一月29日 20:41 UTC](https://meta.discourse.org/t/link-rewriting-for-affiliate-codes/52949/9 "2021-01-29T20:41:21Z")

</div>

哇，多么精彩且富有教育意义的教程！

那个 JSFiddle 只是我找到的一个示例。我们这位新的潜在合作伙伴使用的是 [https://前缀](https://xn--ldrr30i)，而不是在末尾附加联盟 ID。他们使用的是 [adtraction.com](http://adtraction.com) 平台。

在此发布我修改后的版本，供其他人使用。

```plaintext

<script type="text/discourse-plugin" version="0.8.42">
api.decorateCookedElement(
  element => {
        const affiliate = 'https://their-ad-network.com/...';
        const affiliate_links = element.querySelectorAll('a[href*="potentialparterwebsite.com"]');

        affiliate_links.forEach(function(el) {
            if (!el.href.startsWith(affiliate)) {
                el.href = affiliate + encodeURIComponent(el.href);
            }
        });
    },
  {
    onlyStream: true
  }
);
</script>

```

现在，该代码会先添加广告网络的 URL 以跟踪点击，然后再追加合作伙伴链接。

---

<div class="post-metadata">

### Author: ![ljpp](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ljpp/32/96506_2.png) [@ljpp](https://meta.discourse.org/u/ljpp)
#### Post date: [2021年二月10日 20:38 UTC](https://meta.discourse.org/t/link-rewriting-for-affiliate-codes/52949/11 "2021-02-10T20:38:04Z")

</div>

虽然这种方法对于手动创建的链接（例如将某个词链接到 [https://website](https://website)）非常有效，但它似乎无法捕获由 Discourse 解析器自动生成的链接。换句话说：

这样是有效的：[Google](http://google.com)  
但这样无效：[Google.com](http://Google.com)

能否改进该脚本，使其也能捕获自动生成的链接？
