Overview
GoBlue supports sending various types of attachments alongside your automated messages, including images, documents, links, and rich media content. This capability enhances your messaging by providing visual context, supporting materials, and interactive elements that increase engagement and effectiveness.
Attachment support depends on the recipient’s device and messaging platform. iMessage supports rich attachments, while SMS has more limitations.
Supported Attachment Types
Images Formats : JPG, PNG, GIF, HEIC
Max Size : 10 MB per image
Use Cases : Product photos, screenshots, infographics, QR codes
Videos Formats : MP4, MOV, M4V
Max Size : 100 MB per video
Use Cases : Product demos, tutorials, testimonials
Audio Formats : MP3, M4A, WAV
Max Size : 25 MB per audio file
Use Cases : Voice messages, audio previews, recordings
Documents Formats : PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX
Max Size : 50 MB per document
Use Cases : Proposals, contracts, presentations, reports
Rich Link Previews
GoBlue automatically generates rich previews for web links:
Features : Title, description, preview image
Best For : Blog posts, landing pages, product pagesCheck out our latest case study: https://yoursite.com/case-study
Generates : Rich preview with title, description, and featured image
Services : Google Drive, Dropbox, OneDrive
Features : File type icons, document names, sharing permissionsHere's your proposal: https://drive.google.com/file/d/abc123/view
Adding Attachments to Messages
Method 1: URL-Based Attachments
Include attachment URLs in your webhook data:
{
"firstName" : "Sarah" ,
"phoneNumber" : "+1234567890" ,
"serviceType" : "web development" ,
"attachments" : [
{
"type" : "image" ,
"url" : "https://yoursite.com/images/portfolio-sample.jpg" ,
"caption" : "Sample of our recent work"
},
{
"type" : "document" ,
"url" : "https://yoursite.com/files/service-guide.pdf" ,
"filename" : "Web Development Service Guide.pdf"
}
]
}
Message Template :
Hi {{firstName}},
Thanks for your interest in {{serviceType}}!
I've attached a sample of our recent work and our service guide for your review.
Looking forward to discussing your project!
Best regards,
{{agentName}}
{{#attachments}}
📎 {{caption}}
{{/attachments}}
Method 2: Dynamic Attachment Selection
Use form data to determine which attachments to include:
// Example: Industry-specific attachments
const attachmentLibrary = {
'healthcare' : [
{
type: 'document' ,
url: 'https://yoursite.com/docs/hipaa-compliance.pdf' ,
filename: 'HIPAA Compliance Guide.pdf'
}
],
'e-commerce' : [
{
type: 'image' ,
url: 'https://yoursite.com/images/ecommerce-portfolio.jpg' ,
caption: 'E-commerce Projects Portfolio'
}
],
'saas' : [
{
type: 'video' ,
url: 'https://yoursite.com/videos/saas-demo.mp4' ,
caption: 'SaaS Platform Demo'
}
]
};
function selectAttachments ( contactData ) {
const industry = contactData . industry || contactData . serviceType ;
return attachmentLibrary [ industry ] || [];
}
Method 3: iOS Shortcuts Integration
Configure iOS Shortcuts to handle different attachment types:
Image Attachments
Document Attachments
Multiple Attachments
Shortcut Steps :
Get message content from GoBlue
Extract attachment URLs from message data
Download images to Photos app
Send message with images attached
GoBlue Integration :{
"messageContent" : "Hi John, here's the mockup you requested!" ,
"attachments" : [
{
"type" : "image" ,
"url" : "https://yoursite.com/mockups/johns-project.png"
}
]
}
Attachment Strategies by Use Case
Sales and Lead Generation
Attachment Types : Images, videos, PDFs
Template Example :Hi {{firstName}},
Thanks for your interest in {{serviceType}}!
I've attached some samples of our work with similar {{industryType}} clients. The {{attachmentDescription}} should give you a good sense of our capabilities.
I'd love to discuss how we could create something similar for {{companyName}}.
Available for a quick call this week?
Best,
{{agentName}}
Dynamic Attachment Selection :function selectPortfolioSamples ( industry , budget ) {
const samples = portfolioLibrary [ industry ] || [];
// Filter by budget tier
if ( budget < 5000 ) {
return samples . filter ( s => s . tier === 'basic' );
} else if ( budget > 20000 ) {
return samples . filter ( s => s . tier === 'premium' );
}
return samples . filter ( s => s . tier === 'standard' );
}
Attachment Types : PDFs, spreadsheets, presentations
Template Example :Hi {{firstName}},
I've prepared a custom proposal for your {{projectType}} project.
The attached document includes:
• Project timeline and milestones
• Detailed pricing breakdown
• Team member profiles
• Similar client case studies
Please review and let me know if you have any questions. I'm available to discuss any aspects of the proposal.
Looking forward to working together!
{{agentName}}
Case Studies and Testimonials
Attachment Types : PDFs, images, videos
Implementation :function selectCaseStudies ( contactData ) {
const relevant = caseStudyLibrary . filter ( study =>
study . industry === contactData . industry ||
study . projectType === contactData . serviceType ||
study . companySize === contactData . companySize
);
// Return top 2-3 most relevant
return relevant
. sort (( a , b ) => b . relevanceScore - a . relevanceScore )
. slice ( 0 , 3 );
}
Customer Service and Support
Use Case : Onboarding new customers
Template :Hi {{firstName}},
Welcome to {{productName}}!
I've attached a quick video tutorial that will help you get started with {{specificFeature}}.
The video is just {{videoDuration}} and covers:
• Initial setup steps
• Key features for your {{useCase}}
• Pro tips for maximum efficiency
Watch when convenient, and feel free to reach out with any questions!
{{supportTeamName}}
Attachment Types : PDFs, screenshots, screen recordings
Dynamic Content :function generateTroubleshootingGuide ( issueType , userPlatform ) {
const guide = {
steps: getTroubleshootingSteps ( issueType ),
screenshots: getScreenshots ( issueType , userPlatform ),
additionalInfo: getAdditionalResources ( issueType )
};
return generatePDF ( guide );
}
E-commerce and Retail
Use Case : Order confirmations, product recommendations
Template :Hi {{firstName}},
Your order #{{orderNumber}} has shipped! 🎉
I've attached photos of your {{productName}} being carefully packaged. Your order includes:
{{#orderItems}}
• {{itemName}} ({{quantity}}x)
{{/orderItems}}
Tracking: {{trackingUrl}}
Expected delivery: {{deliveryDate}}
Thanks for choosing {{companyName}}!
Attachment Types : Images, PDFs
Implementation :function attachSizeGuide ( productCategory , customerData ) {
const sizeChart = getSizeChart ( productCategory );
const personalizedGuide = generatePersonalizedGuide (
sizeChart ,
customerData . previousOrders
);
return {
type: 'image' ,
url: personalizedGuide . url ,
caption: `Size guide for ${ productCategory } `
};
}
Advanced Attachment Features
Conditional Attachments
Use webhook data to determine which attachments to include:
{
"firstName" : "John" ,
"phoneNumber" : "+1234567890" ,
"serviceType" : "web development" ,
"budget" : "$10,000+" ,
"hasSeenDemo" : false ,
"industry" : "healthcare" ,
"attachmentRules" : [
{
"condition" : "budget > 5000" ,
"attachments" : [ "premium-portfolio.pdf" , "enterprise-case-study.pdf" ]
},
{
"condition" : "hasSeenDemo === false" ,
"attachments" : [ "product-demo-video.mp4" ]
},
{
"condition" : "industry === 'healthcare'" ,
"attachments" : [ "hipaa-compliance-doc.pdf" ]
}
]
}
Personalized Attachments
Generate custom attachments based on recipient data:
class PersonalizedAttachmentGenerator {
async generateProposal ( contactData ) {
const template = await this . getProposalTemplate ();
const personalizedData = {
clientName: ` ${ contactData . firstName } ${ contactData . lastName } ` ,
companyName: contactData . companyName ,
projectDetails: contactData . projectDescription ,
timeline: contactData . timeline ,
budget: contactData . budget ,
customizations: this . getRecommendations ( contactData )
};
const proposalPDF = await this . generatePDF ( template , personalizedData );
return {
type: 'document' ,
url: proposalPDF . url ,
filename: `Proposal_ ${ contactData . companyName } _ ${ Date . now () } .pdf`
};
}
async generateQRCode ( contactData , campaign ) {
const qrData = {
url: ` ${ campaign . landingPageUrl } ?ref= ${ contactData . id } ` ,
contactId: contactData . id ,
campaignId: campaign . id
};
const qrImage = await this . generateQR ( qrData );
return {
type: 'image' ,
url: qrImage . url ,
caption: 'Scan to access your personalized page'
};
}
}
Interactive Attachments
Create attachments that encourage engagement:
QR Codes
Calendly Links
Survey Forms
Use Cases :
Event registration
Exclusive offers
Contact information sharing
App downloads
function createQRCode ( action , contactId ) {
const qrData = {
action: action ,
contactId: contactId ,
timestamp: Date . now (),
trackingUrl: `https://yoursite.com/track/ ${ action } / ${ contactId } `
};
return generateQRCode ( qrData );
}
Technical Implementation
File Storage and Management
Cloud Storage Integration
Supported Services : AWS S3, Google Cloud Storage, Azure Blobclass AttachmentManager {
async uploadFile ( file , metadata ) {
const storageKey = `attachments/ ${ metadata . campaignId } / ${ file . name } ` ;
const uploadResult = await this . cloudStorage . upload ({
key: storageKey ,
body: file . buffer ,
contentType: file . mimeType ,
metadata: {
originalName: file . name ,
uploadedBy: metadata . userId ,
campaignId: metadata . campaignId ,
expiresAt: metadata . expiresAt
}
});
return {
url: uploadResult . publicUrl ,
storageKey: storageKey ,
size: file . size ,
contentType: file . mimeType
};
}
}
Benefits : Faster downloads, global distribution, bandwidth optimizationfunction generateCDNUrl ( attachmentKey , transformations = {}) {
const baseUrl = 'https://cdn.yoursite.com' ;
const params = new URLSearchParams ();
// Image transformations
if ( transformations . width ) params . set ( 'w' , transformations . width );
if ( transformations . height ) params . set ( 'h' , transformations . height );
if ( transformations . quality ) params . set ( 'q' , transformations . quality );
return ` ${ baseUrl } / ${ attachmentKey } ? ${ params . toString () } ` ;
}
Security : Generate expiring URLs for sensitive documentsfunction generateTemporaryUrl ( attachmentKey , expirationHours = 24 ) {
const expiresAt = Date . now () + ( expirationHours * 60 * 60 * 1000 );
const signature = generateSignature ( attachmentKey , expiresAt );
return `https://secure.yoursite.com/attachments/ ${ attachmentKey } ?expires= ${ expiresAt } &sig= ${ signature } ` ;
}
iOS Shortcuts Integration
Shortcut Structure for Attachments :
Retrieve Message Data
Get message content and attachment metadata from GoBlue API
Download Attachments
// Download each attachment
for ( const attachment of message . attachments ) {
const fileData = await downloadFile ( attachment . url );
attachmentFiles . push ({
data: fileData ,
filename: attachment . filename || extractFilename ( attachment . url ),
type: attachment . type
});
}
Prepare Message
Combine text content with attachment files
Send via iMessage
Use iOS Shortcuts actions to send message with attachments
Update Status
Report delivery status back to GoBlue
Error Handling
const sizeLimits = {
image: 10 * 1024 * 1024 , // 10 MB
video: 100 * 1024 * 1024 , // 100 MB
document: 50 * 1024 * 1024 , // 50 MB
audio: 25 * 1024 * 1024 // 25 MB
};
function validateFileSize ( attachment ) {
const limit = sizeLimits [ attachment . type ];
if ( attachment . size > limit ) {
throw new Error ( `File too large: ${ attachment . type } limit is ${ limit } bytes` );
}
}
async function downloadWithRetry ( url , maxRetries = 3 ) {
for ( let attempt = 1 ; attempt <= maxRetries ; attempt ++ ) {
try {
const response = await fetch ( url , { timeout: 30000 });
if ( response . ok ) {
return await response . buffer ();
}
} catch ( error ) {
if ( attempt === maxRetries ) {
throw new Error ( `Failed to download after ${ maxRetries } attempts: ${ error . message } ` );
}
// Wait before retry
await new Promise ( resolve => setTimeout ( resolve , attempt * 1000 ));
}
}
}
function handleAttachmentFailure ( message , failedAttachment ) {
// Remove failed attachment
message . attachments = message . attachments . filter ( a => a !== failedAttachment );
// Add fallback text
message . content += ` \n\n 📎 Attachment unavailable. View online: ${ failedAttachment . fallbackUrl } ` ;
// Log for manual review
this . logAttachmentFailure ( message . id , failedAttachment );
return message ;
}
Analytics and Tracking
Engagement Metrics
Download Rate : % of recipients who download attachments
View Time : How long recipients view media
Click-through Rate : Clicks on links in attachments
Sharing Rate : How often attachments are forwarded
Technical Metrics
Delivery Success Rate : % of attachments delivered successfully
File Size Impact : Effect on message delivery time
Format Performance : Which file types perform best
Error Rates : Common attachment failures
Tracking Implementation
class AttachmentAnalytics {
trackAttachmentPerformance ( messageId , attachmentId , event ) {
const trackingData = {
messageId: messageId ,
attachmentId: attachmentId ,
event: event , // 'sent', 'downloaded', 'viewed', 'shared'
timestamp: new Date (). toISOString (),
userAgent: this . getUserAgent (),
ipAddress: this . getClientIP ()
};
return this . analytics . track ( 'attachment_event' , trackingData );
}
generateAttachmentReport ( campaignId ) {
const attachmentStats = this . getAttachmentStats ( campaignId );
return {
totalAttachments: attachmentStats . total ,
deliveryRate: attachmentStats . delivered / attachmentStats . total ,
downloadRate: attachmentStats . downloaded / attachmentStats . delivered ,
topPerformingTypes: this . getTopPerformingTypes ( attachmentStats ),
sizingRecommendations: this . getSizingRecommendations ( attachmentStats )
};
}
}
Best Practices
Content Guidelines
File Optimization
Compress images without losing quality
Use appropriate formats (JPEG for photos, PNG for graphics)
Keep file sizes reasonable for mobile networks
Test downloads on different connection speeds
Accessibility
Include alt text for images
Provide text descriptions for videos
Use descriptive filenames
Consider recipients with disabilities
Security
Don’t include sensitive information in filenames
Use secure, expiring URLs for confidential documents
Scan files for malware before sending
Implement access controls for attachments
User Experience
Preview attachments in your message text
Explain why you’re including attachments
Provide alternative access methods
Keep attachment lists concise
// Only download attachments when message is being sent
async function prepareMessageForSending ( message ) {
const attachments = await Promise . all (
message . attachmentUrls . map ( url => this . downloadAttachment ( url ))
);
return {
... message ,
attachments: attachments . filter ( a => a !== null ) // Remove failed downloads
};
}
class AttachmentCache {
constructor () {
this . cache = new Map ();
this . maxSize = 100 * 1024 * 1024 ; // 100 MB cache
}
async getAttachment ( url ) {
if ( this . cache . has ( url )) {
return this . cache . get ( url );
}
const attachment = await this . downloadAttachment ( url );
if ( this . getCacheSize () + attachment . size <= this . maxSize ) {
this . cache . set ( url , attachment );
}
return attachment ;
}
}
Next Steps
Test your attachments across different devices and network conditions to ensure a consistent experience for all recipients.