feat(website): serve Windows from the Microsoft Store and tag store campaigns
The Windows button downloaded plezy-windows-installer.exe from the latest release. It now opens the Store listing, which brings Store-managed updates. The endpoint redirects to ms-windows-store://, so the button only resolves on Windows; macOS and Linux keep their direct release downloads. Store links carry campaign parameters (ct=Landing, utm_campaign=landing, cid=landing) so landing-page traffic separates from the README's in each store's own reporting. Play reports utm_source and utm_campaign, so no utm_medium is sent. Structured data keeps untagged canonical URLs: schema.org offers are consumed by search engines, and a rich-result click is not landing-page traffic.
This commit is contained in:
@@ -5,7 +5,13 @@
|
|||||||
import AmazonIcon from "~icons/cib/amazon";
|
import AmazonIcon from "~icons/cib/amazon";
|
||||||
import ChevronDownIcon from "~icons/heroicons/chevron-down-solid";
|
import ChevronDownIcon from "~icons/heroicons/chevron-down-solid";
|
||||||
import WindowsIcon from "./WindowsIcon.svelte";
|
import WindowsIcon from "./WindowsIcon.svelte";
|
||||||
import { AMAZON_URL, linuxArchitectures, releaseAsset, storeOptions } from "$lib/content/downloads";
|
import {
|
||||||
|
AMAZON_URL,
|
||||||
|
linuxArchitectures,
|
||||||
|
MICROSOFT_STORE_URL,
|
||||||
|
releaseAsset,
|
||||||
|
storeOptions,
|
||||||
|
} from "$lib/content/downloads";
|
||||||
|
|
||||||
const componentId = $props.id();
|
const componentId = $props.id();
|
||||||
const linuxPanelId = `${componentId}-linux-downloads`;
|
const linuxPanelId = `${componentId}-linux-downloads`;
|
||||||
@@ -67,7 +73,9 @@
|
|||||||
<!-- Desktop row -->
|
<!-- Desktop row -->
|
||||||
<div class="desktop-buttons">
|
<div class="desktop-buttons">
|
||||||
<a
|
<a
|
||||||
href={releaseAsset("plezy-windows-installer.exe")}
|
href={MICROSOFT_STORE_URL}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
class="desktop-button"
|
class="desktop-button"
|
||||||
>
|
>
|
||||||
<WindowsIcon />
|
<WindowsIcon />
|
||||||
|
|||||||
@@ -16,6 +16,17 @@ export const APP_STORE_ID = '6754315964';
|
|||||||
export const ANDROID_PACKAGE = 'com.edde746.plezy';
|
export const ANDROID_PACKAGE = 'com.edde746.plezy';
|
||||||
export const AMAZON_URL = 'https://www.amazon.com/gp/product/B0GK65CVS1';
|
export const AMAZON_URL = 'https://www.amazon.com/gp/product/B0GK65CVS1';
|
||||||
|
|
||||||
|
// Untagged product URLs for structured data. Campaign-tagged URLs belong on
|
||||||
|
// links a visitor actually clicks here; attributing a search rich-result click
|
||||||
|
// to the site's own campaign would be wrong.
|
||||||
|
export const APP_STORE_CANONICAL_URL = `https://apps.apple.com/us/app/id${APP_STORE_ID}`;
|
||||||
|
export const PLAY_STORE_CANONICAL_URL = `https://play.google.com/store/apps/details?id=${ANDROID_PACKAGE}`;
|
||||||
|
|
||||||
|
// Microsoft Store. `cid` is the Partner Center campaign code; `referrer=appbadge`
|
||||||
|
// is the value Microsoft's own badge snippet emits for this endpoint.
|
||||||
|
export const MICROSOFT_STORE_URL =
|
||||||
|
'https://get.microsoft.com/installer/download/9n5r1s1t68h7?referrer=appbadge&cid=landing';
|
||||||
|
|
||||||
export const releaseAsset = (name: string) =>
|
export const releaseAsset = (name: string) =>
|
||||||
`https://github.com/edde746/plezy/releases/latest/download/${name}`;
|
`https://github.com/edde746/plezy/releases/latest/download/${name}`;
|
||||||
|
|
||||||
@@ -23,12 +34,14 @@ export const storeOptions = {
|
|||||||
ios: {
|
ios: {
|
||||||
id: 'app-store',
|
id: 'app-store',
|
||||||
label: 'App Store',
|
label: 'App Store',
|
||||||
url: `https://apps.apple.com/us/app/id${APP_STORE_ID}`,
|
// pt/ct/mt: App Store Analytics campaign link (Analytics > Acquisition > Campaigns).
|
||||||
|
url: `https://apps.apple.com/app/apple-store/id${APP_STORE_ID}?pt=128238902&ct=Landing&mt=8`,
|
||||||
},
|
},
|
||||||
android: {
|
android: {
|
||||||
id: 'play-store',
|
id: 'play-store',
|
||||||
label: 'Google Play',
|
label: 'Google Play',
|
||||||
url: `https://play.google.com/store/apps/details?id=${ANDROID_PACKAGE}`,
|
// referrer: URL-encoded UTM pair; Play Console reports utm_source/utm_campaign.
|
||||||
|
url: `${PLAY_STORE_CANONICAL_URL}&referrer=utm_source%3Dplezy.app%26utm_campaign%3Dlanding`,
|
||||||
},
|
},
|
||||||
} as const satisfies Record<'ios' | 'android', StoreOption>;
|
} as const satisfies Record<'ios' | 'android', StoreOption>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { AMAZON_URL, storeOptions } from './downloads';
|
import {
|
||||||
|
AMAZON_URL,
|
||||||
|
APP_STORE_CANONICAL_URL,
|
||||||
|
PLAY_STORE_CANONICAL_URL,
|
||||||
|
} from './downloads';
|
||||||
|
|
||||||
export type StorePrices = {
|
export type StorePrices = {
|
||||||
appStorePrice: string | null;
|
appStorePrice: string | null;
|
||||||
@@ -25,7 +29,7 @@ export function buildSoftwareApplicationOffers({
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
'@type': 'Offer',
|
'@type': 'Offer',
|
||||||
url: storeOptions.ios.url,
|
url: APP_STORE_CANONICAL_URL,
|
||||||
category: 'App Store',
|
category: 'App Store',
|
||||||
...(appStorePrice === null
|
...(appStorePrice === null
|
||||||
? {}
|
? {}
|
||||||
@@ -36,7 +40,7 @@ export function buildSoftwareApplicationOffers({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'@type': 'Offer',
|
'@type': 'Offer',
|
||||||
url: storeOptions.android.url,
|
url: PLAY_STORE_CANONICAL_URL,
|
||||||
category: 'Google Play',
|
category: 'Google Play',
|
||||||
...(playStorePrice === null
|
...(playStorePrice === null
|
||||||
? {}
|
? {}
|
||||||
|
|||||||
Reference in New Issue
Block a user