Improve goal sharing experience
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Portfolio Journal - Goal Progress</title>
|
||||
|
||||
<!--
|
||||
IMPORTANT: For proper social media previews, Open Graph tags must be rendered server-side.
|
||||
|
||||
Options:
|
||||
1. Use a serverless function (Vercel, Netlify, Cloudflare Workers) to read query params and inject OG tags
|
||||
2. Use a service like htmlrewriter or edge functions
|
||||
3. Use a simple server (Node.js, PHP, etc.)
|
||||
|
||||
The URL format from the app is:
|
||||
https://portfoliojournal.app/share?goal=My%20Goal&progress=42
|
||||
|
||||
Your server should read these params and set:
|
||||
- og:title = "I'm 42% towards my 'My Goal' goal!"
|
||||
- og:description = "Track your investment goals with Portfolio Journal"
|
||||
-->
|
||||
|
||||
<!-- Default/Fallback Meta Tags (shown when no params or for non-social contexts) -->
|
||||
<meta name="title" content="Portfolio Journal - Track Your Investment Goals">
|
||||
<meta name="description" content="Set financial goals, track your progress, and celebrate your investment milestones. Available on the App Store.">
|
||||
<meta name="keywords" content="investment tracker, portfolio tracker, financial goals, investment app, iOS app, wealth tracking, goal sharing">
|
||||
<meta name="author" content="Portfolio Journal">
|
||||
|
||||
<!-- Open Graph / Facebook - These should be dynamic on your server -->
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" id="og-url" content="https://portfoliojournal.app/share">
|
||||
<meta property="og:title" id="og-title" content="I'm making progress on my investment goal! 🎯">
|
||||
<meta property="og:description" content="Track your investment goals with Portfolio Journal. Download now on the App Store.">
|
||||
<meta property="og:image" content="https://portfoliojournal.app/images/og-share-card.png">
|
||||
<meta property="og:image:width" content="1200">
|
||||
<meta property="og:image:height" content="630">
|
||||
<meta property="og:site_name" content="Portfolio Journal">
|
||||
<meta property="og:locale" content="en_US">
|
||||
|
||||
<!-- Twitter Card -->
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:url" id="twitter-url" content="https://portfoliojournal.app/share">
|
||||
<meta name="twitter:title" id="twitter-title" content="I'm making progress on my investment goal! 🎯">
|
||||
<meta name="twitter:description" content="Track your investment goals with Portfolio Journal. Download now on the App Store.">
|
||||
<meta name="twitter:image" content="https://portfoliojournal.app/images/og-share-card.png">
|
||||
|
||||
<!-- Apple Smart App Banner -->
|
||||
<meta name="apple-itunes-app" content="app-id=6744983373">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/png" href="/favicon.png">
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
||||
|
||||
<!-- Canonical URL -->
|
||||
<link rel="canonical" id="canonical-url" href="https://portfoliojournal.app/share">
|
||||
|
||||
<!-- Schema.org structured data -->
|
||||
<script type="application/ld+json" id="schema-data">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebPage",
|
||||
"name": "Goal Progress - Portfolio Journal",
|
||||
"description": "Track your investment goals with Portfolio Journal",
|
||||
"url": "https://portfoliojournal.app/share",
|
||||
"mainEntity": {
|
||||
"@type": "MobileApplication",
|
||||
"name": "Portfolio Journal",
|
||||
"operatingSystem": "iOS",
|
||||
"applicationCategory": "FinanceApplication",
|
||||
"downloadUrl": "https://apps.apple.com/app/portfolio-journal/id6744983373"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
color: white;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.app-icon {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 22px;
|
||||
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.goal-card {
|
||||
background: rgba(255,255,255,0.15);
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: 20px;
|
||||
padding: 24px;
|
||||
margin-bottom: 24px;
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.goal-label {
|
||||
font-size: 0.85rem;
|
||||
opacity: 0.8;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.goal-name {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
background: rgba(255,255,255,0.2);
|
||||
border-radius: 10px;
|
||||
height: 12px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
background: white;
|
||||
height: 100%;
|
||||
border-radius: 10px;
|
||||
transition: width 0.5s ease;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tagline {
|
||||
font-size: 1rem;
|
||||
opacity: 0.9;
|
||||
margin-bottom: 24px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.download-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
background: white;
|
||||
color: #667eea;
|
||||
padding: 14px 28px;
|
||||
border-radius: 14px;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.2);
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.download-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 30px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.download-btn svg {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 32px;
|
||||
font-size: 0.85rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<!-- App Icon -->
|
||||
<img src="/images/app-icon.png" alt="Portfolio Journal" class="app-icon">
|
||||
|
||||
<!-- Goal Progress Card (shown when params present) -->
|
||||
<div class="goal-card" id="goal-card">
|
||||
<div class="goal-label">Goal Progress</div>
|
||||
<div class="goal-name" id="goal-name">Investment Goal</div>
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill" id="progress-fill" style="width: 0%"></div>
|
||||
</div>
|
||||
<div class="progress-text"><span id="progress-text">0</span>% complete</div>
|
||||
</div>
|
||||
|
||||
<h1>Portfolio Journal</h1>
|
||||
<p class="tagline">Track your investment goals and celebrate your financial milestones.</p>
|
||||
|
||||
<a href="https://apps.apple.com/app/portfolio-journal/id6744983373" class="download-btn">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"/>
|
||||
</svg>
|
||||
Download Free
|
||||
</a>
|
||||
|
||||
<p class="footer">
|
||||
<a href="https://portfoliojournal.app">portfoliojournal.app</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Read URL parameters and update the page
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const goalName = params.get('goal');
|
||||
const progress = parseInt(params.get('progress')) || 0;
|
||||
|
||||
if (goalName) {
|
||||
// Update visible content
|
||||
document.getElementById('goal-name').textContent = goalName;
|
||||
document.getElementById('progress-text').textContent = progress;
|
||||
document.getElementById('progress-fill').style.width = progress + '%';
|
||||
|
||||
// Update page title
|
||||
document.title = `${progress}% towards "${goalName}" - Portfolio Journal`;
|
||||
|
||||
// Note: These JavaScript updates won't affect social media crawlers
|
||||
// as they don't execute JavaScript. You need server-side rendering for that.
|
||||
} else {
|
||||
// Hide goal card if no params
|
||||
document.getElementById('goal-card').classList.add('hidden');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user