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

はい、可能です。まずは簡単なところから始めましょう。新しいテーマコンポーネントの「ヘッダー」タブに、以下のコードを追加します。

<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 引数を覚えていますか?ここでそれが役立ちます。

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 を追加するだけなので、コンポーザー内ではこのコードを実行する必要はありません。ここでメソッドのオプションが役立ちます。

メソッドに渡せるオプションの一つに 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>

これをコンポーネントの「ヘッダー」タブに追加すれば、準備完了です。この例では GOG を使用しましたが、URL 構造がわかれば、このパターンはあらゆるアフィリエイトプログラムに適用できます。

「いいね!」 11

わあ、なんて素晴らしい教育的なチュートリアルでしょう!

JSFiddle は私がたまたま見つけた例にすぎません。私たちの新たな潜在的パートナーは、末尾にアフィリエイト ID を置くのではなく、https:// プレフィックスを使用しています。彼らは 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

スクリプトを改善して、自動的に生成されたリンクも検出できるようにすることはできますか?