<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>於是寫下生活筆記</title><link>https://yuslife.cc/coding/</link><description>Recent content in Codings on 於是寫下生活筆記</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><lastBuildDate>Sun, 21 Apr 2024 12:28:00 +0000</lastBuildDate><atom:link href="https://yuslife.cc/coding/index.xml" rel="self" type="application/rss+xml"/><item><title>iPhone 雙卡切換訊號很麻煩？教你如何透過捷徑輕鬆一鍵切換！</title><link>https://yuslife.cc/coding/iphone-switches-signals/</link><pubDate>Sun, 21 Apr 2024 12:28:00 +0000</pubDate><guid>https://yuslife.cc/coding/iphone-switches-signals/</guid><description>從 Apple iPhone XS 支援使用 e-SIM 雙卡開始，許多人可能會因為工作、訊號、資費等各種因素，而同時持有多個門號，然而有時可能會因為住家與工作場合在不同間電信公司</description><content:encoded><![CDATA[<p>從 Apple iPhone XS 支援使用 e-SIM 雙卡開始，許多人可能會因為工作、訊號、資費等各種因素，而同時持有多個門號，然而有時可能會因為住家與工作場合在不同間電信公司間的訊號狀態不同，而會希望能夠切換不同門號的訊號，這時除了點進層層的設定選單中外，其實透過 iPhone 內建的捷徑功能，就可以輕輕鬆鬆達到目的。</p>
<h2 id="設定原理文末有捷徑連結">設定原理（文末有捷徑連結）</h2>
<p>透過 iOS 內建的捷徑，我們可以將 iPhone 數據設定成指定的行動方案，詳細設定如下：</p>
<h3 id="1確定-iphone-行動方案數量">1、確定 iPhone 行動方案數量</h3>
<p>目前的 iPhone 在使用 e-SIM 的情況下可以支援超過 8 組的 e-SIM，雖然這個狀況屬於少數，但在為了通用的情況下，我們先判斷行動方案數量，再扣除目前正在使用的行動方案下，若是數量大於 1，則要顯示列表讓使用者選則要切換的行動方案；反之，若是數量等於 1，則直接切換行動方案到另一組。</p>
<p>在 iOS 的捷徑中，可以使用「尋找使用方案」這個動作，並加入過濾條件，設定為「非目前的行動數據號碼」，以篩選出除了目前使用中的行動方案。</p>
<p>接著使用「計數」來計算前面篩選出來的數量，讓後續能做為判斷使用。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/iphone-switches-signals_01_huc33ce858e93d8b655deda1255a98e457_206076_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/iphone-switches-signals_01_huc33ce858e93d8b655deda1255a98e457_206076_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/iphone-switches-signals_01_huc33ce858e93d8b655deda1255a98e457_206076_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/iphone-switches-signals_01_huc33ce858e93d8b655deda1255a98e457_206076_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<h3 id="2判斷手機中的行動方案數量並做出對應動作">2、判斷手機中的行動方案數量並做出對應動作</h3>
<h4 id="2-1計數小於等於-1">2-1、計數小於等於 1</h4>
<p>在前面篩出數量後，我們要使用「如果」功能，如果計數的結果小於等於 1，代表手機中僅有至多 2 張 SIM 卡在使用，這時候我們要選取剩餘的行動方案，因此使用「從列表取得項目」功能，將變數設為最一開始的「尋找行動方案」，因為這當中只會有一個選項。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/iphone-switches-signals_02_huc33ce858e93d8b655deda1255a98e457_203287_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/iphone-switches-signals_02_huc33ce858e93d8b655deda1255a98e457_203287_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/iphone-switches-signals_02_huc33ce858e93d8b655deda1255a98e457_203287_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/iphone-switches-signals_02_huc33ce858e93d8b655deda1255a98e457_203287_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<h4 id="2-2計數大於-1">2-2、計數大於 1</h4>
<p>如果記入大於 1 時，代表手機中有超過 2 個 SIM 卡方案，因此需要讓使用者選擇他想切換的方案，這時我們使用「從列表中選擇」功能，並將變數設為最一開始的「尋找行動方案」，將所有方案列出讓使用者選取。</p>
<h3 id="3設定行動數據方案">3、設定行動數據方案</h3>
<p>在「結束如果」後，我們使用「設定預設號碼」功能，切換預設變數為「數據」，並將設為結果設定成「如果結果」。</p>
<h3 id="4跳出提示">4、跳出提示</h3>
<p>到前面步驟 3 時，已經順利將行動數據切換成另一個方案，但考量使用者體驗，這時候若是有提示通知已經完成切換，以及切換的方案為何是一個比較恰當的做法，所以我們在這裡先用「文字」功能，輸入提示想出現的文字，例如：「您已切換至&hellip;」，後方則利用變數功能，加入稍早選取的結果，這邊可以視需要加入或調整變數內容，比如：電信業者名稱、手機號碼&hellip;等。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/iphone-switches-signals_03_huc33ce858e93d8b655deda1255a98e457_175151_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/iphone-switches-signals_03_huc33ce858e93d8b655deda1255a98e457_175151_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/iphone-switches-signals_03_huc33ce858e93d8b655deda1255a98e457_175151_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/iphone-switches-signals_03_huc33ce858e93d8b655deda1255a98e457_175151_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>完成文字內容設計後，就可以使用「顯示通知」功能，將變數設為前面規劃好的文字，在最後完成切換後，顯示通知。</p>
<h2 id="捷徑連結底家">捷徑連結底家</h2>
<p>如果真的覺得前面設定流程實在太複雜，給辛苦看到這裡的你一個方便，使用 iPhone 點擊下方連結，快速取得捷徑吧！</p>
<p><a href="https://www.icloud.com/shortcuts/f43b7ef42e01422baa41703e632d1392" title="取得捷徑">&raquo;取得捷徑&lt;&lt;</a></p>
]]></content:encoded></item><item><title>用 ChatGPT + MBTI 打造出高社群擴散的心理測驗網站！</title><link>https://yuslife.cc/coding/chatgpt-mbti-test/</link><pubDate>Sun, 25 Jun 2023 12:14:03 +0000</pubDate><guid>https://yuslife.cc/coding/chatgpt-mbti-test/</guid><description>AI 當道，你真的熟悉 ChatGPT 嗎？本文將透過與 ChatGPT 對話，並搭配 MBTI 人格分析，打造出高度社群擴散力的心理測驗網站！ 首先先來確認 ChatGPT 是否了解 MBTI 模型 考量 ChatGPT 經常給出</description><content:encoded><![CDATA[<p>AI 當道，你真的熟悉 ChatGPT 嗎？本文將透過與 ChatGPT 對話，並搭配 MBTI 人格分析，打造出高度社群擴散力的心理測驗網站！</p>
<h2 id="首先先來確認-chatgpt-是否了解-mbti-模型">首先先來確認 ChatGPT 是否了解 MBTI 模型</h2>
<p>考量 ChatGPT 經常給出錯誤的答案，在一開始先向 ChatGPT 詢問它是否了解 MBTI 人格分析測驗。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-01_hu9a9208e2d9b5132adae167027fa846a1_659599_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-01_hu9a9208e2d9b5132adae167027fa846a1_659599_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-01_hu9a9208e2d9b5132adae167027fa846a1_659599_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/chatgpt-mbti-test-01_hu9a9208e2d9b5132adae167027fa846a1_659599_960x0_resize_box_3.png" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<h2 id="先從簡化後的測驗開始吧">先從簡化後的測驗開始吧</h2>
<p>傳統的 MBTI 測驗題目很多且需要花費不少時間作答，然而考量我們想要建立的是一個快速、高度擴散的測驗網站，題目數自然不能太多，因此我先請 ChatGPT 提供一個 5 題左右的簡易版 MBTI 測驗。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-02_hu86038a83a380fe268786b43a7f8c12de_348628_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-02_hu86038a83a380fe268786b43a7f8c12de_348628_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-02_hu86038a83a380fe268786b43a7f8c12de_348628_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/chatgpt-mbti-test-02_hu86038a83a380fe268786b43a7f8c12de_348628_960x0_resize_box_3.png" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>當 ChatGPT 提供了簡易測驗後，我請它說明每一到題目與選項是如何給出最終結果的，確保這個測驗能具有一定的準確性與可信度。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-03_huc4d19ab7060799a09470f8b8a03a754a_575800_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-03_huc4d19ab7060799a09470f8b8a03a754a_575800_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-03_huc4d19ab7060799a09470f8b8a03a754a_575800_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/chatgpt-mbti-test-03_huc4d19ab7060799a09470f8b8a03a754a_575800_960x0_resize_box_3.png" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<h2 id="接著好好包裝一個故事吧">接著好好包裝一個故事吧</h2>
<p>接下來我請 ChatGPT 將前述的測驗包裝成一個情境，這邊我想請他將測驗以受試者是主角，它走入了一個森林中，並將遇到一系列的情境，透過每個情境的抉擇，最終找出它對應的 MBTI 人格。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-04_hud83469a6d9b527b0b8afa981e605308e_488325_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-04_hud83469a6d9b527b0b8afa981e605308e_488325_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-04_hud83469a6d9b527b0b8afa981e605308e_488325_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/chatgpt-mbti-test-04_hud83469a6d9b527b0b8afa981e605308e_488325_960x0_resize_box_3.png" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>在 ChatGPT 幫我設計完情境後，我希望它能幫我將 MBTI 的 16 型人格分別給予對應的 16 種動物，以做為整個測驗的結果，同時要求 ChatGPT 提供對應的描述。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-05_hua4a5ece75c0a4ff7eb013b74ff750e99_469813_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-05_hua4a5ece75c0a4ff7eb013b74ff750e99_469813_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-05_hua4a5ece75c0a4ff7eb013b74ff750e99_469813_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/chatgpt-mbti-test-05_hua4a5ece75c0a4ff7eb013b74ff750e99_469813_960x0_resize_box_3.png" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>除了對應的描述外，我還希望這些動物具有能力值，因此請 ChatGPT 依照活躍度、領導力、智慧值、力量值、敏捷度這 5 個象限，從 1 - 10 分個別給予能力值。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-06_hu083af509fc292170a29f21fd4d6c1bb6_283739_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-06_hu083af509fc292170a29f21fd4d6c1bb6_283739_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-06_hu083af509fc292170a29f21fd4d6c1bb6_283739_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/chatgpt-mbti-test-06_hu083af509fc292170a29f21fd4d6c1bb6_283739_960x0_resize_box_3.png" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>在整個包裝的最後，我請 ChatGPT 提供一段故事引言，並提供一個標題。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-07_hueaa4086782ee67094c7275948eb3bd03_638731_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-07_hueaa4086782ee67094c7275948eb3bd03_638731_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-07_hueaa4086782ee67094c7275948eb3bd03_638731_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/chatgpt-mbti-test-07_hueaa4086782ee67094c7275948eb3bd03_638731_960x0_resize_box_3.png" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-08_huf8fec16663f540ba03824c7d30ae074b_54162_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-08_huf8fec16663f540ba03824c7d30ae074b_54162_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-08_huf8fec16663f540ba03824c7d30ae074b_54162_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/chatgpt-mbti-test-08_huf8fec16663f540ba03824c7d30ae074b_54162_960x0_resize_box_3.png" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<h2 id="接著開始寫成網站吧當然還是-chatgpt-來寫">接著開始寫成網站吧！當然還是 ChatGPT 來寫</h2>
<p>首先，先請 ChatGPT 將前面討論的內容轉化成為一個 Html 與 Javascript 的網站，並告訴 ChatGPT 網站的流程與邏輯。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-09_hua705714d08e41ecc4ca988ebe8d025cc_380371_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-09_hua705714d08e41ecc4ca988ebe8d025cc_380371_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-09_hua705714d08e41ecc4ca988ebe8d025cc_380371_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/chatgpt-mbti-test-09_hua705714d08e41ecc4ca988ebe8d025cc_380371_960x0_resize_box_3.png" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>在第一次提供的程式碼可以發現，並沒有將測驗內容放入程式碼中，因此我請 ChatGPT 將內容填入。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-10_huc18dc42b3b479185e99bcf350e10804f_241869_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-10_huc18dc42b3b479185e99bcf350e10804f_241869_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-10_huc18dc42b3b479185e99bcf350e10804f_241869_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/chatgpt-mbti-test-10_huc18dc42b3b479185e99bcf350e10804f_241869_960x0_resize_box_3.png" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>而在這過程中可以發現 ChatGPT 經常性的發生「失憶」現象，因此除了不斷提醒之外，也可以嘗試直接將前面生成的內容複製貼上提供給 ChatGPT。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-11_hu707eaa4db2842428a3b99cbd7a28f907_398780_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-11_hu707eaa4db2842428a3b99cbd7a28f907_398780_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-11_hu707eaa4db2842428a3b99cbd7a28f907_398780_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/chatgpt-mbti-test-11_hu707eaa4db2842428a3b99cbd7a28f907_398780_960x0_resize_box_3.png" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>在這過程中，我們可以將 ChatGPT 所提供的程式碼貼至 Codepen 等網站中，快速測試程式碼是否正常運作。</p>
<p>若發現無法運作，可以將狀況甚至是 Console（主控台）中報的錯誤提供給 ChatGPT 進行修正。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-12_hu96455d76b8e8239878d9c1e102c03eb4_183801_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-12_hu96455d76b8e8239878d9c1e102c03eb4_183801_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/chatgpt-mbti-test-12_hu96455d76b8e8239878d9c1e102c03eb4_183801_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/chatgpt-mbti-test-12_hu96455d76b8e8239878d9c1e102c03eb4_183801_960x0_resize_box_3.png" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<h2 id="最終成果">最終成果</h2>
<p>最後，在多次嘗試與 ChatGPT 對話與修正之下，終於完成了這個網站。</p>
<p>大家若有興趣的話可以到「<a href="https://animaltest.yuslife.cc/">這裡</a>」來玩玩看。</p>
<p>（小提醒：文章截圖為方便說明，有部分為事後撰文時的對話，可能與實際網頁及原始對話不同，詳細可參考下方對話過程；另網頁部分程式碼非由 ChatGPT 撰寫，而是由筆者修正調整。）</p>
<ul>
<li>範例網站：<a href="https://animaltest.yuslife.cc/">https://animaltest.yuslife.cc/</a></li>
<li>程式原始碼：<a href="https://github.com/chenghanxyu/mbti-test">https://github.com/chenghanxyu/mbti-test</a></li>
<li>與 ChatGPT 對話過程：<a href="https://chat.openai.com/share/2e954a3d-5355-46fb-82dc-eb1696eb8e10">https://chat.openai.com/share/2e954a3d-5355-46fb-82dc-eb1696eb8e10</a></li>
</ul>
]]></content:encoded></item><item><title>用 Google Sheet + Google App Script 打造網頁計數器</title><link>https://yuslife.cc/coding/google-app-script-article-pageview/</link><pubDate>Fri, 09 Dec 2022 12:00:00 +0000</pubDate><guid>https://yuslife.cc/coding/google-app-script-article-pageview/</guid><description>過去本站無論是全站瀏覽數或是單篇文章的瀏覽數，都是透過 Google Analytics 搭配 Google Sheets 串接提供的，主要是參考前輩 August 大大的文章更改而成，但上述的方法將會在明年 7 月</description><content:encoded><![CDATA[<p>過去本站無論是全站瀏覽數或是單篇文章的瀏覽數，都是透過 Google Analytics 搭配 Google Sheets 串接提供的，主要是參考前輩 August 大大的<a href="https://www.letswrite.tw/ga-spreadsheet-add-on/" title="用 GA Spreadsheet Add-on 製作網站訪客人數功能">文章</a>更改而成，但上述的方法將會在明年 7 月遇到問題—— Google Analytics 將從通用版全面改為 Google Analytics 4（GA4）。</p>
<p>然而目前 GA4 尚未提供與 Google Sheets 搭配串接的官方外掛（非官方大多須付費），因此筆者便將腦筋動到了 Google 的另一項服務—— Google Apps Script（GAS）上，本文將紀錄筆者如何透過 Google Sheets + Google Forms 紀錄本站瀏覽數，並透過 Google Apps Script 串接將瀏覽數顯示在網站上。</p>
<h2 id="整體流程如何運作">整體流程如何運作？</h2>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-01_hu07c21d16551a1ec421e9603ea25331e7_41904_400x0_resize_q75_h2_box_3.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-01_hu07c21d16551a1ec421e9603ea25331e7_41904_600x0_resize_q75_h2_box_3.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-01_hu07c21d16551a1ec421e9603ea25331e7_41904_960x0_resize_q75_h2_box_3.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-01_hu07c21d16551a1ec421e9603ea25331e7_41904_960x0_resize_box_3.png" alt="運作流程圖"
            class="lazy"  title="運作流程圖"  width="960" height="540">
    </picture>
    
    <figcaption>
        <p>運作流程圖</p>
    </figcaption>
    
</figure></p>
<p>首先，我們會先透過 Google Forms 功能，在所有使用者到訪網站時觸發並記錄下來，將結果回傳到與表單連動的 Google Sheets 中。</p>
<p>接下來，在 Google Sheets 中我們將進行簡單的數據整理，以利後續網頁接收資料時使用，在這裡，便是將 Google Sheets 作為一個小型資料庫使用。</p>
<p>最後，我們透過 Google Apps Script 將 Google Sheets 中的資料變身成為 API，並在網站上串接使用，顯示於網頁前端。</p>
<p>就讓我們開始吧！</p>
<h2 id="先建立紀錄用的-google-表單">先建立紀錄用的 Google 表單</h2>
<iframe src="https://docs.google.com/forms/d/e/1FAIpQLScBtEkMNxQJrrIK0kLJHMOUFnPqWv7Dpa7P36J7BLrGszqJuQ/viewform?embedded=true" width="640" height="600" frameborder="0" marginheight="0" marginwidth="0" style="width: 100%;height: auto;aspect-ratio: 16 / 12;">載入中…</iframe>
<p>在這個表單中，我們要紀錄的是使用者進入的網址，並增加計數，紀錄網只是為了後續可以在個別文章頁面上顯示個別瀏覽數，而計數欄位則是方便後續直接加總。</p>
<p>需要注意的是，這兩個欄位在 Google Forms 上的設定，必須選擇「簡答」，且不可設為必填（參考下圖），這是避免後續傳送資料發生錯誤。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-02_hu231a7e0183de13310075b2e84c8b865f_24779_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-02_hu231a7e0183de13310075b2e84c8b865f_24779_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-02_hu231a7e0183de13310075b2e84c8b865f_24779_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-02_hu231a7e0183de13310075b2e84c8b865f_24779_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>表單題目設定完成後，點選上方「回覆」分頁，並點選「建立試算表」，後續我們會將這個試算表作為小型資料庫來使用。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-03_hue90d7272d7568ea45156237e30f0d316_25476_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-03_hue90d7272d7568ea45156237e30f0d316_25476_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-03_hue90d7272d7568ea45156237e30f0d316_25476_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-03_hue90d7272d7568ea45156237e30f0d316_25476_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<h2 id="將網頁計數透過-google-form-寫入-google-sheet-吧">將網頁計數透過 Google Form 寫入 Google Sheet 吧</h2>
<p>接下來我們回到網站，要來寫 Code 將資料傳入 Google Sheets 中，這部份將會參考同樣是 August 大大的<a href="https://www.letswrite.tw/custom-google-form/" title="完全客製 Google 表單，美化表單樣式">文章</a>來進行。</p>
<p>事實上，這個方法是透過 Google Forms 回傳到後端的端口作為我們要將資料傳入 Google Sheets 的入口，因此必須取得這份表單的：</p>
<ol>
<li>POST 的 URL</li>
<li>各欄位的 name</li>
</ol>
<h3 id="先來取得-post-的-url-吧">先來取得 POST 的 URL 吧</h3>
<p>取得的方式也很簡單，前往稍早建立完成的表單頁面後（可以點擊右上方的預覽前往），點擊右鍵 → 檢查，即可開啟 DevTools 界面。</p>
<p>在此界面中點選右上方「…」符號並選取搜尋，或按下快捷鍵「crtl+F / cmd+F」，並在搜尋欄位中搜尋「&lt;form」。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-04_hu56e3e2ad37df09365391a0bf4a088392_115148_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-04_hu56e3e2ad37df09365391a0bf4a088392_115148_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-04_hu56e3e2ad37df09365391a0bf4a088392_115148_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-04_hu56e3e2ad37df09365391a0bf4a088392_115148_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>在這段程式碼中，會有一個「action=」開頭，後方接著一段網址，將這段網址複製並記錄下來，後面會使用它。</p>
<p>本次所取得的網址如下（本網址為 Demo 用，非實際本站用網址）：</p>
<pre><code>https://docs.google.com/forms/u/0/d/e/1FAIpQLScBtEkMNxQJrrIK0kLJHMOUFnPqWv7Dpa7P36J7BLrGszqJuQ/formResponse
</code></pre>
<h3 id="接下來取得各欄位的-name">接下來取得各欄位的 name</h3>
<p>繼續在網頁右側的 DevTools 中搜尋「entry.」，會看到幾列 &lt;input type=&ldquo;hidden&rdquo; 開頭的程式碼，由上而下會對應到你所建立的表單欄位（依照建立順序而不是顯示順序）。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-05_hu8c12d22a7e7cb18b257212d2eb5b8fb1_69940_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-05_hu8c12d22a7e7cb18b257212d2eb5b8fb1_69940_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-05_hu8c12d22a7e7cb18b257212d2eb5b8fb1_69940_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-05_hu8c12d22a7e7cb18b257212d2eb5b8fb1_69940_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>在程式碼中的「name=」後方內容，就是我們所需要的 name 值，本文範例如下：</p>
<pre><code>entry.1515159479
entry.790304345
</code></pre>
<p>取得這些資訊後，就可以回到網站，準備讓資料記入 Google Sheets 囉！</p>
<h3 id="回到網站準備寫-code">回到網站準備寫 Code</h3>
<p>在這裡，我們需要取得目前網頁的網址，為了方便後續使用，這邊只需要取得網址路徑（Pathname）的部份，可以透過 「location.pathname」來取得。</p>
<pre><code class="javascript">let pageviewUrl = location.pathname;  
// 假設網址為 https://example.com/abc/  
// pageviewUrl 為 /abc/  
</code></pre>
<p>而計數的部份則固定為 1：</p>
<pre><code class="javascript">let pageviewCount = 1;</code></pre>
<p>接下來要將資料透過 $ajax POST 到 Google Forms 上（記得要先引入 jQuery）：</p>
<pre><code class="javascript">let data = {  
    'entry.1515159479': pageviewUrl,  
    'entry.790304345': pageviewCount  
};  
$.ajax({  
    type: 'POST',  
    url: 'https://docs.google.com/forms/d/e/1FAIpQLSeTgHEpVpuV_OHakO-25X-O7I4T1tIzIAUqHWLRvUqG9e6TvQ/formResponse',  
    data: data,  
    contentType: 'application/json',  
    dataType: 'jsonp'  
});</code></pre>
<p>其中，data 裡的 key 就是稍早在 Google Forms 中取得 entry. 開頭的 name，而 url 則是 Google Forms 中取得的 url。</p>
<p>完成後到瀏覽器嘗試載入網頁，應該就可以發現 Google Sheets 中出現此筆資料了。</p>
<iframe src="https://docs.google.com/spreadsheets/d/e/2PACX-1vRbg3G_CI8PU6e4L-nX2dgeNPwrCy_YQSJWgB5dPoGgnrsJPgtFYz75FvJ7yL6_NakamUFJRxb8a3Ht/pubhtml?gid=1221490765&single=true&widget=true&headers=false" width="600" height="120" frameborder="0" marginheight="0" marginwidth="0" style="width: 100%;height: auto;aspect-ratio: 16 / 4;overflow: hidden;"></iframe>
<h2 id="將-google-sheets-作為資料庫使用">將 Google Sheets 作為資料庫使用</h2>
<p>接著回到 Google Sheets，我們要透過 Google Apps Script 將資料傳輸給網頁使用，但在使用前你會發現 Google Sheets 中的資料是分開一筆一筆紀錄的，但我們在實際使用上會希望是呈現不同頁面累積的流量，因此需要先在 Google Sheets 中進行基本處理。</p>
<h3 id="透過-query-函式快速整理資料">透過 QUERY 函式快速整理資料</h3>
<p>首先，先在 Google Sheets 中建立一個新分頁，我們將他命名為「Pageview」。</p>
<p>接著，這邊將會使用到 Google Sheets 的一個函式「QUERY」，這是一個可以在 Google Sheet 中方便使用 SQL 資料庫語法的函式，在進行較複雜的資料整理時相當有用，而 QUERY 的函式使用方式可參考<a href="https://support.google.com/docs/answer/3093343?hl=zh-Hant" title="對多筆資料執行 Google Visualization API Query Language 查詢作業。">官方說明</a>。</p>
<p>QUERY 函式用法：</p>
<pre><code>=QUERY(資料範圍,SQL 語法,標題[選填])
</code></pre>
<p>而在這次的資料中，我們需要的是表單回應裡的網址與計數兩欄，其中計數欄會希望是加總後的結果，因此在 Pageview 分頁中的 A1 儲存格中輸入如下公式：</p>
<pre><code>=QUERY('表單回應 1'!B:C,&quot;select B,sum(C) group by B order by sum(C) desc&quot;)
</code></pre>
<p>在 SQL 語法部份，Google Sheets 的 QUERY 函式不像一般 SQL 可以使用表頭來選取資料，而是要使用絕對位置的欄位來選取，各內容說明如下：</p>
<ul>
<li>select B, sum(C)：指將 B 欄與加總後的 C 欄選取出來。</li>
<li>group by B：因為有使用 sum 函式，必須透過 group by 來告訴系統資料的分組方式，這邊選擇 B 欄也就是網址來進行分組。</li>
<li>order by sum(C) desc：以 sum(C) 的結果遞減排序。</li>
</ul>
<p>資料進行處理後你將會得到如下的表單：</p>
<iframe src="https://docs.google.com/spreadsheets/d/e/2PACX-1vRbg3G_CI8PU6e4L-nX2dgeNPwrCy_YQSJWgB5dPoGgnrsJPgtFYz75FvJ7yL6_NakamUFJRxb8a3Ht/pubhtml?gid=179157578&single=true&widget=true&headers=false" width="600" height="120" frameborder="0" marginheight="0" marginwidth="0" style="width: 100%;height: auto;aspect-ratio: 16 / 4;overflow: hidden;"></iframe>
<h3 id="用-google-apps-script-取得-google-sheets-的資料">用 Google Apps Script 取得 Google Sheets 的資料</h3>
<p>Google Apps Script 是由 Google 開發的腳本平台（Scripting Platform），支援使用 JavaScript 撰寫程式碼，除了可以串連 Google 文件、試算表等工具外，妥善使用甚至能作為輕量後端。</p>
<p>而 Google Apps Script 免費的額度是一天 2 萬次，因此對於小流量的網站基本上是相當足夠的。</p>
<h4 id="前往-google-apps-script-撰寫程式碼">前往 Google Apps Script 撰寫程式碼</h4>
<p>要前往 Google Apps Script，可以在 Google Sheets 上方選單選取「擴充功能」→ 「Apps Script」。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-06_hu73049170e172038e5f562c8eee6a9b98_26055_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-06_hu73049170e172038e5f562c8eee6a9b98_26055_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-06_hu73049170e172038e5f562c8eee6a9b98_26055_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-06_hu73049170e172038e5f562c8eee6a9b98_26055_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>開啟 Google Apps Script 後，就可以開始進行程式碼的撰寫了。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-07_huba052656d30312b6fa5dfb7fc336e662_64980_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-07_huba052656d30312b6fa5dfb7fc336e662_64980_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-07_huba052656d30312b6fa5dfb7fc336e662_64980_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-07_huba052656d30312b6fa5dfb7fc336e662_64980_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<h4 id="獲取-google-sheets-資料">獲取 Google Sheets 資料</h4>
<p>首先，要先讓 Google Apps Script 能讀取 Google Sheets 的資料，透過以下公式可以取得資料，並將資料轉為陣列形式。</p>
<pre><code class="javascript">var ss = SpreadsheetApp.getActiveSpreadsheet();  // 設定要取得資料的文件  
var sheet = ss.getSheetByName("Pageview");       //要取得資料的分頁名稱  
var range = sheet.getRange("A:B");               // 設定資料範圍  
var data = range.getValues();                    // 取得資料陣列</code></pre>
<p>在這裡我們可以在預設的 myFunction() 中，透過 console.log(); 的方式看一下獲取的資料內容，程式碼如下：</p>
<pre><code class="javascript">function myFunction() {  
    console.log(data);  
}</code></pre>
<p>點選畫面上方的「執行」，首次將會跳出授權畫面，點選「審查授權」。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-08_hu77f5ad15006e351d158622ff585502be_84758_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-08_hu77f5ad15006e351d158622ff585502be_84758_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-08_hu77f5ad15006e351d158622ff585502be_84758_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-08_hu77f5ad15006e351d158622ff585502be_84758_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>點選後會跳出警示畫面，因為這個應用程式是我們自己寫的，因此可以放心按下下方的「前往」，並選擇要授權的 Google 帳號（目前登入使用的）。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-09_hu365933289face04955e69e7348a201cb_47771_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-09_hu365933289face04955e69e7348a201cb_47771_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-09_hu365933289face04955e69e7348a201cb_47771_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-09_hu365933289face04955e69e7348a201cb_47771_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>取得授權後，下方執行記錄就會列出我們所選取的資料陣列內容。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-10_hu64f96f4e704dde2785b1e888939da417_42660_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-10_hu64f96f4e704dde2785b1e888939da417_42660_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-10_hu64f96f4e704dde2785b1e888939da417_42660_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-10_hu64f96f4e704dde2785b1e888939da417_42660_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<h3 id="將資料以-json-形式提供給網站">將資料以 Json 形式提供給網站</h3>
<p>Google Apps Script 取得 Google Sheets 的資料後，我們要再將資料轉成 Json 形式，讓網站能順利讀取。</p>
<p>而 Google Apps Script 的資料要能夠對外發送，必須透過一個特別的函式 doGet() 來進行：</p>
<pre><code class="javascript">function doGet() {  
    var dataExportFormat = JSON.stringify(data); // 將資料陣列轉換成為 Json 格式  
    return ContentService.createTextOutput(dataExportFormat).setMimeType(ContentService.MimeType.JSON); // 回傳資料  
}</code></pre>
<p>完成後，點選畫面上方的「部署」→「新增部署作業」。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-11_hu13a7803d69c3ae49a3d45e44a3cc44cd_100254_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-11_hu13a7803d69c3ae49a3d45e44a3cc44cd_100254_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-11_hu13a7803d69c3ae49a3d45e44a3cc44cd_100254_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-11_hu13a7803d69c3ae49a3d45e44a3cc44cd_100254_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>點選左方齒輪 →「網頁應用程式」。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-12_hu94f29fc572fe3d260e5580fb396607e0_43685_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-12_hu94f29fc572fe3d260e5580fb396607e0_43685_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-12_hu94f29fc572fe3d260e5580fb396607e0_43685_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-12_hu94f29fc572fe3d260e5580fb396607e0_43685_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>下方的「誰可以存取」改選「任何人」，並點擊「部署」。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/google-app-script-article-13_hub0141eed09685ebe7217e809e80e4c97_65315_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-13_hub0141eed09685ebe7217e809e80e4c97_65315_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/google-app-script-article-13_hub0141eed09685ebe7217e809e80e4c97_65315_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/google-app-script-article-13_hub0141eed09685ebe7217e809e80e4c97_65315_960x0_resize_q75_box.jpg" alt=""
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<p>完成部署後會獲得一串網址：</p>
<pre><code class="bash">https://script.google.com/macros/s/xxxxxxxxxxxxxxxxxxx/exec</code></pre>
<p>後續將會在網站上透過此網址來串接網頁瀏覽數。</p>
<h2 id="最後一哩路用-javascript-將資料放入頁面中">最後一哩路：用 Javascript 將資料放入頁面中</h2>
<p>回到網頁，同樣使用 jQuery 的 $ajax 來串接資料，其中的 url 填入前面從 Google Apps Script 所取得的連結，程式碼如下：</p>
<pre><code>$.ajax({
    url: 'https://script.google.com/macros/s/AKfycbypNr2QBNkSkJ6FBaYz8C8o2E8IuWsB4AzL-UltX7aUeBZJ-d00uGaMm7Joy-gP2nT_Bw/exec',
    type: 'get',
    async: false,
    success: function (res) {
        // 獲取資料成功
    },
    error: function (res) {
        // 獲取資料失敗
    }
});
</code></pre>
<p>成功獲取資料後，理想中我們希望依據不同網址獲取不同瀏覽次數，因此使用一個 for 迴圈來篩選出資料：</p>
<pre><code>for (var i of res) {
    if (i[0] === pageviewUrl) { // 當 i[0] 也就是陣列中的網址 等於 本頁路徑時
        var pv = i[1]; // 讓 pv 等於 i[1] 也就是陣列中的計數
        $('#pv').text(pv); // 將 #pv 元素加入此數值
    }
}
</code></pre>
<p>最後整合 for 迴圈與 $ajax 如下：</p>
<pre><code>$.ajax({
    url: 'https://script.google.com/macros/s/AKfycbypNr2QBNkSkJ6FBaYz8C8o2E8IuWsB4AzL-UltX7aUeBZJ-d00uGaMm7Joy-gP2nT_Bw/exec',
    type: 'get',
    async: false,
    success: function (res) {
        for (var i of res) {
            if (i[0] === pageviewUrl) { // 當 i[0] 也就是陣列中的網址 等於 本頁路徑時
                var pv = i[1]; // 讓 pv 等於 i[1] 也就是陣列中的計數
                $('#pv').text(pv); // 將 #pv 元素加入此數值
            }
        }
    },
    error: function (res) {
        console.log('Error')
    }
});
</code></pre>
<p>到這裡就完成囉！</p>
<p>最後，Demo 頁面與程式碼範例都放在 GitHub 上，也歡迎大家提供其他建議囉！</p>
<ul>
<li>Demo 頁面：<a href="https://demo-uqp.pages.dev/google-app-script-article-pageview/">https://demo-uqp.pages.dev/google-app-script-article-pageview/</a></li>
<li>範例程式碼：<a href="https://github.com/chenghanxyu/google-app-script-article-pageview/">https://github.com/chenghanxyu/google-app-script-article-pageview/</a></li>
</ul>
]]></content:encoded></item><item><title>打造線上廣播電台播放器 Diantai：一切都從需求開始</title><link>https://yuslife.cc/coding/diantai-01/</link><pubDate>Sun, 04 Dec 2022 00:00:00 +0800</pubDate><guid>https://yuslife.cc/coding/diantai-01/</guid><description>隨著 HiNet 廣播網 hichannel 的服務在 2022/9/30 終止，原先透過網路收聽廣播電台的大宗使用者，只能紛紛尋找其他替代服務，然而許多替代方案都存在著不同問題，因而衍生出需</description><content:encoded><![CDATA[<p>隨著 HiNet 廣播網 hichannel 的服務在 2022/9/30 終止，原先透過網路收聽廣播電台的大宗使用者，只能紛紛尋找其他替代服務，然而許多替代方案都存在著不同問題，因而衍生出需要一款符合台灣受眾使用習慣，且方便美觀的線上廣播網站需求。</p>
<p>
<figure>
    <picture>
        
        <source data-srcset="/src/images/post/diantai-01-featured_hu4dc60c7155cc8ebab94d2a596b11438b_850199_400x0_resize_q75_h2_box.webp" media="(max-width:500px)" type="image/webp">
        
        <source data-srcset="/src/images/post/diantai-01-featured_hu4dc60c7155cc8ebab94d2a596b11438b_850199_600x0_resize_q75_h2_box.webp" media="(max-width:700px)" type="image/webp">
        
        <source data-srcset="/src/images/post/diantai-01-featured_hu4dc60c7155cc8ebab94d2a596b11438b_850199_960x0_resize_q75_h2_box.webp" type="image/webp">
        
        <img src="/src/images/img-placeholder.svg" data-src="/src/images/post/diantai-01-featured_hu4dc60c7155cc8ebab94d2a596b11438b_850199_960x0_resize_q75_box.jpg" alt="hichannel 服務終止通知"
            class="lazy"  width="960" height="540">
    </picture>
    
</figure></p>
<h2 id="hichannel-結束後的替代方案與常見問題">hichannel 結束後的替代方案與常見問題</h2>
<p>在 hichannel 結束服務後，大多數習慣使用網路收聽廣播的使用者，可能會有以下選擇：</p>
<ol>
<li>透過各電台官網收聽</li>
<li>透過其他集合線上收聽管道收聽</li>
</ol>
<p>然而上述兩管道卻存在著不同的問題，首先，由於各廣播電台線上收聽管道不一，有的是透過自己本身網站提供服務，有的是透過 YouTube、Twitch 等第三方影音平台提供串流，進而加大了使用者搜尋的難度與切換電台的不便性。</p>
<p>而透過其他集合線上收聽管道的網站收聽，則會發現大多服務都是國外網站所提供，缺乏符合國內使用者的收聽需求，比如：語言不一定提供繁體中文、電台收錄不完整、篩選方式缺乏以電台頻率等台灣使用者習慣的方式篩選、因非台灣在地服務無法即時更新等問題。</p>
<p>綜觀上述問題，筆者想試著透過自己淺薄的程式技能，嘗試開發出一款符合自身需求而且又好看的網路線上廣播電台。</p>
<h2 id="我心目中的線上廣播電台是如何">我心目中的線上廣播電台是如何？</h2>
<p>觀察目前市面的線上廣播網並集合我的需求，我會希望打造如下功能的線上廣播電台：</p>
<ol>
<li>只包含台灣的廣播電台，降低複雜度</li>
<li>能依照地區、種類、頻率篩選廣播電台列表</li>
<li>具備背景播放功能</li>
<li>能收藏喜愛電台</li>
<li>美觀、好看</li>
</ol>
<p>接下來，我將依循上述大方向，開始規畫屬於自己的線上廣播電台，而在正式打造前，先幫這個專案命名，既然是收聽廣播電台，就稱呼他為「DianTai（電台音譯）」吧！</p>
<blockquote>
<p>「程式筆記」是於是寫下生活筆記全新系列主題文章，主要將會記錄各種筆者開發網站或工具的過程，留下屬於斜槓行銷人的文字紀錄。</p>
<p>因為不是專業工程師，若開發過程有任何建議與指教，都可以在下方留言交流！</p>
</blockquote>
]]></content:encoded></item></channel></rss>