發表文章

區域網路存取權,讓你正視呼叫API的方法

圖片
為什麼 API 權限全開,還是會封鎖連線? 開發前後端分離架構,或是串接不同環境 API 時,常發生一種情況:後端已設定 Access-Control-Allow-Origin: * (允許所有網域存取),且 Postman 測試正常,但從瀏覽器環境透過 JavaScript 發送請求給內網或私有環境的 API 伺服器時,Chrome 卻強制阻擋連線。 這是 Chrome 實施「 區域網路存取權 」(Local Network Access, LNA)規範所致,目的是為了保護使用者免於跨網站要求偽造 (CSRF) 攻擊。 使用者在初次進入網站時,可能會看到這2種提示訊息視窗(也可能不會看到就自動封鎖): 這會帶來什麼影響? 這項安全機制會導致即使後端 API 權限全開,瀏覽器仍攔截請求。具體的錯誤訊息如下: Access to fetch at 'https://api.example.com/apiName' from origin 'https://www.example.com' has been blocked by CORS policy: Permission was denied for this request to access the `unknown` address space. net::ERR_FAILED 看到 Permission was denied for this request to access the ... address space 關鍵字,即代表觸發區域網路存取限制。瀏覽器判定來源(如 www.example.com )位於公網,而目標解析後位於私有網路或無法判定的位址空間,直接封鎖。 技術債的償還:API 呼叫的正規做法 遇到此問題時,有些網站管理者會教使用者如何解除封鎖,並叫他們點擊「允許」: 點擊網址左邊的icon。 開啟存取權。 重新整理頁面。 跳出提示視窗時點擊允許。 使用者手動解除封鎖的方法 但從架構安全的角度來看, 前端直接呼叫私有 API 或第三方服務,本質上就是一種「技術債」 ,就算寫在 .env 裡面有心人也有辦法翻出來。API 呼叫的最佳實踐本來就該是 S...
圖片
許多人在最近都有看過一份來自seer interactive的 AIO觀察報告 ,點擊率下降已是常態,但讓人出乎意料的是,就算沒有出現AIO(AI Overviews),點擊率也下降。 數據來源是他們的客戶,觀察時間從去年6月到今年9月: 42 個客戶組織的 3119 個搜尋詞彙 2510 萬次自然曝光和 110 萬次付費曝光 自然搜尋點擊有無AIO的影響 有AIO下降幅度:61% 無AIO下降幅度:41% 為何就算沒有AIO,點擊率仍然下降了41%?原因很簡單: 零點擊搜尋越來越多 AIO與其它AI平台的出現,造成更多企業往PPC投資 Google自家平台在SERP越來越活躍(商家檔案、Google Maps、Google Shopping、YouTube) 其它使用者習慣的改變 你可以發現,就算沒有AIO,自然點擊率也註定會下降,只是AIO加劇了這個情況。 但多投資付費關鍵字廣告就是解答嗎?倒也不是,實際上付費廣告的點擊率也不一定會好。 付費廣告點擊有無AIO的影響 有AIO下降幅度:68% 無AIO下降幅度:32% 就算付費廣告出現的位置在AIO上面,點擊率仍然大幅下降;且就算沒有AIO,也因為可預見的競爭變多、AI Agent的自動完成工作,下降幅度也不小。 有趣的是,在下方的AIO如果有提到你的品牌,付費點擊率又會上升91%。 AIO存在且品牌被AIO引用,會提升點擊率 但要注意,這個數據可能有誤導性:也許搜尋的字詞本身就包含品牌也說不定,又或者是二次搜尋導致。 Google拿石頭砸自己腳? 所以,Google AIO 的出現反而讓 Google 自己在付費廣告賺的錢變少了? 答案是不一定,畢竟競爭變多了,平均單次點擊價格也會大幅提升。而且,Google自己可能也發現了PPC點擊率下降的問題,因此在9月測試並修改了AIO的某些演算法。 BrightEdge 發現,9月時AIO在電子商務類的覆蓋率異常 這次的改動,多半是AIO對於「意圖」的理解度提升,讓使用者在需要點擊付費廣告時大幅降低出現AIO的機率,判斷是比較、研究、學習等意圖時則保留出現率。 因此,我們可以觀察11、12月的購物季,付費廣告的點擊率有沒有稍微改善。 被AI提及或引用太重要 我...
圖片
長久以來,Google提出的data-nosnippet方法只對Google爬蟲有用;現在Bing也跟上支援這個HTML attritube,且就連Copilot AI也能看懂data-nosnippet了。 圖片作者: Jason Leung data-nosnippet是什麼?功用是什麼? 自從2021年開始, 網頁title 和描述(description)會在搜尋結果中被Google修改後,為了不讓描述出現網站擁有者不想讓別人看見的文字, data-nosnippet 就此孕育而生。 它的功用在於,只要該段落加上data-nosnippet,當中的文字絕對不會變成Google搜尋結果中的網頁描述。以下為簡單的使用例子: <section data-nosnippet> <p>這段文字不會變成網頁描述,也不會被Copilot AI提取</p> </section> 另外,Bing也簡單 舉例 了它的常見運用方式: 將付費內容排除在預覽之外。 不想讓用戶評論或評價的曝光。 隱藏法律樣板、免責聲明和Cookie通知。 排除贊助廣告或過期的促銷內容。 A/B TEST。 Bing和Copilot AI的支援,樂觀看待 另一個搜尋巨頭也能用data-nosnippet的話,可以樂觀地期待所有搜尋引擎都支援的一天到來。 更開心的是連Copilot都支援以提升AI生成的品質,其它AI巨頭是否也會跟上?
圖片
以前如果說 CSS 是「程式碼」的話,通常都會被糾正為「原始碼」,但在 @function 等功能性的語法出現之後,現在這個傳統界線也越來越模糊。 本文將透過之前提過的 if() 和 sibling-index()、sibling-count() 語法,帶大家體驗 @function 的強大功能。 1. 結合 attr() 與型別定義的狀態樣式 過去我們使用 attr() 取值時,通常只能用於 content 屬性,且無法參與運算或邏輯判斷。新的語法允許我們指定型別 type(<custom-ident>) ,這讓 HTML 的屬性值可以被 CSS 的 if() 邏輯正確識別。 在這個範例中,我們定義了一個 --status-color 函數,它接收一個狀態參數,並根據傳入的值決定回傳的顏色。你可以注意到,它和 JavaScript 一樣可以設定變數的預設值: @function --status-color(--status: xxx, --success: #7dfaa5, --error: #ff3874) { result: if( style(--status: success): var(--success); style(--status: error): var(--error); else: #fccd81 ); } .card { /* 使用 attr() 抓取 HTML 的 data-status,並強制轉型為 custom-ident */ background-color: --status-color(attr(data-status type(<custom-ident>))); } 跟 JavaScript 不同的地方在於,JS 是用 return 拋出結果,CSS 則是用 result: 。 這樣的寫法讓我們可以直接在 HTML 中控制語意,而樣式的邏輯完全封裝在 CSS 函數內: <div class="card" data-status="error">error</div> <div class="card" data-status=...
圖片
許多行銷人員都會依賴 GTM 插入 Facebook Pixel 的程式碼,但你是否有想過,當一個網站上出現多個 Pixel ID 的時候,一直 init(重新宣告)Pixel ID、直接觸發事件、整段程式碼貼上,會重複追蹤事件(一直Add to Cart)、覆蓋變數影響其它 Pixel ID……等問題,最終除了讓網頁效能降低外,收集到的數據也不準確。 曾經經手過一個充滿好幾個 meta pixel 和 bing uet 的網站,單純把 GTM 拿掉,效能就可以提升超過40分。 自訂事件一般寫法 許多行銷人員會在 GTM 中使用「自訂 HTML」直接貼上像這樣的程式碼來達成他想要的自訂事件: <script> !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)}; if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t,s)}(window, document,'script', 'https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '1234567890'); fbq('trackCustom', '自訂事件名稱', { '額外要傳送的數據Object': 999 }); </script> 但他完全沒有考慮可能會發生的問題: https://connect.facebook.net/en_US/fbevents.js 是否已經載入過了。( 這個其實官方程式碼已經處理: if(f.fbq)return; ) Pixel ID 是否已經宣告...
圖片
CSS 中「兄弟元素」的應用與痛點 在網頁切版與動畫設計中,我們經常遇到需要根據「元素是第幾個」或「總共有幾個元素」來改變樣式的情境。例如: 交錯動畫 (Staggered Animation): 讓列表中的項目一個接一個出現,而不是同時出現。 動態寬度: 根據容器內有多少個項目,自動計算每個項目的寬度。 階梯狀視覺: 依序改變背景色深淺或位置偏移。 在過去,要純用 CSS 達成這些效果非常繁瑣。我們通常只能依賴 :nth-child() 寫死一堆規則(例如寫 50 行 CSS 來對應 50 個項目),或是使用 SCSS 的迴圈在編譯時產生代碼。更靈活的做法則是依賴 JavaScript 去計算並動態賦予 CSS 變數(如 --index , --total )。因此原生的 CSS 解決方案因此備受期待。 此圖片由AI生成 sibling-index() 與 sibling-count() sibling-index()返回該元素在兄弟節點中的 索引值 (通常從 1 開始計算,具體依實作而定)。它相當於 JavaScript 中遍歷 DOM 得到的 index。 sibling-count()返回該元素的父容器下,包含自己在內共有多少個 兄弟節點總數 。它相當於 JavaScript 中的 parentNode.children.length 。 基本語法範例: .item { /* 讓每個項目的動畫延遲時間隨索引增加 */ animation-delay: calc(sibling-index() * 0.1s); /* 根據總數量自動計算寬度 */ width: calc(100% / sibling-count()); } CodePen 實例解析 接下來我們透過 CodePen 實作一些簡單的範例。 See the Pen sibling-index(), sibling-count() by cj ( @cjzopen ) on CodePen . 自動計數與視覺堆疊 在範例中,透過 sibling-index() ,我們可以為每一個卡片或列表項目設定獨立的 Z 軸層級或顏色變化,而...
圖片
大家都知道,AI 為了迎合使用者、不懂裝懂時,會產生 AI 幻覺(hallucination),除了文字之外,有時也會出現超連結的幻覺。若只是 AI 幻想的連結那還好,但若是把社交工程的連結拿來給使用者點擊,嚴重性可大可小。 本圖片由AI生成 實際經驗 前幾天在AI平台詢問如何報廢機車領取補助、如何得知該報廢機車的出廠年份,AI 給出的答案都非常正確,但其中一個連結卻是連到釣魚網站。 雖然我以前就知道 AI 有時候會自創連結,但沒想到這次自創的連結剛好具有攻擊性,不可不注意。 說到這裡,有些人的網站也遇到一些來自AI平台的404流量。 如何處理因AI幻覺而進站的404流量? 絕對不要為了從以前就不存在的頁面設定301轉址。 網站的404頁面要有引導能力。 任意設定301轉址的話會造成各方面的困惑(不論是爬蟲還是使用者),最差的做法就是將404全部跳轉到首頁,這對 SEO 來說是禁忌。 404並沒有什麼不好,它也是好不容易得來的流量;反過來看,你可以把404頁面當成landing page,好好地設計它,讓它成為有效的流量。 舉例來說,404頁面可以導入AI技術,從網址來判斷使用者的意圖,再推薦使用者一些他可能會感興趣的頁面。 為何網站的404幻覺流量會很多? 有一說是網頁架構太差,加上網頁的網址結構太爛。例如明明存在產品導覽頁面,但產品網址卻不在產品導覽頁面下面。 另外也有一說是缺乏標準網址(canonical)、原本存在的404連結就很多。就看你信不信。 總而言之,在AI平台(尤其是 ChatGPT)點擊超連結時,就跟打開 email 一樣,稍微留意一下網域是否錯的太離譜。
圖片
也許你有發現各AI平台有在優化「黏著度」,有的是在回答完後問你要不要繼續幫你做某些事,有的則是會在回答中分段落,在點擊段落標題後把此標題當作你的繼續提問,有的則是列出你可能還會問的問題吸引你點擊,有的還會跳出相關領域的「AI專家」吸引你切換後繼續提問。 在越來越多人使用、花費更多時間在AI平台時,所有人都知道要評估自身品牌 GEO 的成效,但是,資料從哪裡來? 先說結論:目前有 ahrefs 等大廠推出評估工具,但效果如何見仁見智。為什麼?因為目前仍然無法得知: 真正的使用者問了什麼,讓我的品牌被提及了?只能自己設定 prompt。 AI 提及我的品牌時是如何描述的?就算用 API 去執行一次,實際上也會因為不同人而產生差異;且就算是同一個人,重複提問產生的內容也未必相同。 AI 因「黏著度」的考量會引導使用者追問,它說了什麼?使用者又是追問了什麼?這個跟前兩者是類似的原因。 什麼時候開始引用我的連結?是否為「無效引用」?一直問類似問題出現的比例是多少?顯示的圖片又是哪一張? 「無效引用」跟使用者問了什麼息息相關,舉例來說,當使用者提問像是「導入AI的最佳指南是什麼」之類的問題,AI在思考期間想從多種角度切入,其中一個角度是ROI;然而,你因為寫了一篇「什麼是ROI」的文章而被引用,但跟使用者的主要目的完全無關,就是無效引用。 是的,你可以發現目前大廠的工具都只是「模擬」,而不是真正的數據。 強化AIO與GEO的方法 也許你也會想知道怎麼優化,這裡先提供一份簡報給你參考: https://gamma.app/docs/AIOGEOAI-MODE-rt0q4h5vz30dwaz 。 總而言之就是先做好 SEO 的基本功:indexing。 簡報中有寫: Priming Effect:一旦某個品牌或概念出現在AIO,它就會變成人們想法的起點(或視野會被限制)。 風險、成本越高,就越會查證。而查證就是 SEO 的方向。 SEO成功的驅動力之一: 線下SEO 。用戶在AIO或搜尋結果中看到你的品牌之前,你已經贏得了多少 「心智份額」(有別人稱心佔率) 。 除此之外,你還要有基本認知: Google 會去分辨內容是 AI 寫的,還是人寫的嗎? ...
圖片
在Chromium的環境中,可以直接寫JavaScript導入生成摘要的AI(Gemini Nano): Summarizer API 。 這個 API 可以幫助生成文章或對話的重點或摘要、前導訊息、生成標題……等用途。 官方明確提出會在 Chrome 138 的版本導入此 API,但其實在很早之前就鼓勵開發者試著用Gemini Nano開發擴充功能。 在開始使用之前,可以順便閱讀 The People + AI Guidebook 與 Ameba 平台實際運用的情境 。 開始使用 查看是否支援 Summarizer API: if ('Summarizer' in self) { // The Summarizer API is supported. } Summarizer.availability() 可以判斷模型是否已準備好:它會回傳 "unavailable"(不支援)、"downloadable"(尚未下載)、"downloading"(下載中)、"available"(支援且可執行)。 而如果是 downloadable 或 downloading,可以在 Summarizer.create() 中使用 downloadprogress 查看下載進度: const summarizer = await Summarizer.create({ monitor(m) { m.addEventListener('downloadprogress', (e) => { console.log(`Downloaded ${e.loaded * 100}%`); }); } }); 呼叫 function 一般摘要: const theArticle = document.querySelector('#article').innerHTML; const summary = await summarizer.summarize(theArticle, { context: 'This article is about vtuber of ho...
圖片
不知道大家有沒有看了Apple的 WWDC25 ?先不論他們說了什麼,我只在想他們的液態玻璃(Liquid Glass)UI要如何實現(這裡討論的是靜態效果)。 部分UI改成毛玻璃樣式。 然而大部分元件則是改成不太一樣的液態玻璃樣式。 backdrop-filter 一開始當然是先想到從以前就有的毛玻璃效果(Glassmorphism),也就是用backdrop-filter來嘗試: See the Pen backdrop-filter by cj ( @cjzopen ) on CodePen . 但你可以發現,做不出底下文字或圖片扭曲的效果,於是就想到了SVG的filter。 <svg style="display: none;"> <filter id="wavy-distort"> <feTurbulence type="turbulence" baseFrequency="0.02" numOctaves="2" result="turbulence"/> <feDisplacementMap in2="turbulence" in="SourceGraphic" scale="10" xChannelSelector="R" yChannelSelector="G"/> </filter> </svg> feTurbulence 我們可以先在HTML裡創造一個擁有filter的SVG,其中包含feTurbulence: type: turbulence (亂流) / fractalNoise (雲)。 baseFrequency: 雜訊圖的密度。 numOctaves: 雜訊圖疊的層數。 result: 類似 id,後續拿來引用的名稱。 再使用feDisplacementMap引用feTurbulence: ...
圖片
CSS 的 if() 搭配 變數系統 或 attr() ,讓我們能直接用 CSS 判斷條件或 HTML 屬性自動達成樣式變化,在某些情況下不再需要寫任何 JavaScript。 範例 我們可以用不同 class 搭配變數不同的值,再加上 if 和 else 判斷來自動設定 background-color 的值: :root { --color: #333; } .element { background-color: if( style(--color: #fafafa): black; style(--color: #ed5fe8): #000a75; else: white); } .dark { --color: #fafafa; } .esport { --color: #ed5fe8; } 你可以注意到,寫複數個判斷條件還可以實現「else if」的效果。 但直接使用的缺點也很明顯,就是直接判斷變數的值太不直觀了,所以我們還可以用上 attr() 來改良。 用 attr() 優化 if() 的判斷條件 這裡我們使用 attr() 搭配 if() 判斷狀態(data-status)來給不同的值,程式寫起來就會直觀很多。 <div class="container"> <div class="card" data-status="success"></div> <div class="card" data-status="warning"></div> <div class="card" data-status="success"></div> <div class="card" data-status="error"></div> <div class="card" data-status="warning"></div>...
圖片
SE Ranking 分析了Google AI Overviews(AIO)在美國五個州的表現(科羅拉多、德州、加州、紐約和華盛頓特區)。 報告顯示,AI Overviews的出現率在各州差異不大,約佔查詢總數的30%。雖然整體來源相似,但在處理在地化查詢時,會納入該州特有的網域。研究也發現,查詢字詞越長越可能觸發AI Overviews,且內容越長的AI Overviews引用的來源越多。Google.com是引用次數最多的來源,Reddit和Quora也重新回歸成為主要的引用來源。 且AIO幾乎都會跟其他 SERP 功能一起出現(99.25%),最常見的是PAA(98.5%)。 引用的方式持續演變 平均引用來源數:在所有州中,AI Overviews 平均引用 13.34 個來源,各州之間的差異極小(13.28 到 13.41)。 最大引用來源數:休士頓和洛杉磯的單一回覆最多引用了 95 個連結。丹佛、紐約和華盛頓特區的最高引用連結數分別是 77、87 和 82。 引用連結數的分佈:最常見的回覆包含 6 到 14 個連結,這可能代表 Google 演算法使用的「最佳範圍」。包含 0 或 1 個連結的回覆很少見,不到 0.5% 的案例,這可能表明需要一定數量的來源來提供高品質且可信的摘要。包含超過 21 個連結的回覆頻率會穩步下降。在各州中,包含 8-9 個連結的回覆最為常見。加州和紐約最常見的是 8 個連結的回覆 (6.57%-6.56%),而德州和科羅拉多最常見的是 9 個連結的回覆 (6.59%-6.60%)。華盛頓特區則在 6 個連結 (5.64%) 和 12 個連結 (5.84%) 的回覆頻率上較高。 與回覆長度的關係:AI Overview 回覆的長度與引用的來源數量呈現強烈的正相關:回覆越長,包含的來源越多。例如,長度少於 600 字元的回覆平均引用 5.31 個來源,而長度在 6600-7200 字元範圍的回覆則引用 28 個來源。 主要引用的網站 在所有研究的五個州中,Google.com 是被引用最多的網站。這個結果也被酸是 Google 的圍牆花園(walled garden)效應。 Google.com 出現在近 44% 的回覆中。 其他排名前十的被引用網站(在各州幾乎相同)包括 YouT...
圖片
準備好你的擴充功能檔案。 註冊開發人員帳戶。 上傳擴充功能檔案。 填寫相關資訊。 提交審核。 前陣子 manifest_version 從 2 強制升級成 3,我認為是一個很好的入坑時機點,直接學新的版本就好了,所以試著上傳小工具給官方,也當作一次學習。 1. 準備好程式碼與各項設定 chrome 擴充功能的設定都會寫在 manifest.json 裡面,包含擴充功能的名稱、簡單描述、各種檔案的路徑。 { "manifest_version": 3, "name": "__MSG_extensionName__", "version": "1.0.0", "description": "__MSG_extensionDescription__", "default_locale": "en", "permissions": [ "storage", "activeTab", "tabs" ], "host_permissions": [ "<all_urls>" ], "background": { "service_worker": "background.js" }, "action": { "default_popup": "popup.html", "default_icon": { "16": "icons/icon16.png", "48": "icons/icon48.png", "128": "icons/icon12...