This package will get metadata (title, image, etc.) for a given URL and use it to prefill other form fields.

Config

You’ll need to configure the embedProvider setting as well as at least one provider (unless you’re using the builtin method).

In your private settings:

1
2
3
4
"embedProvider": "builtin",
"embedly": {
"apiKey": "123foo"
},

Possible providers include:

Form Component

Inside forms, you can use the EmbedURL component to display a special URL field that will prefill other fields based on its own value whenever that value changes.

Prefillable fields include:

  • title: the title of the linked URL.
  • body: the description of the URL.
  • thumbnailUrl: a thumbnail image of the URL.
  • media: a media embed, for example a YouTube video embed.
  • sourceName: the source name, for example the name of a YouTube channel.
  • sourceUrl: the source URL, for example the URL of a YouTube channel.

Here’s an example of including these fields as custom fields on the Posts collection (which already includes its own title and body):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import Posts from '../posts/index.js';
import { EmbedlyURL } from 'meteor/vulcan:embed';

Posts.addField([
{
fieldName: 'url',
fieldSchema: {
control: EmbedlyURL, // we are just extending the field url, not replacing it
}
},
{
fieldName: 'thumbnailUrl',
fieldSchema: {
type: String,
optional: true,
insertableBy: ['members'],
editableBy: ['members'],
viewableBy: ['guests'],
hidden: true
}
},
{
fieldName: 'media',
fieldSchema: {
type: Object,
optional: true,
blackbox: true,
viewableBy: ['guests'],
}
},
{
fieldName: 'sourceName',
fieldSchema: {
type: String,
optional: true,
viewableBy: ['guests'],
}
},
{
fieldName: 'sourceUrl',
fieldSchema: {
type: String,
optional: true,
viewableBy: ['guests'],
}
}
]);

Mutations

The package exposes the following GraphQL mutation:

1
getEmbedData(url: String) : JSON

Custom Providers

To add a new provider, follow this structure to implement the Embed.myProvider.getData function:

1
2
3
4
5
6
7
8
9
10
11
12
import { Embed } from 'meteor/vulcan:embed';

Embed.myProvider = {

getData(url) {

const metadata = getMyData(url);

return metadata; // title, description, thumbnailUrl, etc.
}

}

Then set the embedProvider setting to myProvider.

Callbacks

You can use callbacks to generate embedded media server-side:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/*

Callbacks to add media/thumbnail after submit and on edit

*/

import { addCallback, getSetting, registerSetting } from 'meteor/vulcan:core';
import { Embed } from 'meteor/vulcan:embed';

const embedProvider = getSetting('embedProvider');

// For security reason, we make the media property non-modifiable by the client and
// we use a separate server-side API call to set it (and the thumbnail object if it hasn't already been set)

// Async variant that directly modifies the post object with update()
function AddMediaAfterSubmit (post) {

if(post.url){

const data = Embed[embedProvider].getData(post.url);

if (data) {

// only add a thumbnailUrl if there isn't one already
if (!post.thumbnailUrl && data.thumbnailUrl) {
post.thumbnailUrl = data.thumbnailUrl;
}

// add media if necessary
if (data.media && data.media.html) {
post.media = data.media;
}

// add source name & url if they exist
if (data.sourceName && data.sourceUrl) {
post.sourceName = data.sourceName;
post.sourceUrl = data.sourceUrl;
}

}

}

return post;
}
addCallback('posts.new.sync', AddMediaAfterSubmit);

function updateMediaOnEdit (modifier, post) {

const newUrl = modifier.$set.url;

if(newUrl && newUrl !== post.url){

const data = Embed[embedProvider].getData(newUrl);

if(data) {

if (data.media && data.media.html) {
if (modifier.$unset.media) {
delete modifier.$unset.media
}
modifier.$set.media = data.media;
}

// add source name & url if they exist
if (data.sourceName && data.sourceUrl) {
modifier.$set.sourceName = data.sourceName;
modifier.$set.sourceUrl = data.sourceUrl;
}

}
}
return modifier;
}
addCallback('posts.edit.sync', updateMediaOnEdit);
Edit on GitHub