← 記事に戻る
# LLMO対策の前手順として、マークダウン記法を施しました.

おはようございます.LLMO対策の前手順として、マークダウン記法を施しました.シングルページにマークダウン記法のリンクがそれぞれの記事にあると思います.

そのリンクをクリックするとマークダウン記法が表示されます.LLMO設置後、LLMs.txtを設置すれば良いらしいので、そちらも近日中に対応する予定です.尚、この記事がUPされている頃にはLLMs.txtの設置が終わっている気もします.

追伸:LLMs.txtの設置が終わりました、ルートに設置しています.LLMs.txtはマークダウン記法が記載されているURL(リンク)を一行ずつ表示するような形式で良いらしいです.

これをチャッピーさんにプラグインにして貰いましたのでお裾分けです.下記のプラグインを導入すると全記事URL(パラメーター(マークダウン記法と認識させる))が発行されます.

※マークダウン記法したページはご自身で作る必要があります.

```
<?php
/*
Plugin Name: LLMS URL Exporter (Fixed)
Description: 公開記事のURLをuploads/llms.txt に日付降順で出力します。管理画面のボタンで非同期(AJAX)実行。新規公開時は先頭に追記。
Version: 1.1
Author: taoka toshiaki
*/

if ( ! defined( 'ABSPATH' ) ) exit;

class LLMS_URL_Exporter {
    private $file;

    public function __construct() {
        $this->file = $_SERVER['DOCUMENT_ROOT'] . '/llms.txt';

        add_action( 'admin_menu', [ $this, 'add_admin_page' ] );
        add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_script' ] );

        // AJAX (管理画面からの呼び出し = ログインユーザー用)
        add_action( 'wp_ajax_llms_generate_urls', [ $this, 'generate_urls' ] );

        // 投稿が公開になったとき(状態遷移を監視)
        add_action( 'transition_post_status', [ $this, 'on_transition_post_status' ], 10, 3 );

        register_activation_hook( __FILE__, [ $this, 'create_file_on_activate' ] );
    }

    public function create_file_on_activate() {
        $dir = dirname( $this->file );
        if ( ! is_dir( $dir ) ) {
            wp_mkdir_p( $dir );
        }
        if ( ! file_exists( $this->file ) ) {
            @file_put_contents( $this->file, "" );
        }
    }

    public function add_admin_page() {
        add_menu_page(
            'LLMS URL Exporter',
            'LLMS Export',
            'manage_options',
            'llms-url-exporter',
            [ $this, 'admin_page_html' ]
        );
    }

    public function enqueue_admin_script( $hook ) {
        // 管理画面の当該ページだけに読み込む
        if ( $hook !== 'toplevel_page_llms-url-exporter' ) return;

        // jQuery は管理画面に既に存在
        wp_enqueue_script( 'llms-admin', plugins_url( 'llms-admin.js', __FILE__ ), [ 'jquery' ], '1.0', true );

        wp_localize_script( 'llms-admin', 'LLMS_Ajax', [
            'ajax_url' => admin_url( 'admin-ajax.php' ),
            'nonce'    => wp_create_nonce( 'llms_generate_urls_nonce' ),
        ] );

        // もし外部ファイルを用意しないなら、admin_page_html 内の inline script がフォールバックになります。
    }

    public function admin_page_html() {
        ?>
        <div class="wrap">
            <h1>LLMS URL Exporter</h1>
            <p>公開中の全投稿URLを /llms.txt に日付降順で書き出します。</p>
            <button id="llms-generate-btn" class="button button-primary">全記事URLを書き出す</button>
            <div id="llms-result" style="margin-top:12px;"></div>
        </div>
        <?php
        // フォールバック用のインラインスクリプト(もし外部 JS を作らない場合に有効)
        $nonce = wp_create_nonce( 'llms_generate_urls_nonce' );
        $ajax_url = admin_url( 'admin-ajax.php' );
        ?>
        <script type="text/javascript">
        jQuery(function($){
            $('#llms-generate-btn').on('click', function(){
                var $res = $('#llms-result');
                $res.text('処理中...');

                var data = {
                    action: 'llms_generate_urls',
                    _ajax_nonce: (typeof LLMS_Ajax !== 'undefined' ? LLMS_Ajax.nonce : '<?php echo esc_js( $nonce ); ?>')
                };
                var url = (typeof LLMS_Ajax !== 'undefined' ? LLMS_Ajax.ajax_url : '<?php echo esc_js( $ajax_url ); ?>');

                $.post(url, data, function(response){
                    if ( response && response.success ) {
                        $res.html( response.data.message );
                    } else if ( response && response.data && response.data.message ) {
                        $res.html('エラー: ' + response.data.message);
                    } else {
                        $res.html('不明なレスポンス: ' + JSON.stringify(response));
                    }
                }).fail(function(jqXHR, textStatus, errorThrown){
                    $res.html('AJAX エラー: ' + textStatus + ' ' + errorThrown + ' (status: ' + jqXHR.status + ')');
                });
            });
        });
        </script>
        <?php
    }

    // AJAX ハンドラ
    public function generate_urls() {
        // nonce と権限チェック
        check_ajax_referer( 'llms_generate_urls_nonce', '_ajax_nonce' );
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => '権限がありません。' ], 403 );
        }

        $args = [
            'post_type'      => 'post',
            'post_status'    => 'publish',
            'orderby'        => 'date',
            'order'          => 'DESC',
            'posts_per_page' => -1,
            'no_found_rows'  => true,
            'fields'         => 'ids',
        ];

        $posts = get_posts( $args );
        $urls = [];
        foreach ( $posts as $pid ) {
            $permalink = get_permalink( $pid );
            if ( $permalink ) $urls[] = $permalink.'?md=1';
        }

        $content = implode("\n", $urls);


        $written = @file_put_contents( $this->file, $content );
        if ( $written === false ) {
            $err = error_get_last();
            $msg = isset( $err['message'] ) ? $err['message'] : '不明な書き込みエラー';
            wp_send_json_error( [ 'message' => 'ファイル書き込みに失敗しました: ' . $msg ] );
        }

        wp_send_json_success( [ 'message' => 'llms.txt に ' . count( $urls ) . ' 件のURLを書き出しました。' ] );
    }

    // 公開判定:状態遷移で publish になったときに先頭へ追加
    public function on_transition_post_status( $new_status, $old_status, $post ) {
        if ( $post->post_type !== 'post' ) return;
        if ( $new_status === 'publish' && $old_status !== 'publish' ) {
            $url = get_permalink( $post->ID ).'?md=1';

            $current = '';
            if ( file_exists( $this->file ) ) {
                $current = file_get_contents( $this->file );
            }

            // 既存の同一URLがあれば削除して先頭へ
            $lines = array_filter( array_map( 'trim', explode("\n", $current ) ) );
            $lines = array_values( array_diff( $lines, [ $url ] ) );
            array_unshift( $lines, $url );

            $new_content = implode("\n", $lines);

            @file_put_contents( $this->file, $new_content );
        }
    }
}

new LLMS_URL_Exporter();

```



明日へ続く

 [ ![](https://zip358.com/wp-content/uploads/2026/01/image-35.png) AIは能力の鏡だとさ.そうかも知れない.

 ](https://zip358.com/2026/02/08/ai%e3%81%af%e8%83%bd%e5%8a%9b%e3%81%ae%e9%8f%a1%e3%81%a0%e3%81%a8%e3%81%95-%e3%81%9d%e3%81%86%e3%81%8b%e3%82%82%e7%9f%a5%e3%82%8c%e3%81%aa%e3%81%84.html) 

 [ ![](https://zip358.com/wp-content/uploads/2026/01/image-34.png) 考え過ぎずに行動力.逆算出来れば凄いけどね.

 ](https://zip358.com/2026/02/07/%e8%80%83%e3%81%88%e9%81%8e%e3%81%8e%e3%81%9a%e3%81%ab%e8%a1%8c%e5%8b%95%e5%8a%9b-%e9%80%86%e7%ae%97%e5%87%ba%e6%9d%a5%e3%82%8c%e3%81%b0%e5%87%84%e3%81%84%e3%81%91%e3%81%a9%e3%81%ad.html) 

 [ ![](https://zip358.com/wp-content/uploads/2026/01/image-33.png) ネガティブ思考は駄目なのか本当にそう?

 ](https://zip358.com/2026/02/06/%e3%83%8d%e3%82%ac%e3%83%86%e3%82%a3%e3%83%96%e6%80%9d%e8%80%83%e3%81%af%e9%a7%84%e7%9b%ae%e3%81%aa%e3%81%ae%e3%81%8b%e6%9c%ac%e5%bd%93%e3%81%ab%e3%81%9d%e3%81%86%ef%bc%9f.html) 

 [ ![](https://zip358.com/wp-content/uploads/2026/01/image-32.png) 成功体験と成功の模倣.

 ](https://zip358.com/2026/02/05/%e6%88%90%e5%8a%9f%e4%bd%93%e9%a8%93%e3%81%a8%e6%88%90%e5%8a%9f%e3%81%ae%e6%a8%a1%e5%80%a3.html) 

 [ ![](https://zip358.com/wp-content/uploads/2026/01/image-31.png) サイトを分離した話を黙々と書いていきます.

 ](https://zip358.com/2026/02/04/%e3%82%b5%e3%82%a4%e3%83%88%e3%82%92%e5%88%86%e9%9b%a2%e3%81%97%e3%81%9f%e8%a9%b1%e3%82%92%e9%bb%99%e3%80%85%e3%81%a8%e6%9b%b8%e3%81%84%e3%81%a6%e3%81%84%e3%81%8d%e3%81%be%e3%81%99.html)