第三方集成
本指南将详细介绍如何在 Shopify 主题中集成各种第三方服务,提升网站功能和营销效果。
分析和跟踪集成
1. Google Analytics 4 集成
<!-- snippets/google-analytics.liquid -->
{% if settings.google_analytics_id != blank %}
<!-- Google Analytics 4 -->
<script async src="https://www.googletagmanager.com/gtag/js?id={{ settings.google_analytics_id }}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ settings.google_analytics_id }}', {
send_page_view: false,
custom_map: {
'custom_parameter_1': 'shop_name',
'custom_parameter_2': 'customer_type'
}
});
// 发送页面浏览事件
gtag('event', 'page_view', {
page_title: {{ page_title | json }},
page_location: window.location.href,
shop_name: {{ shop.name | json }},
customer_type: {% if customer %}{% if customer.orders.size > 0 %}'returning'{% else %}'new'{% endif %}{% else %}'guest'{% endif %}
});
// 电商事件跟踪
class GAEcommerce {
static viewItem(product) {
gtag('event', 'view_item', {
currency: '{{ cart.currency.iso_code }}',
value: product.price / 100,
items: [{
item_id: product.id,
item_name: product.title,
item_category: product.type,
item_variant: product.selected_variant?.title,
price: product.price / 100,
quantity: 1
}]
});
}
static addToCart(variant, quantity) {
gtag('event', 'add_to_cart', {
currency: '{{ cart.currency.iso_code }}',
value: (variant.price * quantity) / 100,
items: [{
item_id: variant.product.id,
item_name: variant.product.title,
item_category: variant.product.type,
item_variant: variant.title,
price: variant.price / 100,
quantity: quantity
}]
});
}
static removeFromCart(item) {
gtag('event', 'remove_from_cart', {
currency: '{{ cart.currency.iso_code }}',
value: item.line_price / 100,
items: [{
item_id: item.product.id,
item_name: item.product.title,
item_category: item.product.type,
item_variant: item.variant.title,
price: item.price / 100,
quantity: item.quantity
}]
});
}
static beginCheckout(cart) {
gtag('event', 'begin_checkout', {
currency: '{{ cart.currency.iso_code }}',
value: cart.total_price / 100,
items: cart.items.map(item => ({
item_id: item.product.id,
item_name: item.product.title,
item_category: item.product.type,
item_variant: item.variant.title,
price: item.price / 100,
quantity: item.quantity
}))
});
}
static search(query) {
gtag('event', 'search', {
search_term: query
});
}
}
// 暴露到全局
window.GAEcommerce = GAEcommerce;
</script>
{% endif %}
2. Facebook Pixel 集成
<!-- snippets/facebook-pixel.liquid -->
{% if settings.facebook_pixel_id != blank %}
<!-- Facebook Pixel -->
<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', '{{ settings.facebook_pixel_id }}');
fbq('track', 'PageView');
// 电商事件类
class FacebookPixelEcommerce {
static viewContent(product) {
fbq('track', 'ViewContent', {
content_type: 'product',
content_ids: [product.id.toString()],
content_name: product.title,
content_category: product.type,
value: product.price / 100,
currency: '{{ cart.currency.iso_code }}'
});
}
static addToCart(variant, quantity) {
fbq('track', 'AddToCart', {
content_type: 'product',
content_ids: [variant.product.id.toString()],
content_name: variant.product.title,
value: (variant.price * quantity) / 100,
currency: '{{ cart.currency.iso_code }}'
});
}
static initiateCheckout() {
{% if cart.item_count > 0 %}
fbq('track', 'InitiateCheckout', {
content_type: 'product',
content_ids: [{% for item in cart.items %}'{{ item.product.id }}'{% unless forloop.last %},{% endunless %}{% endfor %}],
value: {{ cart.total_price | money_without_currency }},
currency: '{{ cart.currency.iso_code }}',
num_items: {{ cart.item_count }}
});
{% endif %}
}
static search(query) {
fbq('track', 'Search', {
search_string: query
});
}
static addToWishlist(product) {
fbq('track', 'AddToWishlist', {
content_type: 'product',
content_ids: [product.id.toString()],
content_name: product.title,
value: product.price / 100,
currency: '{{ cart.currency.iso_code }}'
});
}
}
window.FacebookPixelEcommerce = FacebookPixelEcommerce;
</script>
<!-- 无JavaScript情况下的跟踪 -->
<noscript>
<img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id={{ settings.facebook_pixel_id }}&ev=PageView&noscript=1"/>
</noscript>
{% endif %}
3. TikTok Pixel 集成
<!-- snippets/tiktok-pixel.liquid -->
{% if settings.tiktok_pixel_id != blank %}
<script>
!function (w, d, t) {
w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.instance=function(t){for(var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e},ttq.load=function(e,n){var i="https://analytics.tiktok.com/i18n/pixel/events.js";ttq._i=ttq._i||{},ttq._i[e]=[],ttq._i[e]._u=i,ttq._t=ttq._t||{},ttq._t[e]=+new Date,ttq._o=ttq._o||{},ttq._o[e]=n||{};var o=document.createElement("script");o.type="text/javascript",o.async=!0,o.src=i+"?sdkid="+e+"&lib="+t;var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(o,a)};
ttq.load('{{ settings.tiktok_pixel_id }}');
ttq.page();
}(window, document, 'ttq');
// TikTok 电商事件
class TikTokEcommerce {
static viewContent(product) {
ttq.track('ViewContent', {
content_type: 'product',
content_id: product.id.toString(),
content_name: product.title,
content_category: product.type,
value: product.price / 100,
currency: '{{ cart.currency.iso_code }}'
});
}
static addToCart(variant, quantity) {
ttq.track('AddToCart', {
content_type: 'product',
content_id: variant.product.id.toString(),
content_name: variant.product.title,
value: (variant.price * quantity) / 100,
currency: '{{ cart.currency.iso_code }}'
});
}
static initiateCheckout() {
ttq.track('InitiateCheckout', {
value: {{ cart.total_price | money_without_currency }},
currency: '{{ cart.currency.iso_code }}'
});
}
}
window.TikTokEcommerce = TikTokEcommerce;
</script>
{% endif %}
营销工具集成
1. Mailchimp 邮件订阅
<!-- snippets/mailchimp-newsletter.liquid -->
<div class="newsletter-signup" data-newsletter>
<div class="newsletter-content">
<h3 class="newsletter-title">{{ section.settings.heading | default: '订阅我们的邮件' }}</h3>
<p class="newsletter-description">{{ section.settings.description | default: '获取最新产品和优惠信息' }}</p>
</div>
<form class="newsletter-form" data-newsletter-form>
<div class="form-group">
<label for="newsletter-email" class="sr-only">邮箱地址</label>
<input type="email"
id="newsletter-email"
name="email"
placeholder="输入您的邮箱"
class="newsletter-input"
required>
<button type="submit" class="newsletter-submit btn btn--primary">
<span class="btn-text">订阅</span>
<span class="btn-loading" style="display: none;">
{% render 'loading-spinner' %}
</span>
</button>
</div>
<div class="newsletter-message" data-newsletter-message style="display: none;"></div>
</form>
</div>
<script>
class MailchimpNewsletter {
constructor(element) {
this.container = element
this.form = element.querySelector('[data-newsletter-form]')
this.message = element.querySelector('[data-newsletter-message]')
this.submitBtn = this.form.querySelector('button[type="submit"]')
this.btnText = this.submitBtn.querySelector('.btn-text')
this.btnLoading = this.submitBtn.querySelector('.btn-loading')
this.init()
}
init() {
this.form.addEventListener('submit', (e) => {
e.preventDefault()
this.subscribe()
})
}
async subscribe() {
const email = this.form.email.value.trim()
if (!email || !this.isValidEmail(email)) {
this.showMessage('请输入有效的邮箱地址', 'error')
return
}
this.setLoading(true)
try {
// 使用Shopify的客户API或Mailchimp API
const response = await fetch('/contact', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
'form_type': 'customer',
'utf8': '✓',
'contact[email]': email,
'contact[tags]': 'newsletter'
})
})
if (response.ok) {
this.showMessage('订阅成功!感谢您的订阅。', 'success')
this.form.reset()
// 发送事件到分析工具
if (window.gtag) {
gtag('event', 'sign_up', {
method: 'email'
})
}
if (window.fbq) {
fbq('track', 'Subscribe')
}
} else {
throw new Error('订阅失败')
}
} catch (error) {
this.showMessage('订阅失败,请稍后重试', 'error')
console.error('Newsletter subscription error:', error)
} finally {
this.setLoading(false)
}
}
isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
}
setLoading(loading) {
this.submitBtn.disabled = loading
this.btnText.style.display = loading ? 'none' : 'inline'
this.btnLoading.style.display = loading ? 'inline' : 'none'
}
showMessage(text, type) {
this.message.textContent = text
this.message.className = `newsletter-message newsletter-message--${type}`
this.message.style.display = 'block'
setTimeout(() => {
this.message.style.display = 'none'
}, 5000)
}
}
// 初始化邮件订阅
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('[data-newsletter]').forEach(newsletter => {
new MailchimpNewsletter(newsletter)
})
})
</script>
2. Klaviyo 邮件营销集成
<!-- snippets/klaviyo-integration.liquid -->
{% if settings.klaviyo_public_key != blank %}
<script async type="text/javascript" src="https://static.klaviyo.com/onsite/js/klaviyo.js?company_id={{ settings.klaviyo_public_key }}"></script>
<script>
class KlaviyoIntegration {
static identify(customer) {
if (window._learnq) {
_learnq.push(['identify', {
'$email': customer.email,
'$first_name': customer.first_name,
'$last_name': customer.last_name,
'$phone_number': customer.phone,
'customer_id': customer.id.toString()
}]);
}
}
static track(event, properties = {}) {
if (window._learnq) {
_learnq.push(['track', event, properties]);
}
}
static viewedProduct(product) {
this.track('Viewed Product', {
'ProductID': product.id.toString(),
'ProductName': product.title,
'ProductURL': window.location.protocol + '//' + window.location.host + product.url,
'ProductImageURL': product.featured_image,
'Price': product.price / 100,
'CompareAtPrice': product.compare_at_price / 100,
'ProductType': product.type,
'ProductVendor': product.vendor,
'ProductTags': product.tags
});
}
static addedToCart(variant, quantity) {
this.track('Added to Cart', {
'ProductID': variant.product.id.toString(),
'ProductName': variant.product.title,
'ProductURL': window.location.protocol + '//' + window.location.host + variant.product.url,
'ProductImageURL': variant.product.featured_image,
'Price': variant.price / 100,
'CompareAtPrice': variant.compare_at_price / 100,
'ProductType': variant.product.type,
'ProductVendor': variant.product.vendor,
'Quantity': quantity,
'VariantID': variant.id.toString(),
'VariantTitle': variant.title
});
}
static startedCheckout(cart) {
const items = cart.items.map(item => ({
'ProductID': item.product.id.toString(),
'ProductName': item.product.title,
'Quantity': item.quantity,
'Price': item.price / 100,
'ProductURL': window.location.protocol + '//' + window.location.host + item.product.url,
'ProductImageURL': item.product.featured_image,
'VariantID': item.variant.id.toString(),
'VariantTitle': item.variant.title
}));
this.track('Started Checkout', {
'$event_id': cart.token,
'$value': cart.total_price / 100,
'Items': items,
'CheckoutURL': window.location.protocol + '//' + window.location.host + '/cart'
});
}
static subscribeToNewsletter(email) {
if (window._learnq) {
_learnq.push(['identify', { '$email': email }]);
}
}
}
// 自动识别已登录客户
{% if customer %}
KlaviyoIntegration.identify({
email: {{ customer.email | json }},
first_name: {{ customer.first_name | json }},
last_name: {{ customer.last_name | json }},
phone: {{ customer.phone | json }},
id: {{ customer.id }}
});
{% endif %}
window.KlaviyoIntegration = KlaviyoIntegration;
</script>
{% endif %}
客服和支持工具
1. Intercom 客服聊天
<!-- snippets/intercom-chat.liquid -->
{% if settings.intercom_app_id != blank %}
<script>
window.intercomSettings = {
app_id: "{{ settings.intercom_app_id }}",
{% if customer %}
name: "{{ customer.first_name }} {{ customer.last_name }}",
email: "{{ customer.email }}",
user_id: "{{ customer.id }}",
created_at: {{ customer.created_at | date: '%s' }},
customer_id: "{{ customer.id }}",
total_spent: {{ customer.total_spent | money_without_currency }},
orders_count: {{ customer.orders_count }},
tags: "shopify-customer"
{% else %}
name: "访客",
tags: "shopify-visitor"
{% endif %}
};
</script>
<script>
(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',w.intercomSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Intercom=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/{{ settings.intercom_app_id }}';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();
</script>
{% endif %}
2. Zendesk Chat 集成
<!-- snippets/zendesk-chat.liquid -->
{% if settings.zendesk_chat_key != blank %}
<script id="ze-snippet" src="https://static.zdassets.com/ekr/snippet.js?key={{ settings.zendesk_chat_key }}"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
if (window.zE) {
// 设置用户信息
{% if customer %}
zE('webWidget', 'prefill', {
name: {
value: '{{ customer.first_name }} {{ customer.last_name }}',
readOnly: true
},
email: {
value: '{{ customer.email }}',
readOnly: true
}
});
// 设置用户字段
zE('webWidget', 'identify', {
name: '{{ customer.first_name }} {{ customer.last_name }}',
email: '{{ customer.email }}',
external_id: '{{ customer.id }}',
organization: '{{ shop.name }}'
});
{% endif %}
// 自定义聊天触发
window.ZendeskChat = {
show: function() {
zE('webWidget', 'open');
},
hide: function() {
zE('webWidget', 'hide');
},
updateVisitorInfo: function(info) {
zE('webWidget', 'identify', info);
}
};
}
});
</script>
{% endif %}
支付和金融服务
1. PayPal Express Checkout
<!-- snippets/paypal-express.liquid -->
{% if settings.paypal_client_id != blank %}
<div id="paypal-button-container" style="display: none;"></div>
<script src="https://www.paypal.com/sdk/js?client-id={{ settings.paypal_client_id }}¤cy={{ cart.currency.iso_code }}&intent=capture&components=buttons,marks"></script>
<script>
class PayPalExpress {
constructor() {
this.init()
}
init() {
if (window.paypal && document.getElementById('paypal-button-container')) {
this.renderButton()
}
}
renderButton() {
paypal.Buttons({
style: {
shape: 'rect',
color: 'gold',
layout: 'vertical',
label: 'paypal'
},
createOrder: (data, actions) => {
return this.createOrder(actions)
},
onApprove: (data, actions) => {
return this.onApprove(data, actions)
},
onError: (err) => {
console.error('PayPal Error:', err)
this.showError('支付过程中发生错误,请重试')
}
}).render('#paypal-button-container')
}
async createOrder(actions) {
try {
// 获取当前购物车
const cart = await fetch('/cart.js').then(r => r.json())
const items = cart.items.map(item => ({
name: item.product_title,
unit_amount: {
currency_code: cart.currency,
value: (item.price / 100).toFixed(2)
},
quantity: item.quantity
}))
return actions.order.create({
purchase_units: [{
amount: {
currency_code: cart.currency,
value: (cart.total_price / 100).toFixed(2),
breakdown: {
item_total: {
currency_code: cart.currency,
value: (cart.total_price / 100).toFixed(2)
}
}
},
items: items
}]
})
} catch (error) {
console.error('Create order error:', error)
throw error
}
}
async onApprove(data, actions) {
try {
const order = await actions.order.capture()
// 重定向到Shopify结账页面,传递PayPal信息
const checkoutUrl = `/cart/checkout?paypal_order_id=${order.id}`
window.location.href = checkoutUrl
} catch (error) {
console.error('Capture order error:', error)
this.showError('支付确认失败,请联系客服')
}
}
showError(message) {
// 显示错误消息
const errorDiv = document.createElement('div')
errorDiv.className = 'paypal-error'
errorDiv.textContent = message
const container = document.getElementById('paypal-button-container')
container.parentNode.insertBefore(errorDiv, container.nextSibling)
setTimeout(() => {
errorDiv.remove()
}, 5000)
}
show() {
document.getElementById('paypal-button-container').style.display = 'block'
}
hide() {
document.getElementById('paypal-button-container').style.display = 'none'
}
}
// 初始化PayPal Express
document.addEventListener('DOMContentLoaded', () => {
window.PayPalExpress = new PayPalExpress()
})
</script>
{% endif %}
2. Stripe Elements 集成
<!-- snippets/stripe-elements.liquid -->
{% if settings.stripe_publishable_key != blank %}
<script src="https://js.stripe.com/v3/"></script>
<div id="stripe-elements-container" style="display: none;">
<div id="card-element">
<!-- Stripe Elements 将在这里插入卡片表单 -->
</div>
<div id="card-errors" role="alert"></div>
<button id="stripe-submit" class="btn btn--primary">
确认支付
</button>
</div>
<script>
class StripeElements {
constructor() {
this.stripe = Stripe('{{ settings.stripe_publishable_key }}')
this.elements = this.stripe.elements()
this.cardElement = null
this.init()
}
init() {
this.setupCardElement()
this.bindEvents()
}
setupCardElement() {
const style = {
base: {
color: '#424770',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#9e2146',
iconColor: '#9e2146'
}
}
this.cardElement = this.elements.create('card', { style })
this.cardElement.mount('#card-element')
this.cardElement.on('change', ({ error }) => {
const displayError = document.getElementById('card-errors')
if (error) {
displayError.textContent = error.message
} else {
displayError.textContent = ''
}
})
}
bindEvents() {
const submitButton = document.getElementById('stripe-submit')
submitButton.addEventListener('click', () => {
this.handleSubmit()
})
}
async handleSubmit() {
const { token, error } = await this.stripe.createToken(this.cardElement)
if (error) {
const errorElement = document.getElementById('card-errors')
errorElement.textContent = error.message
} else {
// 发送token到后端处理
this.submitFormWithToken(token.id)
}
}
async submitFormWithToken(tokenId) {
try {
// 创建结账会话
const response = await fetch('/checkout/create-payment-intent', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
payment_method: tokenId,
cart_token: {{ cart.token | json }}
})
})
const session = await response.json()
if (session.url) {
window.location.href = session.url
} else {
throw new Error('Failed to create checkout session')
}
} catch (error) {
console.error('Payment error:', error)
this.showError('支付失败,请重试')
}
}
showError(message) {
const errorElement = document.getElementById('card-errors')
errorElement.textContent = message
}
show() {
document.getElementById('stripe-elements-container').style.display = 'block'
}
hide() {
document.getElementById('stripe-elements-container').style.display = 'none'
}
}
// 初始化Stripe Elements
document.addEventListener('DOMContentLoaded', () => {
window.StripeElements = new StripeElements()
})
</script>
{% endif %}
社交媒体集成
1. Instagram Feed
<!-- snippets/instagram-feed.liquid -->
<div class="instagram-feed" data-instagram-feed>
<div class="instagram-header">
<h3>{{ section.settings.heading | default: 'Instagram动态' }}</h3>
{% if settings.instagram_username %}
<a href="https://instagram.com/{{ settings.instagram_username }}"
target="_blank"
class="instagram-follow">
关注我们
</a>
{% endif %}
</div>
<div class="instagram-grid" data-instagram-grid>
<!-- Instagram图片将通过JavaScript加载 -->
</div>
</div>
<script>
class InstagramFeed {
constructor(element) {
this.container = element
this.grid = element.querySelector('[data-instagram-grid]')
this.accessToken = '{{ settings.instagram_access_token }}'
this.limit = {{ section.settings.limit | default: 6 }}
if (this.accessToken) {
this.loadFeed()
}
}
async loadFeed() {
try {
const response = await fetch(
`https://graph.instagram.com/me/media?fields=id,caption,media_type,media_url,thumbnail_url,permalink&access_token=${this.accessToken}&limit=${this.limit}`
)
const data = await response.json()
if (data.data) {
this.renderFeed(data.data)
}
} catch (error) {
console.error('Instagram feed error:', error)
this.showError()
}
}
renderFeed(posts) {
const postsHtml = posts
.filter(post => post.media_type === 'IMAGE' || post.media_type === 'CAROUSEL_ALBUM')
.map(post => `
<a href="${post.permalink}"
target="_blank"
class="instagram-item"
aria-label="查看Instagram帖子">
<img src="${post.media_url}"
alt="${this.truncateCaption(post.caption)}"
loading="lazy"
class="instagram-image">
<div class="instagram-overlay">
<span class="instagram-icon">📷</span>
</div>
</a>
`).join('')
this.grid.innerHTML = postsHtml
}
truncateCaption(caption) {
if (!caption) return ''
return caption.length > 100 ? caption.substring(0, 100) + '...' : caption
}
showError() {
this.grid.innerHTML = `
<div class="instagram-error">
<p>无法加载Instagram动态</p>
</div>
`
}
}
// 初始化Instagram Feed
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('[data-instagram-feed]').forEach(feed => {
new InstagramFeed(feed)
})
})
</script>
2. 社交分享按钮
<!-- snippets/social-sharing.liquid -->
{% comment %}
社交分享按钮组件
参数:
- share_title: 分享标题 (可选)
- share_url: 分享链接 (可选)
- share_image: 分享图片 (可选)
{% endcomment %}
{% assign share_title = share_title | default: page_title | url_encode %}
{% assign share_url = share_url | default: canonical_url | url_encode %}
{% assign share_image = share_image | default: page_image | img_url: '1200x630' | url_encode %}
<div class="social-sharing">
<span class="social-sharing__label">分享:</span>
<div class="social-sharing__buttons">
<!-- Facebook -->
<a href="https://www.facebook.com/sharer/sharer.php?u={{ share_url }}"
target="_blank"
rel="noopener"
class="social-sharing__button social-sharing__button--facebook"
aria-label="分享到Facebook">
{% render 'icon-facebook' %}
</a>
<!-- Twitter -->
<a href="https://twitter.com/intent/tweet?text={{ share_title }}&url={{ share_url }}"
target="_blank"
rel="noopener"
class="social-sharing__button social-sharing__button--twitter"
aria-label="分享到Twitter">
{% render 'icon-twitter' %}
</a>
<!-- Pinterest -->
<a href="https://pinterest.com/pin/create/button/?url={{ share_url }}&media={{ share_image }}&description={{ share_title }}"
target="_blank"
rel="noopener"
class="social-sharing__button social-sharing__button--pinterest"
aria-label="分享到Pinterest">
{% render 'icon-pinterest' %}
</a>
<!-- WhatsApp -->
<a href="https://wa.me/?text={{ share_title }}%20{{ share_url }}"
target="_blank"
rel="noopener"
class="social-sharing__button social-sharing__button--whatsapp"
aria-label="通过WhatsApp分享">
{% render 'icon-whatsapp' %}
</a>
<!-- 微信 -->
<button type="button"
class="social-sharing__button social-sharing__button--wechat"
data-wechat-share
aria-label="分享到微信">
{% render 'icon-wechat' %}
</button>
<!-- 复制链接 -->
<button type="button"
class="social-sharing__button social-sharing__button--copy"
data-copy-link="{{ canonical_url }}"
aria-label="复制链接">
{% render 'icon-link' %}
</button>
</div>
</div>
<!-- 微信分享二维码模态框 -->
<div class="wechat-share-modal" data-wechat-modal style="display: none;">
<div class="wechat-share-modal__overlay"></div>
<div class="wechat-share-modal__content">
<div class="wechat-share-modal__header">
<h4>微信分享</h4>
<button class="wechat-share-modal__close" data-wechat-close>
{% render 'icon-close' %}
</button>
</div>
<div class="wechat-share-modal__body">
<div class="wechat-qr-code" data-wechat-qr></div>
<p>使用微信扫一扫分享给朋友</p>
</div>
</div>
</div>
<script>
class SocialSharing {
constructor() {
this.init()
}
init() {
this.bindEvents()
}
bindEvents() {
// 复制链接
document.addEventListener('click', (e) => {
if (e.target.matches('[data-copy-link]')) {
e.preventDefault()
this.copyLink(e.target.dataset.copyLink)
}
if (e.target.matches('[data-wechat-share]')) {
e.preventDefault()
this.showWeChatModal()
}
})
// 微信模态框事件
const wechatModal = document.querySelector('[data-wechat-modal]')
if (wechatModal) {
wechatModal.querySelector('[data-wechat-close]').addEventListener('click', () => {
this.hideWeChatModal()
})
wechatModal.querySelector('.wechat-share-modal__overlay').addEventListener('click', () => {
this.hideWeChatModal()
})
}
}
async copyLink(url) {
try {
await navigator.clipboard.writeText(url)
this.showNotification('链接已复制到剪贴板')
} catch (error) {
// 降级到传统方法
const textArea = document.createElement('textarea')
textArea.value = url
document.body.appendChild(textArea)
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
this.showNotification('链接已复制到剪贴板')
}
}
showWeChatModal() {
const modal = document.querySelector('[data-wechat-modal]')
const qrContainer = modal.querySelector('[data-wechat-qr]')
// 生成二维码
const currentUrl = window.location.href
qrContainer.innerHTML = `
<img src="https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(currentUrl)}"
alt="微信分享二维码"
class="wechat-qr-image">
`
modal.style.display = 'block'
document.body.style.overflow = 'hidden'
}
hideWeChatModal() {
const modal = document.querySelector('[data-wechat-modal]')
modal.style.display = 'none'
document.body.style.overflow = ''
}
showNotification(message) {
const notification = document.createElement('div')
notification.className = 'notification notification--success'
notification.textContent = message
document.body.appendChild(notification)
setTimeout(() => {
notification.classList.add('notification--show')
}, 100)
setTimeout(() => {
notification.classList.remove('notification--show')
setTimeout(() => notification.remove(), 300)
}, 3000)
}
}
// 初始化社交分享
document.addEventListener('DOMContentLoaded', () => {
new SocialSharing()
})
</script>
下一步学习
掌握第三方集成后,建议继续学习:
- 测试和部署 - 质量保证流程
第三方集成是提升网站功能和用户体验的重要手段!
最后更新时间: