Link rewriting for affiliate codes

I saw this and was thrilled:

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?

2 个赞

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

我不太清楚,但我很想听听这方面是否有新进展:slight_smile:

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

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

2 个赞

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

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

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

并将其转换为…

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

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

2 个赞

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

2 个赞

能否将此作为主题自定义功能实现?我正在考虑修改这个 JSFiddle,但不确定在 Discourse 实例中(如果可行的话)正确的实现方式是什么?

// 将下方的 "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
  }
})
1 个赞

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

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

</script>

这是做什么的?这是一种由 Discourse 处理的特殊脚本标签。有什么好处呢?它允许你访问 插件 API 的方法。

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

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

使用方法如下:

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

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

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

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"]');

最终结果如下:

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

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

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 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 结构,这种模式可以用于任何联盟计划。

11 个赞

哇,多么精彩且富有教育意义的教程!

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

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


<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 以跟踪点击,然后再追加合作伙伴链接。

3 个赞

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

这样是有效的:Google
但这样无效:Google.com

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