楽天ランキングを自動表示する方法

Cocoonカスタマイズ集
この記事は約14分で読めます。
記事内に広告が含まれています。

はじめに

楽天アフィリエイトでランキング記事を作成する場合、通常は商品を1件ずつ手動で貼り付けたり、プラグインに頼る必要があります。
しかし、この方法では更新の手間がかかり、ランキング変動にも即座に対応できません。

また、Cocoon標準のrakutenショートコードは、特定の商品やショップへのリンクが主となり、同じカテゴリー内でどの商品が今売れているのかを把握するには、ボタンをクリックして楽天ページへ移動する必要があります。

そこで、楽天公式APIを利用して、楽天デイリーランキングを自動で取得・表示します。
さらに、表示デザインはCocoonの人気記事カードと統一し、自然にランキング記事へ組み込めるようにします。

この記事では、この方法について説明します。

2026年2月10日に発表された、楽天ウェブサービスの新しいAPI移行仕様に対応済みです。

【最大2000円OFFクーポン有】【楽天ランキング1位獲得★プロのバリスタも使うドリッパー】【2点セット】ORIGAMI オリガミ ドリッパー S 1〜2杯用 (日本製) + ドリッパーホルダー セット 【正規品販売店】※ドリッパーはORIGAMIの刻印入り
【最大2000円OFFクーポン有】【楽天ランキング1位獲得★プロのバリスタも使うドリッパー】【2点セット】ORIGAMI オリガミ ドリッパー S 1〜2杯用 (日本製) + ドリッパーホルダー セット 【正規品販売店】※ドリッパーはORIGAMIの刻印入り
3,630円
インタークリスティーヌ
★4.73 (86)
【最大2000円OFFクーポン有】【2点セット】ORIGAMI オリガミ ドリッパー M 2〜4杯用 (日本製) + ドリッパーホルダー セット 【正規品販売店】※ドリッパーはORIGAMIの刻印入り
【最大2000円OFFクーポン有】【2点セット】ORIGAMI オリガミ ドリッパー M 2〜4杯用 (日本製) + ドリッパーホルダー セット 【正規品販売店】※ドリッパーはORIGAMIの刻印入り
3,850円
インタークリスティーヌ
★4.71 (51)
楽天商品検索

使用方法

楽天デイリーランキング

以下にショートコードを示します。

[my_rakuten_ranking]
オプション
オプション説明値初期値
cache_minuteキャッシュ間隔分単位で指定60
genre_idジャンルID(必須)
count表示数10

楽天市場ページの左メニュー「ジャンル」から対象ジャンルのカテゴリページを開きます。
例えば、ブラウザのURLの100356がジャンルIDです。

https://www.rakuten.co.jp/category/100356/

楽天商品検索

以下にショートコードを示します。

[my_rakuten_search]
オプション
オプション説明値初期値
cache_minuteキャッシュ間隔分単位で指定60
keyword検索キーワード(必須)
count表示数10

実装手順

以下の手順で実装します。

  • ラベル
    PHPを追加

    以下のコードをfunctions.phpに追加します。

    define('RAKUTEN_APP_ID',        '123456789');   // 楽天アプリケーションID
    define('RAKUTEN_AFFILIATE_ID',  '123456789');   // 楽天アフィリエイトID
    define('RAKUTEN_ACCESS_KEY',    '123456789');   // 楽天アクセスキー
    
    
    /**
     * 楽天APIからデータを取得する共通関数
     *
     * @param string $endpoint APIエンドポイントURL
     * @param array $params クエリパラメータ
     * @param string $cache_key Transientキャッシュキー
     * @param int $cache_minute キャッシュ保持時間(分)
     * @return array APIレスポンスの商品配列(失敗時は空配列)
     */
    if (!function_exists('new_rakuten_fetch_api_v3')):
    function new_rakuten_fetch_api_v3($endpoint, $params, $cache_key, $cache_minute) {
      // キャッシュが存在する場合
      if ($cached = get_transient($cache_key)) {
        return $cached;
      }
    
      // APIリクエストURLを生成
      $url = add_query_arg($params, $endpoint);
    
      // リクエストヘッダーの設定(リファラーやオリジンを指定)
      $site_url = rawurldecode(home_url('/', 'https'));
      $args = [
        'timeout' => 15,
        'headers' => [
          'Referer' => $site_url,
          'Origin'  => $site_url,
        ]
      ];
    
      // 楽天APIへHTTPリクエストを送信
      $res = wp_remote_get($url, $args);
    
      if (is_wp_error($res)) {
        return [];
      }
    
      // 正常レスポンス(HTTP 200)以外の場合
      if (wp_remote_retrieve_response_code($res) !== 200) {
        return [];
      }
    
      // JSONレスポンスを連想配列に変換
      $json = json_decode(wp_remote_retrieve_body($res), true);
    
      // キー名の大文字・小文字両方に対応して商品リストを取得
      $items = null;
      if (!empty($json['Items'])) {
        $items = $json['Items'];
      } elseif (!empty($json['items'])) {
        $items = $json['items'];
      }
    
      if (empty($items)) {
        return [];
      }
    
      // キャッシュデータを保存
      set_transient($cache_key, $items, MINUTE_IN_SECONDS * max(1, (int)$cache_minute));
    
      return $items;
    }
    endif;
    
    
    /**
     * 楽天商品データからCocoon形式のカードHTMLを生成
     *
     * @param array $item_data 楽天APIの1商品データ
     * @param int $display_rank 表示順位
     * @return string 生成されたカードのHTML文字列
     */
    if (!function_exists('new_rakuten_render_ranking_card_v3')):
    function new_rakuten_render_ranking_card_v3($item_data, $display_rank) {
      // データ配列の大文字・小文字両方に対応
      $item = isset($item_data['item']) ? $item_data['item'] : ($item_data['Item'] ?? null);
    
      if (!$item) {
        return '';
      }
    
      $actual_rank = $display_rank;
    
      $title   = esc_html($item['itemName']);
      $price   = number_format($item['itemPrice']);
      $shop    = esc_html($item['shopName']);
      $url     = esc_url($item['affiliateUrl']);
    
      // 画像URLを取得(複数の構造に対応)
      $img_url = '';
      if (!empty($item['images'][0]['imageUrl'])) {
        $img_url = $item['images'][0]['imageUrl'];
      } elseif (!empty($item['mediumImageUrls'][0]['imageUrl'])) {
        $img_url = $item['mediumImageUrls'][0]['imageUrl'];
      }
      $img = esc_url($img_url);
    
      // レビュー評価と件数を取得
      $rating  = $item['reviewAverage'] ?? '0.0';
      $reviews = number_format($item['reviewCount'] ?? 0);
    
      ob_start();
      ?>
      <a href="<?= $url; ?>" class="popular-entry-card-link widget-entry-card-link a-wrap no-<?= $actual_rank; ?>" title="<?= $title; ?>" target="_blank" rel="nofollow sponsored">
        <div class="popular-entry-card widget-entry-card e-card cf post ranking-visible">
          <figure class="popular-entry-card-thumb widget-entry-card-thumb card-thumb">
            <img src="<?= $img; ?>" alt="<?= $title; ?>" loading="lazy">
          </figure>
          <div class="popular-entry-card-content widget-entry-card-content card-content">
            <div class="popular-entry-card-title widget-entry-card-title card-title">
              <?= $title; ?>
            </div>
            <div class="popular-entry-card-snippet widget-entry-card-snippet card-snippet rakuten">
              <div class="rakuten-rank-price bold-red">
                <?= $price; ?>円
              </div>
              <div class="rakuten-rank-shop"><?= $shop; ?></div>
    
              <?php if ($reviews > 0): ?>
                <div class="rakuten-rank-rating">
                  <span class="stars">★<?= $rating; ?></span>
                  <span class="count">(<?= $reviews; ?>)</span>
                </div>
              <?php endif; ?>
    
            </div>
          </div>
        </div>
      </a>
      <?php
      return ob_get_clean();
    }
    endif;
    
    
    // ショートコードを追加
    add_shortcode('my_rakuten_ranking', function ($atts) {
      $atts = shortcode_atts([
        'genre_id'     => '',   // 楽天ジャンルID
        'count'        => 10,   // 表示件数
        'cache_minute' => 60,   // キャッシュ保持時間(分)
      ], $atts);
    
      if (empty($atts['genre_id'])) {
        return '<p>ジャンルIDが未入力です。</p>';
       }
    
      // ランキングAPIエンドポイント
      $endpoint = 'https://openapi.rakuten.co.jp/ichibaranking/api/IchibaItem/Ranking/20220601';
    
      // APIリクエストパラメータの設定
      $params = [
        'applicationId' => RAKUTEN_APP_ID,
        'affiliateId'   => RAKUTEN_AFFILIATE_ID,
        'accessKey'     => RAKUTEN_ACCESS_KEY,
        'format'        => 'json',
        'genreId'       => $atts['genre_id'],
      ];
    
      // キャッシュキーを生成
      $cache_key = 'rak_rank_v3_' . $atts['genre_id'];
    
      // APIからデータを取得
      $items = new_rakuten_fetch_api_v3($endpoint, $params, $cache_key, $atts['cache_minute']);
    
      if (empty($items)) {
        return '<p>ランキング情報を取得できませんでした。</p>';
      }
    
      // APIから返ってきたデータの順位が降順になっている場合は昇順に補正
      if (isset($items[0]['Item']['rank'], $items[1]['Item']['rank'])) {
        if ((int)$items[0]['Item']['rank'] > (int)$items[1]['Item']['rank']) {
          $items = array_reverse($items);
        }
      } elseif (isset($items[0]['item']['rank'], $items[1]['item']['rank'])) {
        if ((int)$items[0]['item']['rank'] > (int)$items[1]['item']['rank']) {
          $items = array_reverse($items);
        }
      }
    
      // 指定された表示件数に制限
      $items = array_slice($items, 0, (int)$atts['count']);
    
      ob_start();
      ?>
      <div class="popular-entry-cards widget-entry-cards no-icon cf border-square ranking-visible">
        <?php foreach ($items as $index => $item_data): ?>
          <?= new_rakuten_render_ranking_card_v3($item_data, $index + 1); ?>
        <?php endforeach; ?>
      </div>
      <?php
      return ob_get_clean();
    });
    
    
    // ショートコードを追加
    add_shortcode('my_rakuten_search', function ($atts) {
      $atts = shortcode_atts([
        'keyword'      => '',   // 検索キーワード
        'count'        => 10,   // 表示件数
        'cache_minute' => 60,   // キャッシュ保持時間(分)
      ], $atts, 'rakuten_search');
    
      if (empty($atts['keyword'])) {
        return '<p>キーワードが未入力です。</p>';
      }
    
      // 商品検索APIエンドポイント
      $endpoint = 'https://openapi.rakuten.co.jp/ichibams/api/IchibaItem/Search/20260701';
    
      // APIリクエストパラメータの設定
      $params = [
        'applicationId' => RAKUTEN_APP_ID,
        'affiliateId'   => RAKUTEN_AFFILIATE_ID,
        'accessKey'     => RAKUTEN_ACCESS_KEY,
        'format'        => 'json',
        'keyword'       => $atts['keyword'],
        'sort'          => '-reviewCount',      // レビュー数順
        'hits'          => (int)$atts['count'],
      ];
    
      // キャッシュキーを生成
      $cache_key = 'rak_srch_v3_' . md5($atts['keyword'] . $atts['count']);
    
      // APIからデータを取得
      $items = new_rakuten_fetch_api_v3($endpoint, $params, $cache_key, $atts['cache_minute']);
    
      if (empty($items)) {
        return '<p>商品が見つかりませんでした。</p>';
      }
    
      ob_start();
      ?>
      <div class="popular-entry-cards widget-entry-cards no-icon cf border-square ranking-visible">
        <?php foreach ($items as $index => $item_data): ?>
          <?= new_rakuten_render_ranking_card_v3($item_data, $index + 1); ?>
        <?php endforeach; ?>
      </div>
      <?php
      return ob_get_clean();
    });
  • ラベル
    CSSを追加

    以下のコードをstyle.cssに追加します。

    .widget-entry-cards .rakuten.popular-entry-card-snippet {
      display: flex;
      gap: 10px;
    }
    
    .rakuten-rank-rating {
      color: #f39c12;
    }

さいごに

今回紹介した方法を使えば、楽天公式APIを利用して、ランキング記事を自動更新で運用できるようになります。
商品を1件ずつ手作業で貼り替える必要がなく、ランキング変動にも自然に追従できるため、更新コストを大幅に削減できます。

また、Cocoon標準のデザインをそのまま活かしているため、テーマとの統一感を損なわずに導入できる点も大きなメリットです。
売れ筋商品を一覧で把握できるランキング表示は、読者にとっても分かりやすく、アフィリエイト導線としても有効です。

タイトルとURLをコピーしました