 [ ← blog / drupal ](/) Apr 30, 2021  ·  \#drupal  ·  5 min read 

# Adding CodePen oEmbeds to your Drupal site



       ![oEmbed for CodePen code](/sites/default/files/styles/homepage_/public/2021-04/Screen%20Shot%202021-04-30%20at%2012.40.44%20AM.png?itok=DmmZnITy) 

 

I feel that whenever I attempt something with code, nothing ever just works. There's some bug or some roadblock that has to be overcome. I manage to find **something** that goes awry. Apparently, that is the case with embedding CodePen pens via oEmbed today!

Drupal 8.6.0 [added oEmbed support for media](https://www.drupal.org/node/2966029)! Out of the box, only remote video providers Vimeo and YouTube are supported. But a quick hook implementation exposes more providers. The providers are based on a repository provided by the [oEmbed](https://oembed.com/) website. The repository is here: <https://oembed.com/providers.json>

So I tried to add CodePen. Here's my snippet of code that I added to my module so that it would be available as a source for my media type:

```php
/**
 * Implements hook_media_source_info_alter().
 */
function mglaman_dev_media_source_info_alter(array &$sources) {
  $sources['oembed:codepen'] = [
    'id' => 'codepen',
    'label' => new TranslatableMarkup('CodePen'),
    'description' => new TranslatableMarkup('Embed a CodePen.'),
    'allowed_field_types' => ['string'],
    'default_thumbnail_filename' => 'no-thumbnail.png',
    'providers' => ['Codepen'],
    'class' => 'Drupal\media\Plugin\media\Source\OEmbed',
    'forms' => [
      'media_library_add' => OEmbedForm::class
    ],
    'provider' => 'mglaman_dev',
  ];
}
```

Great, off to the races! Naaaaaah. Not so much. I kept getting errors that the URL was invalid and a resource couldn't be fetched. So, I popped on Xdebug to see what was going on.

This is the entry for CodePen from the oEmbed repository:

```
  {
    "provider_name": "Codepen",
    "provider_url": "https://codepen.io",
    "endpoints": [
      {
        "schemes": [
          "http://codepen.io/*",
          "https://codepen.io/*"
        ],
        "url": "https://codepen.io/api/oembed"
      }
    ]
  },
```

Here's the matching blog post where CodePen announced oEmbed support: <https://blog.codepen.io/documentation/oembed/>. Their embed format is the following:

```
https://codepen.io/api/oembed?format=json&url=URL-TO-PEN-HERE
```

The oEmbed repository is missing one feature: defining additional query parameters. The CodePen oEmbed **requires the format** query parameter. Even though no other value is supported (like XML or YAML).

Given the CodePen `https://codepen.io/mglaman/pen/oNBRMeW`, Drupal ends up generating the following URL:

```
https://codepen.io/api/oembed/?url=https://codepen.io/mglaman/pen/oNBRMeW
```

And that returns a 404 because there is no format query parameter 👎🏻. Luckily, there is a hook to alter an oEmbed resource URL to make modifications just like these: `hook_oembed_resource_url_alter()`.

Here's my hook, and we're off to the races! A valid URL! Woohoo!

```
/**
 * Implements hook_oembed_resource_url_alter().
 */
function mglaman_dev_oembed_resource_url_alter(array &$parsed_url, \Drupal\media\OEmbed\Provider $provider) {
  if ($provider->getName() === 'Codepen') {
    $parsed_url['query']['format'] = 'json';
  }
}
```

And, once again. I'm smacked with a brick wall and an error. The provider cannot be found.

But. Wait? CodePen is in the provider repository. I was able to assemble the URL. What in the world? Well, let's look at the results of the full oEmbed URL: [https://codepen.io/api/oembed/?url=https://codepen.io/mglaman/pen/oNBRM…](https://codepen.io/api/oembed/?url=https://codepen.io/mglaman/pen/oNBRMeW&format=json)

```json
{
  "success": true,
  "type": "rich",
  "version": "1.0",
  "provider_name": "CodePen",
  "provider_url": "https://codepen.io",
  "title": "Locale formatting of time elements",
  "author_name": "Matt Glaman",
  "author_url": "https://codepen.io/mglaman",
  "height": "300",
  "width": "800",
  "thumbnail_width": "384",
  "thumbnail_height": "225",
  "thumbnail_url": "https://assets.codepen.io/42103/internal/screenshots/pens/oNBRMeW.default.png?fit=cover&amp;format=auto&amp;ha=false&amp;height=360&amp;quality=75&amp;v=2&amp;version=1619715151&amp;width=640",
  "html": "<iframe id=\"cp_embed_oNBRMeW\" src=\"https://codepen.io/mglaman/embed/preview/oNBRMeW?default-tabs=html%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=oNBRMeW\" title=\"Locale formatting of time elements\" scrolling=\"no\" frameborder=\"0\" height=\"300\" allowtransparency=\"true\" class=\"cp_embed_iframe\" style=\"width: 100%; overflow: hidden;\"></iframe>"
}
```

Notice the `provider_name` value? It's **CodePen**. The oEmbed resource repository has it as **Codepen**. Drupal cannot find the appropriate provider because the names mismatch. **This is a good thing**. It's a security measure. oEmbed is actually pretty dangerous as you're allowing a third-party website to embed random HTML.

To fix this, I have opened an issue and a pull request against the oEmbed repository

- <https://github.com/iamcal/oembed/issues/542>
- <https://github.com/iamcal/oembed/pull/543>

This will fix the oEmbed provider repository. However, I don't want to wait for this to be merged to have the ability to embed a CodePen item into my site. There must be a way!

There isn't. There are no hooks to handle modifying this response.

But. You can decorate the `media.oembed.provider_repository` service to provide a workaround!

---

***UPDATE!*** dpi has made me aware of the [oEmbed Providers](https://www.drupal.org/project/oembed_providers) module which allows you to customize the providers repository via a user interface. This way you do not need to write a decorated service. And maybe it would fix the format query parameter.

> [](https://twitter.com/khromium/statuses/1388141708462858241)



 

---

Here's my service definition:

```
services:
  mglaman_dev.oembed.provider_repository:
    class: Drupal\mglaman_dev\DecoratedProviderRepository
    decorates: media.oembed.provider_repository
    parent: media.oembed.provider_repository

```

Here's my decorated class, with built-in backward compatibility in case my pull request gets merged.

```
<?php declare(strict_types=1);

namespace Drupal\mglaman_dev;

use Drupal\media\OEmbed\ProviderRepository;

final class DecoratedProviderRepository extends ProviderRepository {

  public function get($provider_name) {
    if ($provider_name === 'CodePen') {
      try {
        return parent::get($provider_name);
      }
      catch (\InvalidArgumentException $e) {
        return parent::get('Codepen');
      }
    }
    return parent::get($provider_name);
  }

}

```

***AND IT WORKS!***

If you think I should contribute this to a **media\_codepen** module, let me know and I will.

  

  

  ![](/themes/custom/mglaman/images/headshot.webp)Thanks for reading

I write about Drupal, PHP, and the quiet infrastructure behind large sites — caching, config, and testing. New posts land every week or two.

 [Subscribe via RSS →](/rss.xml) [About me →](/about-me) 

 



 

  [← Older

Formatting time elements to match the current user's locale

 ](/blog/formatting-time-elements-match-current-users-locale) [Newer →

Hack and Play – a new weekly live stream session

 ](/blog/hack-and-play-new-weekly-live-stream-session)