4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

『なければ自分で作ればいい』の精神で,100%ブラウザ完結のセキュアなツールを200個開発した話 〜Googleインデックスとの死闘〜

4
Posted at

『なければ自分で作ればいい』の精神で,100%ブラウザ完結のセキュアなツールを200個開発した話 〜Googleインデックスとの死闘〜

[!IMPORTANT]
※ 本サービスは β版 です.
不具合のご報告や改善のご提案,機能リクエストなどのフィードバックは,お気軽に 公式X(旧Twitter) までお寄せください!


「PDFを結合したい」「画像のファイルサイズを一括で縮小したい」「JWTトークンをデコードしたい」

日々の開発や業務の中で,こうした「ちょっとしたデータ処理や変換」が発生することは日常茶飯事です.ネットで検索すれば,無料のオンラインツールがいくらでも見つかります.

しかし,個人情報が含まれるファイルや,本番環境の認証キー,社外秘のソースコードを扱うとき,アップロードボタンを押す直前に手が止まったことはありませんか?

このデータ,サーバーに送られて保存されてないよな……?

セキュリティポリシーが厳しい企業では,未許可のサードパーティサーバーへデータを送信すること(シャドーIT)自体が禁止されていることも多いはずです.

「安全で,広告がうるさくなくて,登録不要で,かつ爆速で使えるツール集が欲しい」
しかし,ネットを探しても「本当にデータを収集していない」と証明できるツールは見つかりませんでした.

なければ,自分で作ればいい

そう思い立ち,サーバー送信一切なし,100%クライアントサイド(ブラウザ内)だけで完結するセキュアな便利ツール集『ZeroTools(ゼロツールズ)』を開発しました.気がつけば,実装したツールは202個に達していました.

今回は,このツールの設計思想や「200個作りきるまでの泥臭い開発話」,そして個人開発者が直面した「インデックスされない!Google SEOとの死闘」について共有したいと思います.


🛠️ 1. 「オフラインでも動く」完全ローカル完結の設計思想

ZeroToolsの最大の特徴は,「すべての演算をユーザーのブラウザ(V8エンジン等)のメモリ内だけで実行する」という点です.データが外部サーバーへアップロードされることは1バイトもありません.

実際,一度ページを開いてしまえば,LANケーブルを抜いてオフライン(機内モード)にしても,すべてのツールがそのまま動作し続けます.

これを実現するために,以下のようなモダンなWeb APIや技術をフル活用しました.

  • バイナリ・ファイル操作: FileReader APICanvas API を活用し,ローカルでの画像リサイズやPDF編集を実装.
  • 高速な暗号化計算: Web Crypto API を使い,機密テキストの暗号化やハッシュ計算(SHA-256など)をブラウザ上で実行.
  • webrtcやネットワーク検査: local IP の検出など,ブラウザに閉じたネットワークAPIを使用.
  • ネイティブ級の処理能力: C言語やRustで書かれた高度なライブラリを WebAssembly (Wasm) にコンパイルしてブラウザにロード.

データ処理におけるデータフローの比較は以下の通りです.

■ 従来のツール(サーバー処理型)
[あなたのブラウザ] ➔ (機密ファイルを送信) ➔ [他社の外部サーバー(変換処理・保管)] ➔ [結果をダウンロード]

■ ZeroTools(完全ローカル完結型)
[あなたのブラウザ] ➔ (ファイルを読み込み) ➔ [ブラウザのメモリ内(JS/Wasmで処理)] ➔ [即時保存]

例えば,以下は実際に使用している,外部サーバーと一切通信せずにブラウザ上で安全にハッシュ値を計算するコードの抜粋です.

/**
 * ブラウザ標準の Web Crypto API を用いて
 * 外部通信を一切発生させずに SHA-256 ハッシュ値を計算
 */
async function generateSHA256Locally(text: string): Promise<string> {
  const encoder = new TextEncoder();
  const data = encoder.encode(text);
  
  // ブラウザに組み込まれた安全な暗号化APIでハッシュを計算 (外部へのPOST送信なし)
  const hashBuffer = await crypto.subtle.digest("SHA-256", data);
  
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  const hashHex = hashArray
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");
    
  return hashHex;
}

「本当にデータが送信されていないか?」を確かめたいギークの方は、Chromeのデベロッパーツール(F12)の「Network」タブを開いた状態でファイル変換を行ってみてください。アップロードの通信が一切発生していない様子が目視で確認できます.


⏳ 2. 「ツール200個ノック」という地獄の泥臭い開発プロセス

「200個以上のWebアプリを一人で作りきる」というのは,構成や設計面で多くの壁に突き当たりました.

PDF編集,画像処理,JSON/SQL整形,正規表現テスターといったエンジニア向けツールから,手取り・ローン・消費税計算器といったビジネス計算ツールまで,実装すべき仕様は多岐にわたります.

  • UI/UXの一貫性: 各ツールのレイアウトや操作感を統一しつつ,レスポンシブ対応を徹底.
  • WebAssemblyのロード遅延: 大容量のWasmファイルをどう軽量化し,処理開始時のレイテンシを下げるか.
  • ローカルメモリの制御: ブラウザ上で巨大なPDFや画像を一括処理する際,タブがクラッシュ(OOM)しないよう,GC(ガベージコレクション)を意識したメモリバッファの解放処理.

毎日仕事を終えてからの数時間と週末のすべてをコーディングに捧げ,ひたすら仕様を調べ,Next.js + TypeScriptでコンポーネントを量産し続けました.


📈 3. 作ってからが本番だった:Google SEO & AdSense審査との死闘

「良いツールを200個作った.安全だし,爆速.これでみんな使ってくれるはず!」
……しかし,本当の地獄はデプロイした後に待っていました.

Google Search Console(GSC)のステータス画面を見て私は絶望しました.

500ページ以上アップロードしているのに,登録数が360ページあたりで完全に頭打ちになっている……!

さらに,Google AdSenseの審査結果は非情にも「有用性の低いコンテンツ(質の低いコンテンツ)」として不合格.
ここから,個人開発者としてのGoogle検索エンジンとの泥泥の戦いが幕を開けました.調査を進める中で,数々の「やらかし」と「検索エンジンの仕様」が浮き彫りになってきたのです.

死闘①:全202ツールに露出した「コピペ定型文バグ」との戦い

GSCでインデックスされず,AdSenseに弾かれた最大の原因は,信じられないケアレスミスでした.
全ツールの品質向上のために用意した「本ツールのセキュリティと『完全ローカル動作』の仕組み」という約1,500文字の共通SEO解説セクションにおいて,プログラムの置換バグにより,ほぼすべてのツールの説明文の中に,

「『年齢・西暦和暦早見表』に入力したデータやファイルの処理は……」

という「年齢早見表」向けの解説テキスト(誤表記)がそのままハードコードで露出してしまっていたのです.
Googleのクローラーから見れば,「200以上のページに,全く同じ誤表記を含む長文テキストが使い回されている,独自性の極めて低いコピーコンテンツの温床」と判定されて当然の状態でした.

【解決策】
自動置換バッチスクリプトを作成・実行し,全ツールの誤表記を各ツールの「正式名称」に動的にマッピング・置換.さらに,重複コンテンツ判定を完全に回避するため,ツールの特性に応じて3パターンに揺らしを加えた解説文章(数値用,ファイル用,暗号・デベロッパー用)を適用し,395ページ分(日・英)の全テキストを完全に再生成しました.

死闘②:多言語(ja ⇔ en)ペア判定の「非対称hreflang」問題

グローバル展開を狙い,日本語202ツールに加えて英語193ツールの並行静的ディレクトリ(/en/tools/[tool-id]/)を用意しました.
しかし,Googleのインデックス状況を見ると,英語ページの多くが「重複コンテンツ」としてインデックスから除外されていました.

原因は,「日本語ページから英語ページへの hreflangalternates)リンク」の指定が抜け落ちていたこと
Googleは,多言語アソシエーション(ja ⇄ en)が双方向に1対1で正しく記述されていない場合,言語の切り替えバリエーションとして扱わず,「単なる同一ツールの重複(コピー)URL」とみなして一方を排除します.

【解決策】
Next.jsのメタデータジェネレータ(sitemap.ts および各ページのテンプレート)をリファクタリング.日本専用ツール(10件)を除くすべてのツールページにおいて,双方向の alternates.languagesjaen のマッピング)がHTMLの <head> 内に完全に出力されるよう修正しました.
実際にビルドされた HTML 上で,

<link rel="canonical" href="https://usezerotools.com/tools/random-picker/"/>
<link rel="alternate" hrefLang="ja" href="https://usezerotools.com/tools/random-picker/"/>
<link rel="alternate" hrefLang="en" href="https://usezerotools.com/en/tools/random-picker/"/>

と出力されていることを確認した瞬間は,小さくガッツポーズが出ました.

死闘③:Next.js特有の「末尾スラッシュ307リダイレクト」の罠

GSCの「クロール済み - インデックス未登録」を解析すると,多くのブログ記事やツールがそこに放り込まれていました.

原因をログから調べたところ,Next.jsの trailingSlash: true(静的ビルド時のフォルダ出力設定)に対して,サイトマップに末尾スラッシュなしのURL(例:/why-zerotools-is-safe)を逆に入れていたことが判明.
クローラーがアクセスするたびに,Next.jsが /why-zerotools-is-safe/(スラッシュあり)へ 307 Temporary Redirect をかけていたため,クローラーの巡回バジェット(予算)を無駄に浪費し,インデックス登録が保留されていました.

【解決策】
サイトマップ生成スクリプトおよび内部リンクの定義を徹底的に精査し,すべてのURLの末尾をスラッシュ付き(/)に完全統一.無駄なリダイレクトをゼロにしてクローラーの回遊率を高めました.

死闘④:HTTPとHTTPSの競合による「正規URL・ユーザー未指定」エラー

同じページがHTTPとHTTPSの双方でステータス 200 OK でアクセス可能な状態になっていたため,Googleが「どちらが本物のURLか分からない」と判断し,インデックスから弾かれていました.

【解決策】
CloudflareのDNS/CDN設定をチューニングし,Always Use HTTPS を有効化.HTTPリクエストに対して 301 Moved Permanently を返し,HTTPSへ恒久転送するよう徹底しました.

死闘⑤:サイトマップと noindex の矛盾警告

アクセス数を伸ばすため,西暦別の履歴書早見表(70ページ)などのプログラム自動生成ページ(Programmatic SEO)を作ってサイトマップに登録していました.
しかし、開発時のテスト設定で,これらのページに robots: { index: false } が設定されたままになっていました.

これにより,Googleから「サイトマップでインデックスしてくれと言いながら,ページ上では拒否している」という不整合エラーを吐かれ,サイト全体のクロール優先度が落とされていました.

【解決策】
本来 noindex であるべきページ群(計75ページ)を,サイトマップ(sitemap.xml)の出力リストから完全に排除するクレンジングを実施.送信URL数を「本当にインデックスされたい462件」にスリム化しました.


📈 4. 奇をてらわない.泥臭く積み重ねた「初期SEO&集客戦略」のすべて

「作ったけれど誰も来ない」という個人開発の最難関を突破するため,私たちは小手先のSEOではなく,地道で泥臭い施策を一つずつ積み重ねてきました.

施策①:現在も日・英で書き続けている「お役立ち解説ブログ」

ただツールページを並べるだけでは,ドメイン全体の専門性をGoogleに評価してもらうのは困難です.そこで,ツールに関連する実用的なテーマ(例:「時給換算のルール」「割り勘の端数処理のコツ」など)の解説ブログを,日本語・英語の両方で現在も執筆し続けています.
ブログ記事から各ツールへ自然な内部リンクを繋ぎ,巡回するクローラーとユーザーの双方にとって「深いテーマ性を持ったドメイン」であることを学習させています.

施策②:家族や友人を巻き込んだ,泥臭い「初期UXシグナル」の獲得

初期のドメインパワーが弱い段階で,Googleに「このサイトは有益だ」と判定してもらうためには,実際のユーザー行動データが不可欠です.
私たちは,家族や友人にツールの使用をお願いする際,単に直接のURLを送るのではなく,あえて「『割り勘 端数』や『西暦早見表』といった狙っているキーワードで実際にGoogle検索し,検索結果の中からZeroToolsを探し出してアクセスしてほしい」という泥臭い頼み方をしました.
さらに,サイトに入った後も実際に数分間ツールを操作してもらうことで,初期段階から「極めて直帰率が低く,滞在時間の長い(エンゲージメントの高い)良質なUXシグナル」を検索エンジンに蓄積し続けました.

施策③:Search Consoleデータに基づく「メタタイトル・説明文」の最適化と差し戻し

サイトへのアクセスが微増し始めた段階で,Google Search Consoleのクエリ分析を行い,「検索結果に表示されているのに,クリック率(CTR)が悪いページ」を洗い出しました.
調査の結果,英語名のタイトルや無機質なツール名のまま放置されていたページが多く,ユーザーの検索意図に適合していないことが判明しました.

そこで,一括置換プログラムを作成し,主要な30以上のツールに対して,クリックされやすい具体的な日本語タイトル(例:【定額・定率法】減価償却費計算シミュレーター・計算サイト【簡単・端数調整】割り勘&傾斜配分計算ツール など)とキーワードをマッピングして一斉適用しました.

また,タイトルに「【無料・安全】」といった過剰な冠詞を一律でドッキングした結果,逆に検索評価が下がりアクセスが急落する主要ツールが発生した際は,即座に「過去最も検索順位が安定していたオリジナルのタイトル・説明文」へとピンポイントで差し戻し・復元するという,Search Console of データと睨めっこしながらの微調整(チューニング)を泥臭く繰り返しました.
さらに,メタ説明文(description)の末尾に同じ定型句が並んで重複ペナルティを受けるリスクを防ぐため,末尾の説明文を5パターンに自動で「揺らす」ロジックも実装しています.

施策④:Qiita・Zennへの技術アウトプットによるドメインパワーのハック

新規ドメインに決定的に不足している「外部からの信頼(被リンク)」を獲得するため,開発の過程で得たフロントエンドの技術的知見や,完全ローカル動作のセキュリティ設計のこだわりを,QiitaやZennといった外部技術プラットフォームで記事として発信しました.

というか今書いてます.

同じエンジニアや開発者に向けてアウトプットを共有することで,自然な形で信頼性の高い良質な外部リンク(被リンク)が集まり,ドメインの検索順位を底上げする強力な土台を作ることができました.


🔮 5. 今後の展望:とにかく不労所得がほしい……!!

これらのSEO格闘記を経て,現在は以下のような「健全なインデックス設計」に落ち着きました.

  • インデックスさせたい(インデックス許可)ページ: 460ページ
    (日本語ツール202,英語ツール193,ブログ36,カテゴリ・静的29)
  • サイトマップ送信数: 462件
  • 意図的にインデックスから外すページ: 77ページ(noindex化完了)

現在,この修正版がデプロイされ,Googleによる再クロールが進んでいます.ここから1ヶ月程度でインデックス数が400以上に回復することを見込んでおり,それが安定したタイミングでGoogle AdSenseの申請に再挑戦する予定です.

正直なところ,個人開発者として「とにかく不労所得がほしい……!!」という強い想いがあります.サーバー代がほぼゼロで運用できるこのサイトを活かし,まずは【月収1万円】の収益を安定して生み出せるようになることを最初の目標に設定し,一歩ずつ育てていくつもりです.


💬 6. おわりに:フィードバックをお待ちしております!

長々と泥臭い開発とSEOの格闘記を書いてしまいましたが,ZeroToolsは現在 β版 として公開したばかりです.

「このツールをローカル版で追加してほしい!」というアイデアや、「スマホだとここが使いにくい」「こんなバグを見つけた」といったご意見がありましたら,ぜひ私の 公式X(旧Twitter) のDMまでお気軽にメッセージをお送りください!

個人開発者の方や,実務でセキュリティ制限に悩まされている方の作業効率が,少しでも上がれば幸いです.

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?