大きすぎるタグは埋もれ、小さすぎるタグは誰も見ない。数字を見れば、その中間が分かる。
母数と競合度をスコア化して、狙い目のタグを機械的に見つけます
📋 この記事でわかること
- タグの記事数と関連タグを取得するAPI
- タグ内の記事を取得して競合度を測る方法
- 母数と競合からスコアを算出する考え方
- 関連タグを再帰的にたどってタグ地図を作る処理
- 自分の記事のタグ使用状況を分析するスクリプト
- タグを何個・どう付けるかの判断基準
noteのハッシュタグは、記事が読まれる経路の1つです。タグページから流入してくる読者がいるためです。しかし、どのタグを付けるかは多くの人が感覚で決めています。「#日記」のような巨大なタグに付けても、投稿の洪水に埋もれて誰の目にも触れません。逆にニッチすぎるタグは、そもそも見ている人がいません。noteのハッシュタグAPIを使えば、タグごとの記事数と関連タグを取得でき、母数と競合度を数字で比較できます。この記事では、その分析を自動化するスクリプトを作ります。
使うエンドポイント
GET /api/v2/hashtags/{tag}——タグの記事数と関連タグGET /api/v3/hashtags/{tag}/notes——そのタグの記事一覧- どちらも認証不要で使えます
タグの基本情報を取得する
最初のエンドポイントは、タグそのものの情報を返します。記事数と関連タグが取得できます。
import time
from urllib.parse import quote
import requests
UA = ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36")
def get_tag_info(tag: str) -> dict:
"""タグの記事数と関連タグを取得する"""
# 日本語タグはURLエンコードが必要
encoded = quote(tag, safe="")
res = requests.get(
f"https://note.com/api/v2/hashtags/{encoded}",
headers={"User-Agent": UA, "Accept": "application/json"},
timeout=20,
)
if res.status_code != 200:
print(f" 取得失敗({res.status_code}): {tag}")
return {}
data = res.json().get("data", {})
# hashtag キーの下にある場合と、直下にある場合の両方に対応
hashtag = data.get("hashtag", data)
return {
"name": hashtag.get("name", tag),
"count": hashtag.get("count", 0),
"related": [
{"name": r.get("name", ""), "count": r.get("count", 0)}
for r in data.get("relatedHashtags",
data.get("related_hashtags", []))
],
}
if __name__ == "__main__":
for tag in ["Python", "副業", "エッセイ", "毎日note"]:
info = get_tag_info(tag)
if not info:
continue
print(f"\n#{info['name']}")
print(f" 記事数: {info['count']:,} 件")
if info["related"]:
print(" 関連タグ:")
for r in info["related"][:8]:
print(f" #{r['name']}({r['count']:,})")
time.sleep(1.2)
日本語タグはURLエンコードが必須
quote(tag, safe="") を通さずに日本語をそのままURLに含めると、リクエストが失敗するか意図しないタグを参照します。safe="" を指定するのは、スラッシュなどの記号も含めてすべてエンコードするためです。日本語タグを扱ううえで最初につまずくポイントなので、必ず入れてください。
タグ内の記事を取得する
タグに紐づく記事の一覧は、別のエンドポイントで取得します。並び順と有料記事のみの絞り込みが指定できます。
| パラメータ | 値 | 意味 |
|---|---|---|
| order | popular | 人気順 |
| order | new | 新着順 |
| order | hot | 急上昇 |
| page | 数値 | ページ番号 |
| paid_only | true / false | 有料記事だけに絞る |
import time
from urllib.parse import quote
import requests
UA = ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36")
def pick(d: dict, *keys, default=None):
for k in keys:
if k in d and d[k] is not None:
return d[k]
return default
def get_tag_notes(tag: str, order: str = "popular",
pages: int = 1, paid_only: bool = False) -> list:
"""タグに紐づく記事を取得する(1ページ50件程度)"""
encoded = quote(tag, safe="")
session = requests.Session()
session.headers.update({"User-Agent": UA})
results = []
for page in range(1, pages + 1):
params = {"order": order, "page": page}
if paid_only:
params["paid_only"] = "true"
res = session.get(
f"https://note.com/api/v3/hashtags/{encoded}/notes",
params=params,
timeout=20,
)
if res.status_code != 200:
print(f" page {page}: HTTP {res.status_code}")
break
data = res.json().get("data", {})
notes = data.get("notes", [])
if not notes:
break
results.extend(notes)
print(f" page {page}: {len(notes)} 件(累計 {len(results)})")
if data.get("isLastPage") or data.get("is_last_page"):
break
time.sleep(1.2)
return results
if __name__ == "__main__":
tag = "Webライティング"
notes = get_tag_notes(tag, order="popular", pages=1)
print(f"\n=== #{tag} の人気記事 ===")
for n in notes[:15]:
likes = pick(n, "likeCount", "like_count", default=0)
price = pick(n, "price", default=0) or 0
mark = "有料" if price else "無料"
print(f" [{mark}] スキ{likes:>5} | {n.get('name', '')[:38]}")
タグを評価する指標を作る
記事数だけではタグの良し悪しは判断できません。「母数の大きさ」と「上位に食い込む難しさ」の両方を見る必要があります。ここでは3つの指標を組み合わせます。
- 記事数(母数)——そのタグを見る人がどれくらいいるかの目安。少なすぎると流入が期待できません。
- 上位記事のスキ中央値——上位に並ぶための水準。高いほど競争が激しい領域です。
- 新着の勢い——直近でどれくらい投稿されているか。多いほど早く流れて埋もれます。
"""
タグを複数の指標で評価し、狙い目かどうかをスコア化する。
"""
import time
from tag_info import get_tag_info
from tag_notes import get_tag_notes, pick
def median(values: list) -> float:
if not values:
return 0.0
s = sorted(values)
mid = len(s) // 2
if len(s) % 2:
return float(s[mid])
return (s[mid - 1] + s[mid]) / 2
def evaluate_tag(tag: str) -> dict:
"""タグ1つを評価する"""
info = get_tag_info(tag)
if not info:
return {"tag": tag, "error": "情報を取得できません"}
time.sleep(1.0)
popular = get_tag_notes(tag, order="popular", pages=1)
time.sleep(1.0)
recent = get_tag_notes(tag, order="new", pages=1)
likes = [pick(n, "likeCount", "like_count", default=0) or 0
for n in popular]
recent_likes = [pick(n, "likeCount", "like_count", default=0) or 0
for n in recent]
# 新着記事のスキ中央値が低い=新規参入者が読まれていない
result = {
"tag": tag,
"total_notes": info["count"],
"top_likes_max": max(likes) if likes else 0,
"top_likes_median": median(likes),
"new_likes_median": median(recent_likes),
"related_count": len(info["related"]),
}
result["score"] = calc_score(result)
return result
def calc_score(r: dict) -> float:
"""
狙い目スコアを算出する(高いほど狙い目)。
- 母数が一定以上ある
- 上位のハードルが高すぎない
- 新着でも読まれている形跡がある
"""
total = r["total_notes"]
top_median = r["top_likes_median"]
new_median = r["new_likes_median"]
# 母数の評価(多すぎても少なすぎても減点)
if total < 500:
size_score = total / 500 * 40 # 小さすぎる
elif total <= 30000:
size_score = 40 # ちょうどよい
else:
size_score = max(10, 40 - (total - 30000) / 20000)
# 上位のハードル(低いほど入り込みやすい)
if top_median <= 0:
entry_score = 0
else:
entry_score = max(0, 30 - min(top_median, 300) / 10)
# 新着でも反応がある領域か
reach_score = min(30, new_median * 3)
return round(size_score + entry_score + reach_score, 1)
def show(tags: list):
results = []
for t in tags:
print(f"\n### 評価中: #{t}")
r = evaluate_tag(t)
results.append(r)
time.sleep(1.5)
print("\n" + "=" * 76)
print(f"{'タグ':<18}{'記事数':>10}{'上位中央':>9}"
f"{'新着中央':>9}{'スコア':>8}")
print("-" * 76)
for r in sorted(results,
key=lambda x: x.get("score", 0), reverse=True):
if r.get("error"):
print(f"{r['tag']:<18} {r['error']}")
continue
print(f"#{r['tag']:<17}{r['total_notes']:>10,}"
f"{r['top_likes_median']:>9.0f}"
f"{r['new_likes_median']:>9.0f}{r['score']:>8}")
return results
if __name__ == "__main__":
show(["Webライティング", "副業", "ブログ運営",
"文章術", "note初心者"])
スコアの計算式は、目的に応じて調整してください。ここでは「記事数が500〜30,000件」「上位のスキ中央値が低め」「新着でも反応がある」という条件を高く評価しています。数式そのものより、複数の指標を組み合わせて比較するという考え方が重要です。
▶ タグと合わせて、キーワード自体の需要も調べておきたいところです。
検索APIを使ったリサーチ方法を解説しています。
関連タグをたどってタグ地図を作る
関連タグを再帰的にたどると、そのジャンルのタグ構造が見えてきます。自分では思いつかないタグが見つかることも多い処理です。
"""
関連タグを幅優先でたどり、タグの繋がりを地図として出力する。
"""
import csv
import time
from collections import deque
from tag_info import get_tag_info
MAX_TAGS = 60 # 収集する上限
MAX_DEPTH = 2 # たどる深さ
SLEEP_SEC = 1.2
def crawl(seed: str, max_tags: int = MAX_TAGS,
max_depth: int = MAX_DEPTH) -> dict:
"""関連タグを幅優先でたどる"""
visited = {}
edges = []
queue = deque([(seed, 0)])
while queue and len(visited) < max_tags:
tag, depth = queue.popleft()
if tag in visited or depth > max_depth:
continue
info = get_tag_info(tag)
time.sleep(SLEEP_SEC)
if not info:
continue
visited[tag] = info["count"]
print(f" {' ' * depth}#{tag}({info['count']:,})")
for r in info["related"]:
name = r["name"]
if not name:
continue
edges.append((tag, name, r["count"]))
if name not in visited and depth < max_depth:
queue.append((name, depth + 1))
return {"tags": visited, "edges": edges}
def save_csv(result: dict, seed: str):
stamp = seed.replace(" ", "_")
with open(f"tags_{stamp}.csv", "w",
encoding="utf-8-sig", newline="") as f:
writer = csv.writer(f)
writer.writerow(["tag", "note_count"])
for tag, count in sorted(result["tags"].items(),
key=lambda x: -x[1]):
writer.writerow([tag, count])
with open(f"tag_edges_{stamp}.csv", "w",
encoding="utf-8-sig", newline="") as f:
writer = csv.writer(f)
writer.writerow(["from", "to", "to_count"])
writer.writerows(result["edges"])
print(f"\ntags_{stamp}.csv と tag_edges_{stamp}.csv を出力しました")
def report(result: dict):
tags = result["tags"]
if not tags:
print("収集できたタグがありません")
return
print("\n=== 収集したタグ(記事数順)===")
for tag, count in sorted(tags.items(), key=lambda x: -x[1]):
print(f" {count:>9,} #{tag}")
# 母数が中規模のタグを狙い目として提示する
sweet = [(t, c) for t, c in tags.items() if 1000 <= c <= 20000]
if sweet:
print("\n=== 狙い目候補(記事数1,000〜20,000)===")
for tag, count in sorted(sweet, key=lambda x: -x[1]):
print(f" {count:>9,} #{tag}")
if __name__ == "__main__":
import sys
seed = sys.argv[1] if len(sys.argv) > 1 else "Webライティング"
print(f"=== #{seed} から関連タグをたどります ===")
result = crawl(seed)
report(result)
save_csv(result, seed)
出力されたCSVは、そのままグラフ可視化ツールに読み込ませることもできます。タグの繋がりが見えると、自分のジャンルの全体像が把握できます。
自分の記事のタグ使用状況を分析する
他人のタグを調べる前に、自分がどんなタグを使っているかを把握しておくべきです。無意識に同じタグばかり使っているケースは多いものです。
"""
自分の記事に付けたタグを集計し、効果を検証する。
"""
import time
from collections import Counter, defaultdict
import requests
URLNAME = "your_note_id" # ← 自分のnote IDに変更
UA = ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36")
def pick(d: dict, *keys, default=None):
for k in keys:
if k in d and d[k] is not None:
return d[k]
return default
def fetch_my_notes(urlname: str, max_pages: int = 50) -> list:
session = requests.Session()
session.headers.update({"User-Agent": UA})
items = []
for page in range(1, max_pages + 1):
res = session.get(
f"https://note.com/api/v2/creators/{urlname}/contents",
params={"kind": "note", "page": page},
timeout=20,
)
if res.status_code != 200:
break
data = res.json().get("data", {})
contents = data.get("contents", [])
if not contents:
break
items.extend(contents)
if data.get("isLastPage") or data.get("is_last_page"):
break
time.sleep(1.2)
return items
def extract_tags(item: dict) -> list:
"""記事オブジェクトからタグ名の配列を取り出す"""
raw = item.get("hashtags") or item.get("hashtag_notes") or []
names = []
for h in raw:
if isinstance(h, str):
names.append(h.lstrip("#"))
elif isinstance(h, dict):
# {"hashtag": {"name": "..."}} の形にも対応
inner = h.get("hashtag", h)
name = inner.get("name", "")
if name:
names.append(name.lstrip("#"))
return names
def analyze(items: list):
counter = Counter()
likes_by_tag = defaultdict(list)
no_tag = 0
for item in items:
tags = extract_tags(item)
likes = pick(item, "likeCount", "like_count", default=0) or 0
if not tags:
no_tag += 1
continue
for t in tags:
counter[t] += 1
likes_by_tag[t].append(likes)
print(f"=== 記事 {len(items)} 本のタグ分析 ===")
print(f" タグなしの記事: {no_tag} 本")
print(f" 使用タグの種類: {len(counter)} 種")
if items:
avg_tags = sum(counter.values()) / len(items)
print(f" 1記事あたり平均: {avg_tags:.1f} 個")
print("\n=== よく使うタグ TOP20 ===")
print(f"{'タグ':<20}{'使用':>6}{'平均スキ':>10}")
print("-" * 40)
for tag, count in counter.most_common(20):
likes = likes_by_tag[tag]
avg = sum(likes) / len(likes) if likes else 0
print(f"#{tag:<19}{count:>6}{avg:>10.1f}")
# 1回しか使っていないタグ
once = [t for t, c in counter.items() if c == 1]
print(f"\n1回だけ使ったタグ: {len(once)} 種")
if once:
print(" " + ", ".join(f"#{t}" for t in once[:15]))
if __name__ == "__main__":
notes = fetch_my_notes(URLNAME)
analyze(notes)
1回だけ使ったタグに注目する
1回しか使っていないタグが多い場合、タグ運用が場当たり的になっている可能性があります。同じタグを繰り返し使うと、そのタグページで自分の記事が並び、興味を持った読者が他の記事も見てくれます。逆に毎回違うタグを付けていると、この効果が得られません。核となるタグを3〜5個決めて、継続して使うのが有効です。
タグは何個付けるべきか
noteでは複数のタグを付けられますが、多ければいいわけではありません。判断の目安を整理します。
| タグの数 | 効果 | 評価 |
|---|---|---|
| 0個 | タグ経由の流入がゼロになる | もったいない |
| 1〜2個 | 絞りすぎて機会損失 | やや少ない |
| 3〜5個 | 関連性を保ちつつ複数経路を確保 | 推奨 |
| 6〜10個 | 関連の薄いタグが混ざり始める | 内容次第 |
| 10個以上 | 無関係なタグが増え、印象を損ねる | 避けたい |
推奨は3〜5個です。内訳としては「大きいタグ1個・中規模タグ2個・ニッチなタグ1〜2個」という組み合わせが機能しやすくなります。大きいタグは母数狙い、中規模タグは実際の流入源、ニッチなタグは同じ関心を持つ読者との接点、という役割分担です。
"""
記事のテーマから、規模別にタグを提案する。
大 / 中 / 小のバランスで組み合わせを作る。
"""
import time
from tag_info import get_tag_info
def collect_candidates(seed: str, limit: int = 40) -> dict:
"""シードタグと、その関連タグを集める"""
candidates = {}
info = get_tag_info(seed)
if not info:
return candidates
candidates[info["name"]] = info["count"]
for r in info["related"][:limit]:
if r["name"]:
candidates[r["name"]] = r["count"]
return candidates
def suggest(seed: str):
candidates = collect_candidates(seed)
if not candidates:
print(f"#{seed} の情報を取得できませんでした")
return
large = {t: c for t, c in candidates.items() if c > 50000}
medium = {t: c for t, c in candidates.items() if 3000 <= c <= 50000}
small = {t: c for t, c in candidates.items() if 200 <= c < 3000}
def top(d: dict, n: int) -> list:
return sorted(d.items(), key=lambda x: -x[1])[:n]
print(f"=== #{seed} を起点としたタグ提案 ===\n")
print("【大規模タグ】母数狙い・1個まで")
for t, c in top(large, 5):
print(f" #{t}({c:,}件)")
print("\n【中規模タグ】主力・2個程度")
for t, c in top(medium, 8):
print(f" #{t}({c:,}件)")
print("\n【ニッチタグ】接点作り・1〜2個")
for t, c in top(small, 8):
print(f" #{t}({c:,}件)")
# 推奨の組み合わせを提示
combo = []
if large:
combo.append(top(large, 1)[0][0])
combo += [t for t, _ in top(medium, 2)]
combo += [t for t, _ in top(small, 1)]
if combo:
print("\n【推奨の組み合わせ】")
print(" " + " ".join(f"#{t}" for t in combo))
if __name__ == "__main__":
import sys
seed = sys.argv[1] if len(sys.argv) > 1 else "文章術"
suggest(seed)
time.sleep(1.0)
▼ RECOMMENDATION ▼
タグ流入には限界がある。外から集める導線を持つ
タグを最適化しても、note内で見てもらえる数には上限があります。安定してアクセスを増やすには、プラットフォームの外に導線を持つことが必要です。アメブロであれば、アメプレスProがいいね・フォロー・アクセス獲得を自動で回し、集客そのものを仕組み化できます。noteと違ってASPアフィリエイトも使えるため、集めた読者を収益につなげる設計も可能です。月額2,980円、365日LINEサポート付きです。
※ 当サイトはアフィリエイト広告を含みます。
タグの推移を記録する
タグの記事数は時間とともに変わります。定期的に記録しておくと、伸びているタグが分かります。
"""
監視対象のタグの記事数を日次で記録し、増加率を出す。
"""
import csv
import os
import time
from datetime import date
from tag_info import get_tag_info
WATCH_TAGS = [
"Webライティング",
"副業",
"文章術",
"ブログ運営",
"note初心者",
]
HISTORY_FILE = "tag_history.csv"
def record(tags: list = None, path: str = HISTORY_FILE):
tags = tags or WATCH_TAGS
today = date.today().isoformat()
exists = os.path.exists(path)
with open(path, "a", encoding="utf-8-sig", newline="") as f:
writer = csv.writer(f)
if not exists:
writer.writerow(["date", "tag", "note_count"])
for tag in tags:
info = get_tag_info(tag)
if info:
writer.writerow([today, info["name"], info["count"]])
print(f" #{info['name']}: {info['count']:,}")
time.sleep(1.2)
print(f"\n{today} の記録を追加しました")
def show_growth(path: str = HISTORY_FILE):
"""最初の記録と最新の記録を比較する"""
if not os.path.exists(path):
print("履歴がありません")
return
with open(path, encoding="utf-8-sig") as f:
rows = list(csv.DictReader(f))
by_tag = {}
for r in rows:
by_tag.setdefault(r["tag"], []).append(
(r["date"], int(r["note_count"]))
)
print("=== タグの成長 ===")
print(f"{'タグ':<20}{'初回':>10}{'最新':>10}{'増加':>10}{'率':>8}")
print("-" * 60)
for tag, history in by_tag.items():
history.sort()
if len(history) < 2:
continue
first = history[0][1]
last = history[-1][1]
diff = last - first
rate = (diff / first * 100) if first else 0
print(f"#{tag:<19}{first:>10,}{last:>10,}"
f"{diff:>+10,}{rate:>7.1f}%")
if __name__ == "__main__":
record()
show_growth()
数週間分たまると、投稿が増えているタグ(=注目が集まっている領域)が見えてきます。伸びているタグに早めに参入すると、競合が増える前にポジションを取れる可能性があります。
分析結果をどう使うか
数字が出たあとの判断の型を整理します。
| タグの状態 | 意味 | 使い方 |
|---|---|---|
| 記事数が数十万件 | 投稿が多すぎて埋もれる | 付けてもよいが、期待しない |
| 記事数1,000〜20,000件 | 母数と競合のバランスが良い | 主力タグとして使う |
| 記事数100件未満 | 見る人がほとんどいない | 接点作り目的なら可 |
| 上位のスキ中央値が高い | 強い書き手が集まっている | 質で勝負するか、避ける |
| 新着でもスキが付いている | 新規参入者も読まれている | 狙い目 |
| 関連タグが多い | 広がりのあるジャンル | 周辺テーマも書ける |
タグは流入経路の1つにすぎない
タグ分析に時間をかけすぎるのは非効率です。タグから来る読者は、記事の流入全体の一部でしかありません。タグの最適化で得られる差より、記事の内容とタイトルの差のほうがはるかに大きいという前提を忘れないでください。この記事のスクリプトは、タグ選定を数分で終わらせて、書くことに時間を使うためのものです。
まとめ:タグは母数と競合のバランスで選ぶ
ハッシュタグAPIを使うと、感覚で決めていたタグ選定を数字で行えるようになります。実装も簡単で、認証も不要です。
この記事の要点
- タグ情報は
/api/v2/hashtags/{tag}で取得する - 日本語タグは
quote(tag, safe="")でエンコードする - 記事一覧は
/api/v3/hashtags/{tag}/notes。order で並び順を指定 - 記事数・上位のスキ中央値・新着の反応の3点で評価する
- 関連タグを再帰的にたどると、ジャンル構造が見える
- タグは3〜5個。大・中・小を組み合わせる
- 同じタグを継続して使うと、回遊が生まれる
- タグ最適化より、記事の質とタイトルのほうが影響は大きい
まずは自分の記事のタグ使用状況を分析するところから始めてください。1回しか使っていないタグが大量に出てくるようなら、そこが最初の改善点になります。
FAQ|noteのタグ分析についてよくある質問
タグページを見ている読者からの流入は確かに存在します。ただし、記事全体の流入に占める割合は大きくありません。タグを最適化することによる効果は「無いよりはある」という程度に考えてください。付けないと機会をゼロにするので付けるべきですが、タグ選定に何十分もかけるのは投資として見合いません。
中規模が最も機能します。記事数が数十万件のタグは、投稿した瞬間に流れて誰の目にも触れません。逆に数十件のタグは、そもそも見に来る人がいません。目安として1,000〜20,000件程度のタグが、母数と競合のバランスが取れています。この記事のスクリプトはその判定を自動化するものです。
やめてください。関係ないタグを付けると、期待して開いた読者が離脱し、結果的に評価を下げます。またタグの乱用は規約上も問題になり得ます。読者がそのタグを見ているときに「これは読みたい記事だ」と思える内容であることが、タグを付ける最低条件です。数を増やすことより、関連性を保つことを優先してください。
公開後でも編集画面から変更できます。反応が悪かった記事のタグを見直すのは有効な改善です。ただし、タグを変えたからといって急に読まれるようになるわけではありません。まずタイトルと冒頭を見直し、それでも変化がなければタグを調整する、という順序が現実的です。
公開されていませんが、同時に使われることが多いタグが関連として返っていると考えられます。つまり、実際の投稿者たちがどうタグを組み合わせているかの集合知です。これは自分でタグを考えるより信頼できる情報源になります。関連タグを起点に候補を広げる方法が有効なのは、この性質があるためです。
この記事の計算式は、経験則に基づく1つの案です。公式な指標ではありません。重要なのは数式そのものではなく、複数の指標を同じ基準で比較できる形にすることです。自分の運用実績と照らして、係数や閾値は調整してください。たとえば、より小さなタグを重視したいなら母数の評価範囲を下げる、といった調整が考えられます。
URLエンコードを忘れているケースがほとんどです。urllib.parse.quote(tag, safe="") を通してください。safe="" の指定を省くと、一部の文字がエンコードされずに残り、意図しないリクエストになります。それでも失敗する場合は、そのタグが実際に存在するか、noteの画面上で確認してみてください。
APIからは取得できません。noteのダッシュボードでも、流入元をタグ単位で分解した数字は提供されていません。そのため、タグの効果は間接的に推測するしかありません。同じ内容の記事で異なるタグを試し、ビュー数の差を見るという方法もありますが、他の要因の影響が大きいため厳密な比較は困難です。
note運営が設定するお題タグは、特設ページに掲載されるため通常のタグより露出の機会があります。テーマが自分の記事と合っているなら、参加する価値はあります。ただし、お題に合わせて無理に記事を書くと内容が薄くなりがちです。すでに書きたいことがあり、それがお題と重なるときに使うのが自然です。
ジャンルを決めるときに1回、その後は3ヶ月に1回程度で十分です。タグの記事数は日々変動しますが、短期間で大きく傾向が変わることはありません。むしろ、決めた核となるタグを継続して使い続けることのほうが効果があります。頻繁に分析し直すより、同じタグで記事を積み上げるほうが結果につながります。