【開発記録】TikTokの短縮URLを正しく埋め込むまでの試行錯誤

こんにちは、Procom開発チームです。
本日は「TikTokの埋め込み機能」に関して、短縮URL対応の実装とその裏側で起きた問題・改善・最終的な成功までの道のりを記録としてまとめます。


🎯 最初の目的:TikTokの動画を最大3つまで埋め込みたい!

Procomでは、ユーザーページにTikTok動画を埋め込むことができます。しかし、ユーザーが投稿するURLには次のような違いがありました:

  • ✅ 通常URL(例)
    https://www.tiktok.com/@username/video/1234567890123456789
  • ❗短縮URL(例)
    https://vt.tiktok.com/ZSSxATuyK/

最初に想定していたのは「通常URL」のみで、これであればTikTokの提供する <blockquote class="tiktok-embed" ...> で問題なく表示できていました。しかし多くのユーザーは スマホのTikTokアプリから「共有→コピー」で得られる短縮URL を貼っており、表示されない不具合が多発したのです。


🧪 最初の対策:HEADリクエストで短縮URLの展開を試みる

まずは Next.js の API Route (/api/resolve-tiktok-url) を作り、短縮URLを最終的な動画URLに展開する方法を検討しました。

const res = await fetch(url, { method: 'HEAD', redirect: 'follow' });
const resolvedUrl = res.url;

このように fetch(..., { method: 'HEAD' }) にすれば軽量にリダイレクト先を取得できる…はずでした。しかし問題がここで発生します。


❌ 失敗①:HEADリクエストではリダイレクト後のURLが得られない

実際には res.url が期待どおりの tiktok.com/video/... にはならず、場合によっては中途半端なURLになったり、403で失敗することもありました。なぜなら、TikTokの短縮URLはHEADリクエストでのリダイレクトを明示的にブロックしている場合があるからです。

この方法では一部の端末・リンクでは成功しても、他の環境では失敗する不安定な結果になりました。


🔁 再挑戦:GETメソッド + redirect: 'manual' で対応

次の試みでは、fetch()のメソッドをGETにし、リダイレクトを明示的に処理する方法に切り替えました。

const res = await fetch(url, {
method: 'GET',
redirect: 'manual',
});

const location = res.headers.get('location'); // ← これがリダイレクト先

これにより、TikTokが返す302レスポンスの Location ヘッダーから、展開後の完全なURLを取得できるようになりました。


✅ 成功の決め手:TikTokの短縮URLを展開して resolvedUrl として返す

最終的なAPIコードは以下のようになりました:

export async function POST(req: NextRequest) {
const { url } = await req.json();

try {
const res = await fetch(url, {
method: 'GET',
redirect: 'manual',
});

const location = res.headers.get('location');
const resolvedUrl = location || res.url;

if (!resolvedUrl.includes('tiktok.com/video/')) {
return NextResponse.json({ error: 'TikTok動画URLではありません' }, { status: 400 });
}

return NextResponse.json({ resolvedUrl });
} catch (error) {
console.error('🔴 TikTok URL解決エラー:', error);
return NextResponse.json({ error: 'URL解決に失敗しました' }, { status: 500 });
}
}

🎥 フロントエンドの修正:入力欄で自動的に展開する

ユーザーが短縮URLを入力した際、自動的にAPIへPOSTして展開し、正式なURLに置き換えるように実装しました。

if (/^https:\/\/(vt|vm)\.tiktok\.com\//.test(inputUrl)) {
const res = await fetch('/api/resolve-tiktok-url', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url: inputUrl }),
});

const data = await res.json();
if (data.resolvedUrl) {
updated[i] = data.resolvedUrl;
setUrls(updated);
}
}

この対応により、ユーザーがどんな形式のTikTokリンクを貼っても、自動的に「埋め込み可能な正式URL」に変換できるようになりました。


💡 追加で対応した問題

1. undefinedが返ってしまう問題

HEADリクエストではリダイレクトが追えず、res.urlが意図しない値になるため、必ずGET + manualにする必要がありました。

2. TikTok以外のURLを入力してしまうケース

例:https://www.researchnester.jp/... など
extractVideoId() 関数で video/123... が見つからない場合は埋め込まないように if (!videoId) return null でスキップ。

3. Permissions Policy Violation エラー

→ TikTokがaccelerometerなど一部センサー系APIを使用する際、クロスオリジン制限がブラウザ側で出ることがありますが、表示上は問題ないため無視可と判断しました。


✅ 最終成果

  • 短縮URL(vt.tiktok.com, vm.tiktok.com)でも、正式なTikTok動画URLに変換して正しく埋め込み表示できるようになった。
  • 最大3件まで登録可能。
  • 表示する / 非表示にする チェックボックスも導入済み。

🔚 まとめ:TikTokの短縮URLには注意を!

TikTokの仕様は日々変化していますが、今回のように「短縮URLのリダイレクト制御」など、通常のWebサービスと少し違う挙動があるため注意が必要です。Procomでは今後も各SNSの仕様変更に追随しながら、ユーザーにとってより快適な表示環境を提供していきます。


✍ 最後に

このような細かなUXの改善を積み重ねることで、Procomは「あなたのすべてを、ここに集約する」SNSリンクプラットフォームとして進化し続けています。
もし開発や実装に興味のある方がいれば、ぜひ一緒にProcomを盛り上げていきましょう!

おすすめの記事