はじめに
楽天アフィリエイトでランキング記事を作成する場合、通常は商品を1件ずつ手動で貼り付けたり、プラグインに頼る必要があります。
しかし、この方法では更新の手間がかかり、ランキング変動にも即座に対応できません。
また、Cocoon標準のrakutenショートコードは、特定の商品やショップへのリンクが主となり、同じカテゴリー内でどの商品が今売れているのかを把握するには、ボタンをクリックして楽天ページへ移動する必要があります。
そこで、楽天公式APIを利用して、楽天デイリーランキングを自動で取得・表示します。
さらに、表示デザインはCocoonの人気記事カードと統一し、自然にランキング記事へ組み込めるようにします。
この記事では、この方法について説明します。
完成イメージ
楽天デイリーランキング
楽天商品検索
使用方法
楽天デイリーランキング
以下にショートコードを示します。
[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標準のデザインをそのまま活かしているため、テーマとの統一感を損なわずに導入できる点も大きなメリットです。
売れ筋商品を一覧で把握できるランキング表示は、読者にとっても分かりやすく、アフィリエイト導線としても有効です。


