Index: src/bp-activity/bp-activity-embeds.php
new file mode 100644
===================================================================
--- /dev/null
+++ src/bp-activity/bp-activity-embeds.php
@@ -0,0 +1,288 @@
+<?php
+/**
+ * Functions related to embedding single activity items externally.
+ *
+ * Relies on WordPress 4.4.
+ *
+ * @since 2.5.0
+ *
+ * @package BuddyPress
+ * @subpackage ActivityEmbeds
+ */
+
+// Exit if accessed directly.
+defined( 'ABSPATH' ) || exit;
+
+/**
+ * Register oEmbed provider on BuddyPress pages.
+ *
+ * This allows single activity items to be embedded.  WP's TinyMCE doesn't
+ * require this somehow, which is why we only do this on BuddyPress pages.
+ *
+ * @since 2.5.0
+ *
+ * @todo Fix up issues with javascript not firing to hide the fallback <blockquote>
+ */
+function bp_activity_embed_add_oembed_provider() {
+	// Only register our provider on BuddyPress pages.
+	if ( false === is_buddypress() ) {
+		return;
+	}
+
+	if ( bp_core_enable_root_profiles() ) {
+		$domain = bp_get_root_domain();
+	} else {
+		$domain = bp_get_members_directory_permalink();
+	}
+
+	wp_oembed_add_provider( $domain . '*/activity/*', get_oembed_endpoint_url() );
+}
+add_action( 'bp_init', 'bp_activity_embed_add_oembed_provider' );
+
+/**
+ * Use our custom embed template for activity items.
+ *
+ * @since 2.5.0
+ *
+ * @param  string $retval Current embed template
+ * @return string
+ */
+function bp_activity_embed_filter_template( $retval ) {
+	if ( ! bp_is_single_activity() ) {
+		return $retval;
+	}
+
+	// Embed template hierarchy!
+	return bp_locate_template( array(
+		'embeds/template-single-activity.php',
+		'embeds/template.php'
+	) );
+}
+add_filter( 'embed_template', 'bp_activity_embed_filter_template' );
+
+/**
+ * Inject activity content into the embed template.
+ *
+ * @since 2.5.0
+ */
+function bp_activity_embed_inject_content() {
+	if ( ! bp_is_single_activity() ) {
+		return;
+	}
+
+	bp_get_template_part( 'embeds/activity' );
+}
+add_action( 'embed_content', 'bp_activity_embed_inject_content' );
+
+/**
+ * Adds oEmbed discovery links on single activity pages.
+ *
+ * @since 2.5.0
+ *
+ * @param  string $retval Current discovery links.
+ * @return string
+ */
+function bp_activity_embed_oembed_discovery_links( $retval ) {
+	if ( ! bp_is_single_activity() ) {
+		return $retval;
+	}
+
+	$permalink = bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_current_action() . '/';
+
+	$retval = '<link rel="alternate" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( $permalink ) ) . '" />' . "\n";
+
+	if ( class_exists( 'SimpleXMLElement' ) ) {
+		$retval .= '<link rel="alternate" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( $permalink, 'xml' ) ) . '" />' . "\n";
+	}
+
+	return $retval;
+}
+add_filter( 'oembed_discovery_links', 'bp_activity_embed_oembed_discovery_links' );
+
+/**
+ * Filter the oEmbed post ID.
+ *
+ * WP needs a real WordPress post otherwise oEmbed will fail.  So here, we
+ * pass the Members Directory page ID as a dummy, while adding some markers
+ * that we will use to filter other parts of oEmbed so activity embedding will
+ * work.
+ *
+ * @since 2.5.0
+ *
+ * @param  int    $retval Current post ID
+ * @param  string $url Current embed URL
+ * @return int
+ */
+function bp_activity_embed_filter_oembed_request_post_id( $retval, $url ) {
+	// Check the URL to see if this is a single activity URL.
+	// @todo Do checks for BP root domain
+	if ( 0 !== strpos( $url, bp_get_members_directory_permalink() ) ) {
+		return $retval;
+	}
+
+	// Check for activity slug
+	if ( false === strpos( $url, '/' . bp_get_activity_slug() . '/' ) ) {
+		return $retval;
+	}
+
+	$url = trim( untrailingslashit( $url ) );
+
+	// Grab the activity ID
+	$activity_id = (int) substr(
+		$url,
+		strrpos( $url, '/' ) + 1
+	);
+	if ( empty( $activity_id ) ) {
+		return $retval;
+	}
+
+	// Check if activity item still exists.
+	$activity = new BP_Activity_Activity( $activity_id );
+	if ( empty( $activity->component ) ) {
+		return $retval;
+	}
+
+	// Add markers to tell that we're embedding a single activity
+	buddypress()->activity->embedurl_in_progress = $url;
+	buddypress()->activity->embedid_in_progress  = $activity_id;
+
+	// Bypass explicit post check by passing members directory page ID
+	$page_ids = bp_core_get_directory_page_ids();
+	return $page_ids['members'];
+}
+add_filter( 'oembed_request_post_id', 'bp_activity_embed_filter_oembed_request_post_id', 10, 2 );
+
+/**
+ * Pass our BuddyPress activity permalink for embedding.
+ *
+ * @since 2.5.0
+ *
+ * @see bp_activity_oembed_request_post_id()
+ *
+ * @param  string $retval Current embed URL
+ * @return string
+ */
+function bp_activity_embed_filter_post_embed_url( $retval ) {
+	if ( false === isset( buddypress()->activity->embedurl_in_progress ) && ! bp_is_single_activity() ) {
+		return $retval;
+	}
+
+	$url = bp_is_single_activity() ? bp_displayed_user_domain() . bp_get_activity_slug() . '/' . bp_current_action() . '/' : buddypress()->activity->embedurl_in_progress;
+	$url = trailingslashit( $url );
+
+	// This is for the 'WordPress Embed' block
+	// @see bp_activity_embed_comments_button()
+	if ( 'the_permalink' !== current_filter() ) {
+		$url = add_query_arg( 'embed', 'true', trailingslashit( $url ) );
+	}
+
+	return $url;
+}
+add_filter( 'post_embed_url', 'bp_activity_embed_filter_post_embed_url' );
+
+/**
+ * Filter the oEmbed response data to reference our activity content.
+ *
+ * @since 2.5.0
+ *
+ * @param  array $retval Current response data
+ * @return array
+ */
+function bp_activity_embed_filter_oembed_response_data( $retval ) {
+	if ( false === isset( buddypress()->activity->embedurl_in_progress ) ) {
+		return $retval;
+	}
+
+	$activity = new BP_Activity_Activity( buddypress()->activity->embedid_in_progress );
+
+	$retval['title'] = __( 'Activity', 'buddypress' );
+	$retval['author_url'] = bp_core_get_user_domain( $activity->user_id );
+
+	return $retval;
+}
+add_filter( 'oembed_response_data', 'bp_activity_embed_filter_oembed_response_data', 20 );
+
+/**
+ * Filter the embed HTML for default oEmbed fallback HTML.
+ *
+ * @param  string $retval Current embed HTML
+ * @return string
+ */
+function bp_activity_embed_filter_html( $retval ) {
+	if ( false === isset( buddypress()->activity->embedurl_in_progress ) && ! bp_is_single_activity() ) {
+		return $retval;
+	}
+
+	// Change 'Embedded WordPress Post' to 'Embedded Activity Item'
+	$retval = str_replace( __( 'Embedded WordPress Post' ), __( 'Embedded Activity Item', 'buddypress' ), $retval );
+
+	// Remove default <blockquote>
+	$retval = substr( $retval, strpos( $retval, '</blockquote>' ) + 13 );
+
+	// Set up new <blockquote>
+	$activity_id = bp_is_single_activity() ? bp_current_action() : buddypress()->activity->embedid_in_progress;
+	$activity    = new BP_Activity_Activity( $activity_id );
+	$mentionname = bp_activity_do_mentions() ? ' (@' . bp_activity_get_user_mentionname( $activity->user_id ) . ')' : '';
+	$date        = date_i18n( get_option( 'date_format' ), strtotime( $activity->date_recorded ) );
+
+	// 'wp-embedded-content' CSS class is necessary due to how the embed JS works.
+	$blockquote = sprintf( '<blockquote class="wp-embedded-content bp-activity-item">%1$s%2$s %3$s</blockquote>',
+		apply_filters( 'bp_get_activity_content_body', $activity->content ),
+		'- ' . bp_core_get_user_displayname( $activity->user_id ) . $mentionname,
+		'<a href="' . esc_url( bp_activity_get_permalink( $activity_id ) ) . '">' . $date . '</a>'
+	);
+
+	/**
+	 * Filters the fallback HTML used when embedding a BP activity item.
+	 *
+	 * @since 2.5.0
+	 *
+	 * @param string               $blockquote Current fallback HTML
+	 * @param BP_Activity_Activity $activity   Activity object
+	 */
+	$blockquote = apply_filters( 'bp_activity_embed_fallback_html', $blockquote, $activity );
+
+	// Add our custom <blockquote>
+	return $blockquote . $retval;
+}
+add_filter( 'embed_html', 'bp_activity_embed_filter_html' );
+
+/**
+ * Prints the markup for the activity embed comments button.
+ *
+ * @since 2.5.0
+ */
+function bp_activity_embed_comments_button() {
+	if ( ! bp_is_single_activity() ) {
+		return;
+	}
+
+	// Make sure our custom permalink shows up in the 'WordPress Embed' block.
+	add_filter( 'the_permalink', 'bp_activity_embed_filter_post_embed_url' );
+
+	// Only show comment bubble if we have some activity comments.
+	$count = bp_activity_get_comment_count();
+	if ( empty( $count ) ) {
+		return;
+	}
+?>
+
+	<div class="wp-embed-comments">
+		<a href="<?php bp_activity_thread_permalink(); ?>">
+			<span class="dashicons dashicons-admin-comments"></span>
+			<?php
+			printf(
+				_n(
+					'%s <span class="screen-reader-text">Comment</span>',
+					'%s <span class="screen-reader-text">Comments</span>',
+					$count
+				),
+				number_format_i18n( $count )
+			);
+			?>
+		</a>
+	</div>
+
+<?php
+}
+add_action( 'embed_content_meta', 'bp_activity_embed_comments_button', 5 );
\ No newline at end of file
Index: src/bp-activity/bp-activity-loader.php
===================================================================
--- src/bp-activity/bp-activity-loader.php
+++ src/bp-activity/bp-activity-loader.php
@@ -31,6 +31,7 @@
 			array(
 				'adminbar_myaccount_order' => 10,
 				'search_query_arg' => 'activity_search',
+				'features' => array( 'embeds' )
 			)
 		);
 	}
@@ -67,6 +68,12 @@
 			$includes[] = 'akismet';
 		}
 
+		// Embeds - only applicable for WP 4.4+
+		if ( bp_get_major_wp_version() >= 4.4 && bp_is_active( $this->id, 'embeds' ) ) {
+			$includes[] = 'embeds';
+		}
+
+		// Admin-specific
 		if ( is_admin() ) {
 			$includes[] = 'admin';
 		}
Index: src/bp-templates/bp-legacy/buddypress/embeds/activity.php
new file mode 100644
===================================================================
--- /dev/null
+++ src/bp-templates/bp-legacy/buddypress/embeds/activity.php
@@ -0,0 +1,15 @@
+
+		<?php if ( bp_has_activities( 'display_comments=threaded&show_hidden=true&include=' . bp_current_action() ) ) : ?>
+
+			<?php while ( bp_activities() ) : bp_the_activity(); ?>
+				<div class="wp-embed-excerpt"><?php bp_activity_content_body(); ?></div>
+
+				<p><a href="<?php bp_activity_thread_permalink(); ?>"><?php echo date_i18n( get_option( 'time_format' ) . ' - ' . get_option( 'date_format' ), strtotime( bp_get_activity_date_recorded() ) ); ?></a></p>
+			<?php endwhile; ?>
+
+		<?php else : ?>
+
+			<?php bp_get_template_part( 'embeds/not-found' ); ?>
+
+		<?php endif; ?>
+
Index: src/bp-templates/bp-legacy/buddypress/embeds/css.php
new file mode 100644
===================================================================
--- /dev/null
+++ src/bp-templates/bp-legacy/buddypress/embeds/css.php
@@ -0,0 +1,26 @@
+<style type="text/css">
+#wp-embed-header:after {
+	clear: both;
+	content: "";
+	display: table;
+	margin-bottom: 1em;
+}
+
+.wp-embed-avatar {
+	float: left;
+	margin: 0 .75em 0 0;
+}
+
+p.wp-embed-heading {
+	font-size: 16px;
+	margin-bottom: 0;
+}
+
+.wp-embed-excerpt {
+	margin-bottom: .5em;
+}
+
+.wp-embed-footer {
+	margin-top: 20px;
+}
+</style>
\ No newline at end of file
Index: src/bp-templates/bp-legacy/buddypress/embeds/footer.php
new file mode 100644
===================================================================
--- /dev/null
+++ src/bp-templates/bp-legacy/buddypress/embeds/footer.php
@@ -0,0 +1,33 @@
+			<div class="wp-embed-footer">
+				<div class="wp-embed-site-title">
+					<?php
+					$site_title = sprintf(
+						'<a href="%s"><img src="%s" srcset="%s 2x" width="32" height="32" alt="" class="wp-embed-site-icon"/><span>%s</span></a>',
+						esc_url( home_url() ),
+						esc_url( get_site_icon_url( 32, admin_url( 'images/w-logo-blue.png' ) ) ),
+						esc_url( get_site_icon_url( 64, admin_url( 'images/w-logo-blue.png' ) ) ),
+						esc_html( get_bloginfo( 'name' ) )
+					);
+
+					/**
+					 * Filter the site title HTML in the embed footer.
+					 *
+					 * @since 4.4.0
+					 *
+					 * @param string $site_title The site title HTML.
+					 */
+					echo apply_filters( 'embed_site_title_html', $site_title );
+					?>
+				</div>
+
+				<div class="wp-embed-meta">
+					<?php
+					/**
+					 * Print additional meta content in the embed template.
+					 *
+					 * @since 4.4.0
+					 */
+					do_action( 'embed_content_meta');
+					?>
+				</div>
+			</div>
\ No newline at end of file
Index: src/bp-templates/bp-legacy/buddypress/embeds/header.php
new file mode 100644
===================================================================
--- /dev/null
+++ src/bp-templates/bp-legacy/buddypress/embeds/header.php
@@ -0,0 +1,18 @@
+
+		<div id="wp-embed-header">
+			<div class="wp-embed-avatar">
+				<a href="<?php bp_displayed_user_link(); ?>">
+					<?php bp_displayed_user_avatar( 'type=thumb&width=36&height=36' ); ?>
+				</a>
+			</div>
+
+			<p class="wp-embed-heading">
+				<a href="<?php bp_displayed_user_link(); ?>">
+					<?php bp_displayed_user_fullname(); ?>
+				</a>
+			</p>
+
+			<?php if ( bp_is_active( 'activity' ) && bp_activity_do_mentions() ) : ?>
+				<p class="wp-embed-mentionname">@<?php bp_displayed_user_mentionname(); ?></p>
+			<?php endif; ?>
+		</div>
Index: src/bp-templates/bp-legacy/buddypress/embeds/template.php
new file mode 100644
===================================================================
--- /dev/null
+++ src/bp-templates/bp-legacy/buddypress/embeds/template.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Generic embed template used by BuddyPress.
+ *
+ * When a BuddyPress item is embedded in an iframe, this file is used to
+ * create the output.
+ *
+ * This is a modified version of the bundled WordPress embed template
+ * included in WordPress 4.4+.
+ *
+ * @since 2.5.0
+ *
+ * @package BuddyPress
+ * @subpackage Embeds
+ */
+
+if ( ! headers_sent() ) {
+	header( 'X-WP-embed: true' );
+}
+
+?>
+<!DOCTYPE html>
+<html <?php language_attributes(); ?> class="no-js">
+<head>
+	<title><?php echo wp_get_document_title(); ?></title>
+	<meta http-equiv="X-UA-Compatible" content="IE=edge">
+	<base target="_top" />
+	<?php
+	/** This action is documented in wp-includes/embed-template.php */
+	do_action( 'embed_head' );
+
+	// This is used by r-a-y for testing purposes at the moment.
+	bp_get_template_part( 'embeds/css' );
+	?>
+</head>
+<body <?php body_class(); ?>>
+<div <?php post_class( 'wp-embed' ); ?>>
+<?php
+bp_get_template_part( 'embeds/header', bp_current_component() );
+
+/** This action is documented in wp-includes/embed-template.php */
+do_action( 'embed_content' );
+
+bp_get_template_part( 'embeds/footer', bp_current_component() );
+?>
+
+</div>
+
+<?php
+/** This action is documented in wp-includes/embed-template.php */
+do_action( 'embed_footer' );
+?>
+</body>
+</html>
\ No newline at end of file
