Get Involved
No items added to cart
No items added to cart
Allow users to download the CPT info data as .vcf card for adding into phone contacts.
First, read about .vcf card properties and how to use them here: https://en.wikipedia.org/wiki/VCard
In the CPT single post template:
1. Add an elementor button widget, name it and style it as you like and add the ID "downloadBtn".
If you want to change the ID you'll need to change it accordingly also in the js script snippet.
2. Add an elementor html widget, enable dynamic tags and paste the below code here.
3. Edit the code by adding your dynamic tags into the VCARD property fields as well as into those 2 lines from javascript that controls the photo url base64 encoding and generation of card name from post title.
const dynamicData = {
logoUrl: '@post(logo.url)',
title: '@post(title)'
};
4. This code has been tested only with .jpg file format for default logo field.
5. Modify, extend and improve the VCARD information by reading about .vcf card properties provided in the wiki link above.
<pre id="vcard-data" style="display:none">
BEGIN:VCARD
VERSION:3.0
FN:@post(title)
PHOTO;TYPE=JPEG;ENCODING=b:@base64Photo
ORG:@post(taxonomy.label).first()
TITLE:@post(text-2)
TEL;TYPE=WORK:@post(phone)
EMAIL:@post(email)
ADR;TYPE=WORK,PREF:@post(location.medium_address)
URL;CHARSET=utf-8:@post(website)
URL;TYPE=Facebook:@post(url-2)
PROFILE:VCARD
END:VCARD
</pre><script>
// Sample dynamic data simulating post values; replace with real dynamic data as needed
const dynamicData = {
logoUrl: '@post(logo.url)',
title: '@post(title)'
};// Utility function to convert image URL to base64 string (async)
function convertImageURLToBase64(imageUrl) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'Anonymous'; // Important for CORS images
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
try {
const dataURL = canvas.toDataURL('image/jpeg');
const base64 = dataURL.replace(/^data:image\/(png|jpeg|jpg);base64,/, '');
resolve(base64);
} catch (e) {
reject(e);
}
};
img.onerror = () => reject(new Error('Failed to load image at ' + imageUrl));
img.src = imageUrl;
});
}document.getElementById("downloadBtn").addEventListener("click", async () => {
try {
// Get the vCard template string from the <pre>
let vcardTemplate = document.getElementById('vcard-data').innerText;// Convert the logo URL to base64 string
const base64Photo = await convertImageURLToBase64(dynamicData.logoUrl);// Replace the base64 image placeholder @base64Photo with actual base64 string
vcardTemplate = vcardTemplate.replace('@base64Photo', base64Photo);// Create Blob for downloading
const blob = new Blob([vcardTemplate], { type: 'text/vcard' });// Create download link
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = dynamicData.title.replace(/\s+/g, '_') + '.vcf';// Trigger download
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(link.href);
} catch (err) {
alert('Failed to generate vCard: ' + err.message);
console.error(err);
}
});
</script>
Are you sure you want to exit? Your current conversation will be lost.