跳至頁尾內容
使用IRONPDF

如何用IronPDF在Blazor中顯示PDF

通用和手動擔保品的問題

IronPDF首頁 一個發送給資料庫中每位客戶的折扣優惠,不管他們買了什麼或瀏覽了什麼,比起一個真正的優惠,更像是一場噪音事件。 剛花了800美元買行李的顧客不需要10%的行李優惠券。 只使用報告功能的試用使用者不想收到關於協作工具的電子郵件。 個性化不是行銷的奢侈品,而是實際能轉換的擔保品的基礎。

想要個性化擔保品和大量生產之間的鴻溝是問題的所在。 一家旅行公司有十個目的地區域,三個客戶等級,和兩個地區變體,並不擁有60個InDesign文件,他們有三個文件是有人打算更新的,而其餘的文件存放在沒人碰的共享雲端文件夾中。 一家金融服務公司為不同的風險設定生成量身定製的投資摘要,無法要求設計師手工製作每一份。 一個電子商務平台使用流失客戶挽回活動需要為每位收件人生成的報價,而不是為每個區段生成。

每次市場行銷需要"再多一個版本"時,工程部門就會被拉入這個間隙裡。PDF匯出重新建構,模板被複製,資料流水線被延展,等到它上線時,活動窗口已經縮小了。 下一次活動就開始了相同的迴圈。

第三方的個性化平台涵蓋了部分內容,但增加了逐份文件或逐個收件人的定價,這些都直接根據活動規模進行增長,目標越廣泛的活動運行起來就越昂貴。

解決方案:從客戶資料到PDF文件的運行時個性化

IronPDF允許.NET應用透過在運行時合併客戶資料和區段邏輯與HTML內容和CSS市場行銷模板生成個性化的PDF優惠和手冊。活動系統識別接收者及其屬性,選擇合適的模板變體,填入特定於客戶的內容,Chromepdfrenderer生成PDF

行銷部門擁有並更新HTML模板。 工程部門擁有資料流水線和區段邏輯。 彼此不會阻礙對方,設計師可以更改模板布局,更新影像,或重寫文案,而不觸碰到一行C#程式碼,下一次渲染會自動接收更改。 沒有設計工具匯出,沒有逐份文件的供應商費用,也沒有手動的逐活動變異。 渲染執行在現有的.NET應用中作為單一NuGet包。

實際運作方式

1. 活動觸發識別收件人和他們的個人資料

當計畫中的活動工作為目標區段運行時,或使用者達到生命週期里程碑(自上次購買三十天,試用第14天,間隔後首次登錄),或者銷售代表為CRM中的特定潛在客戶生成保留優惠時,會啟動生成。 三個路徑都會生成相同的輸入:客戶ID和觸發活動的聯繫。

程式從客戶資料庫檢索收件人的個人資料,姓名,區段標籤,購買歷史,產品偏好,忠誠度等級,及與優惠相關的任何行為信號。 旅遊客戶瀏覽過的目的地,電子商務購物者最近的類別,SaaS試用使用者使用最多的功能。 這些是讓文件感到特定而不是通用的資料。

2. 區段邏輯選擇模板和內容

模板選擇器將客戶的區段和屬性映射到模板變體。 高消費忠誠客戶獲得帶有最高折扣層級和"尊貴會員"語氣的高級模板。 價格敏感區段獲得具有不同標題和價值主張的預算友好變體。 流失客戶獲得挽回框架。

產品建議、優惠百分比、到期日期和兌換程式碼在此步驟計算,根據客戶的傾向模型、忠誠度層級和活動配置派生。 唯一的兌換程式碼或跟蹤URL將特定文件與接收者聯繫起來,以便在優惠兌現時歸名。

例如:

預算方案範例模板

HTML輸入模板一

標準方案範例模板

HTML輸入模板二

高級方案範例模板

HTML輸入模板三

3. 模板填充並轉為HTML至PDF

using IronPdf;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;

renderer.RenderingOptions.MarginTop = 0;

renderer.RenderingOptions.MarginBottom = 0;

string templateFile = customer.Segment switch
{
    "HighValue"     => "Templates/offer-premium.html",
    "PriceSensitive"=> "Templates/offer-budget.html",
    _               => "Templates/offer-standard.html"
};

string productRows = string.Concat(customer.Recommendations.Take(3).Select(p =>

    $"<div class='product'><img src='{p.ImageUrl}'><p><strong>{p.Name}</strong></p><p>{p.Price:C}</p></div>"));

string html = (await File.ReadAllTextAsync(templateFile))
    .Replace("{{CustomerName}}", customer.FirstName)
    .Replace("{{DiscountPct}}", customer.LoyaltyDiscount.ToString())
    .Replace("{{OfferCode}}", customer.UniqueOfferCode)
    .Replace("{{Expiry}}", campaign.ExpiryDate.ToString("MMMM d, yyyy"))
    .Replace("{{ProductRecommendations}}", productRows);

PdfDocument offer = renderer.RenderHtmlAsPdf(html);

offer.SaveAs($"offers/{campaign.Id}/{customer.Id}.pdf");
using IronPdf;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;

renderer.RenderingOptions.MarginTop = 0;

renderer.RenderingOptions.MarginBottom = 0;

string templateFile = customer.Segment switch
{
    "HighValue"     => "Templates/offer-premium.html",
    "PriceSensitive"=> "Templates/offer-budget.html",
    _               => "Templates/offer-standard.html"
};

string productRows = string.Concat(customer.Recommendations.Take(3).Select(p =>

    $"<div class='product'><img src='{p.ImageUrl}'><p><strong>{p.Name}</strong></p><p>{p.Price:C}</p></div>"));

string html = (await File.ReadAllTextAsync(templateFile))
    .Replace("{{CustomerName}}", customer.FirstName)
    .Replace("{{DiscountPct}}", customer.LoyaltyDiscount.ToString())
    .Replace("{{OfferCode}}", customer.UniqueOfferCode)
    .Replace("{{Expiry}}", campaign.ExpiryDate.ToString("MMMM d, yyyy"))
    .Replace("{{ProductRecommendations}}", productRows);

PdfDocument offer = renderer.RenderHtmlAsPdf(html);

offer.SaveAs($"offers/{campaign.Id}/{customer.Id}.pdf");
Imports IronPdf
Imports System.IO
Imports System.Linq

Dim renderer As New ChromePdfRenderer()

renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter

renderer.RenderingOptions.MarginTop = 0

renderer.RenderingOptions.MarginBottom = 0

Dim templateFile As String = If(customer.Segment = "HighValue", "Templates/offer-premium.html", If(customer.Segment = "PriceSensitive", "Templates/offer-budget.html", "Templates/offer-standard.html"))

Dim productRows As String = String.Concat(customer.Recommendations.Take(3).Select(Function(p) $"<div class='product'><img src='{p.ImageUrl}'><p><strong>{p.Name}</strong></p><p>{p.Price:C}</p></div>"))

Dim html As String = (Await File.ReadAllTextAsync(templateFile)).
    Replace("{{CustomerName}}", customer.FirstName).
    Replace("{{DiscountPct}}", customer.LoyaltyDiscount.ToString()).
    Replace("{{OfferCode}}", customer.UniqueOfferCode).
    Replace("{{Expiry}}", campaign.ExpiryDate.ToString("MMMM d, yyyy")).
    Replace("{{ProductRecommendations}}", productRows)

Dim offer As PdfDocument = renderer.RenderHtmlAsPdf(html)

offer.SaveAs($"offers/{campaign.Id}/{customer.Id}.pdf")
$vbLabelText   $csharpLabel

範例生成PDF

IronPDF範例輸出 ChromePdfRenderer處理模板的全部視覺保真度,產品影像、通過@font-face載入的自定義行銷字型、多欄布局及設計的行動呼叫按鈕精確呈現。 輸出不是模板的降級版; 是模板。

4. 批量生成活動區段

using IronPdf;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;

await Parallel.ForEachAsync(campaignRecipients,

    new ParallelOptions { MaxDegreeOfParallelism = 4 },

    async (customer, _) =>
    {
        string html = await BuildPersonalizedHtmlAsync(customer, campaign);
        PdfDocument pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs($"offers/{campaign.Id}/{customer.Id}.pdf");
    });
using IronPdf;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;

await Parallel.ForEachAsync(campaignRecipients,

    new ParallelOptions { MaxDegreeOfParallelism = 4 },

    async (customer, _) =>
    {
        string html = await BuildPersonalizedHtmlAsync(customer, campaign);
        PdfDocument pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs($"offers/{campaign.Id}/{customer.Id}.pdf");
    });
Imports IronPdf

Dim renderer As New ChromePdfRenderer()

renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter

Await Parallel.ForEachAsync(campaignRecipients, 
    New ParallelOptions With {.MaxDegreeOfParallelism = 4}, 
    Async Function(customer, _) 
        Dim html As String = Await BuildPersonalizedHtmlAsync(customer, campaign)
        Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(html)
        pdf.SaveAs($"offers/{campaign.Id}/{customer.Id}.pdf")
    End Function)
$vbLabelText   $csharpLabel

使用IronPDF程式庫生成的兩種PDF優惠

多個PDF生成範例 每個渲染的PDF按客戶ID在活動目錄下儲存,準備附加到外發郵件中,作為個性化登陸頁中的下載連結,或作為印刷的保留品交給銷售代表。 活動分析追踪哪些程式碼被兌換,將歸功歸回每個接收者收到的具體優惠文件。

實際效益

規模化個性化。 每位收信者獲得來自自己的資料、區段、行為、購買歷史、忠誠度等級生成的文件。 相同的流水線服務於十位潛在客戶清單或五萬人的活動區段。

有形格式。 PDF儲存在下載資料夾中,被轉發給同事,或印刷並釘上。它以電子郵件正文所不具備的方式持續存在於收件箱之外,延長了優惠的壽命,而不需額外努力。

市場敏捷性。 HTML和CSS模板由行銷或設計團隊直接編輯,更新了影像,修訂文案,新版面。 變更在下一次渲染時生效,無需工程部署。

歸因。 每個收信者嵌入的唯一兌換程式碼或跟蹤URL將轉換與客戶收到的具體文件連結起來。 活動表現不是從總點擊率推斷,而是可追溯到單個優惠。

區段靈活性。 新增新的區段意味著新增新的模板變體或調整選擇器邏輯。 生成流水線不變。 工程部門無需重建任何內容以支持新的客戶層級或活動主題。

無每份文件的費用。 渲染在過程中執行。 沒有第三方個性化API,沒有逐收信者費用,也沒有懲罰大規模活動的定價模型。

結語

個性化的PDF擔保品是客戶實際回應的交集 — 對他們特定感到相關的東西 — 以及比電子郵件傳得更遠的格式。 靜態發送和量身定制給每位收信者的文件之間的差距是一個資料流水線和一個模板,而不是一個獨立的平台。

將流水線建置於現有的.NET活動系統內需要一個模板文件,一個資料填充步驟和一個渲染呼叫。 IronPDF在< a href="ironpdf.com處理PDF生成的完整生命周期,在C#中,從渲染HTML內容到儲存、生成報表、流式傳輸及操作文件" target="_blank">http://ironpdf.com">ironpdf.com處理PDF生成的完整生命周期,在C#中,從渲染HTML內容到儲存、生成報表、流式傳輸及操作文件。 如果您準備好用自己的客戶區段和活動資料測試個性化擔保品生成,開始免費30天試用,並在您的下一個活動開啟前建立運作中的流水線。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

除了開發,Curtis對物聯網(IoT)有濃厚的興趣,探索創新的方法來整合硬體和軟體。在空閒時間,他喜歡玩遊戲和建立Discord機器人,結合他對技術的熱愛與創造力。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話